• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 // A Disassembler object is used to disassemble a block of code instruction by
29 // instruction. The default implementation of the NameConverter object can be
30 // overriden to modify register names or to do symbol lookup on addresses.
31 //
32 // The example below will disassemble a block of code and print it to stdout.
33 //
34 //   NameConverter converter;
35 //   Disassembler d(converter);
36 //   for (byte* pc = begin; pc < end;) {
37 //     char buffer[128];
38 //     buffer[0] = '\0';
39 //     byte* prev_pc = pc;
40 //     pc += d.InstructionDecode(buffer, sizeof buffer, pc);
41 //     printf("%p    %08x      %s\n",
42 //            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
43 //   }
44 //
45 // The Disassembler class also has a convenience method to disassemble a block
46 // of code into a FILE*, meaning that the above functionality could also be
47 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
48 
49 
50 #include <assert.h>
51 #include <stdio.h>
52 #include <stdarg.h>
53 #include <string.h>
54 #ifndef WIN32
55 #include <stdint.h>
56 #endif
57 
58 #include "v8.h"
59 
60 #include "constants-arm.h"
61 #include "disasm.h"
62 #include "macro-assembler.h"
63 #include "platform.h"
64 
65 
66 namespace assembler {
67 namespace arm {
68 
69 namespace v8i = v8::internal;
70 
71 
72 //------------------------------------------------------------------------------
73 
74 // Decoder decodes and disassembles instructions into an output buffer.
75 // It uses the converter to convert register names and call destinations into
76 // more informative description.
77 class Decoder {
78  public:
Decoder(const disasm::NameConverter & converter,v8::internal::Vector<char> out_buffer)79   Decoder(const disasm::NameConverter& converter,
80           v8::internal::Vector<char> out_buffer)
81     : converter_(converter),
82       out_buffer_(out_buffer),
83       out_buffer_pos_(0) {
84     out_buffer_[out_buffer_pos_] = '\0';
85   }
86 
~Decoder()87   ~Decoder() {}
88 
89   // Writes one disassembled instruction into 'buffer' (0-terminated).
90   // Returns the length of the disassembled machine instruction in bytes.
91   int InstructionDecode(byte* instruction);
92 
93  private:
94   // Bottleneck functions to print into the out_buffer.
95   void PrintChar(const char ch);
96   void Print(const char* str);
97 
98   // Printing of common values.
99   void PrintRegister(int reg);
100   void PrintSRegister(int reg);
101   void PrintDRegister(int reg);
102   int FormatVFPRegister(Instr* instr, const char* format);
103   int FormatVFPinstruction(Instr* instr, const char* format);
104   void PrintCondition(Instr* instr);
105   void PrintShiftRm(Instr* instr);
106   void PrintShiftImm(Instr* instr);
107   void PrintPU(Instr* instr);
108   void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
109 
110   // Handle formatting of instructions and their options.
111   int FormatRegister(Instr* instr, const char* option);
112   int FormatOption(Instr* instr, const char* option);
113   void Format(Instr* instr, const char* format);
114   void Unknown(Instr* instr);
115 
116   // Each of these functions decodes one particular instruction type, a 3-bit
117   // field in the instruction encoding.
118   // Types 0 and 1 are combined as they are largely the same except for the way
119   // they interpret the shifter operand.
120   void DecodeType01(Instr* instr);
121   void DecodeType2(Instr* instr);
122   void DecodeType3(Instr* instr);
123   void DecodeType4(Instr* instr);
124   void DecodeType5(Instr* instr);
125   void DecodeType6(Instr* instr);
126   void DecodeType7(Instr* instr);
127   void DecodeUnconditional(Instr* instr);
128   // For VFP support.
129   void DecodeTypeVFP(Instr* instr);
130   void DecodeType6CoprocessorIns(Instr* instr);
131 
132 
133   const disasm::NameConverter& converter_;
134   v8::internal::Vector<char> out_buffer_;
135   int out_buffer_pos_;
136 
137   DISALLOW_COPY_AND_ASSIGN(Decoder);
138 };
139 
140 
141 // Support for assertions in the Decoder formatting functions.
142 #define STRING_STARTS_WITH(string, compare_string) \
143   (strncmp(string, compare_string, strlen(compare_string)) == 0)
144 
145 
146 // Append the ch to the output buffer.
PrintChar(const char ch)147 void Decoder::PrintChar(const char ch) {
148   out_buffer_[out_buffer_pos_++] = ch;
149 }
150 
151 
152 // Append the str to the output buffer.
Print(const char * str)153 void Decoder::Print(const char* str) {
154   char cur = *str++;
155   while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
156     PrintChar(cur);
157     cur = *str++;
158   }
159   out_buffer_[out_buffer_pos_] = 0;
160 }
161 
162 
163 // These condition names are defined in a way to match the native disassembler
164 // formatting. See for example the command "objdump -d <binary file>".
165 static const char* cond_names[max_condition] = {
166   "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
167   "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
168 };
169 
170 
171 // Print the condition guarding the instruction.
PrintCondition(Instr * instr)172 void Decoder::PrintCondition(Instr* instr) {
173   Print(cond_names[instr->ConditionField()]);
174 }
175 
176 
177 // Print the register name according to the active name converter.
PrintRegister(int reg)178 void Decoder::PrintRegister(int reg) {
179   Print(converter_.NameOfCPURegister(reg));
180 }
181 
182 // Print the VFP S register name according to the active name converter.
PrintSRegister(int reg)183 void Decoder::PrintSRegister(int reg) {
184   Print(assembler::arm::VFPRegisters::Name(reg));
185 }
186 
187 // Print the  VFP D register name according to the active name converter.
PrintDRegister(int reg)188 void Decoder::PrintDRegister(int reg) {
189   Print(assembler::arm::VFPRegisters::Name(reg + 32));
190 }
191 
192 
193 // These shift names are defined in a way to match the native disassembler
194 // formatting. See for example the command "objdump -d <binary file>".
195 static const char* shift_names[max_shift] = {
196   "lsl", "lsr", "asr", "ror"
197 };
198 
199 
200 // Print the register shift operands for the instruction. Generally used for
201 // data processing instructions.
PrintShiftRm(Instr * instr)202 void Decoder::PrintShiftRm(Instr* instr) {
203   Shift shift = instr->ShiftField();
204   int shift_amount = instr->ShiftAmountField();
205   int rm = instr->RmField();
206 
207   PrintRegister(rm);
208 
209   if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
210     // Special case for using rm only.
211     return;
212   }
213   if (instr->RegShiftField() == 0) {
214     // by immediate
215     if ((shift == ROR) && (shift_amount == 0)) {
216       Print(", RRX");
217       return;
218     } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
219       shift_amount = 32;
220     }
221     out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
222                                          ", %s #%d",
223                                          shift_names[shift], shift_amount);
224   } else {
225     // by register
226     int rs = instr->RsField();
227     out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
228                                          ", %s ", shift_names[shift]);
229     PrintRegister(rs);
230   }
231 }
232 
233 
234 // Print the immediate operand for the instruction. Generally used for data
235 // processing instructions.
PrintShiftImm(Instr * instr)236 void Decoder::PrintShiftImm(Instr* instr) {
237   int rotate = instr->RotateField() * 2;
238   int immed8 = instr->Immed8Field();
239   int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
240   out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
241                                        "#%d", imm);
242 }
243 
244 
245 // Print PU formatting to reduce complexity of FormatOption.
PrintPU(Instr * instr)246 void Decoder::PrintPU(Instr* instr) {
247   switch (instr->PUField()) {
248     case 0: {
249       Print("da");
250       break;
251     }
252     case 1: {
253       Print("ia");
254       break;
255     }
256     case 2: {
257       Print("db");
258       break;
259     }
260     case 3: {
261       Print("ib");
262       break;
263     }
264     default: {
265       UNREACHABLE();
266       break;
267     }
268   }
269 }
270 
271 
272 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
273 // the FormatOption method.
PrintSoftwareInterrupt(SoftwareInterruptCodes swi)274 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
275   switch (swi) {
276     case call_rt_redirected:
277       Print("call_rt_redirected");
278       return;
279     case break_point:
280       Print("break_point");
281       return;
282     default:
283       out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
284                                            "%d",
285                                            swi);
286       return;
287   }
288 }
289 
290 
291 // Handle all register based formatting in this function to reduce the
292 // complexity of FormatOption.
FormatRegister(Instr * instr,const char * format)293 int Decoder::FormatRegister(Instr* instr, const char* format) {
294   ASSERT(format[0] == 'r');
295   if (format[1] == 'n') {  // 'rn: Rn register
296     int reg = instr->RnField();
297     PrintRegister(reg);
298     return 2;
299   } else if (format[1] == 'd') {  // 'rd: Rd register
300     int reg = instr->RdField();
301     PrintRegister(reg);
302     return 2;
303   } else if (format[1] == 's') {  // 'rs: Rs register
304     int reg = instr->RsField();
305     PrintRegister(reg);
306     return 2;
307   } else if (format[1] == 'm') {  // 'rm: Rm register
308     int reg = instr->RmField();
309     PrintRegister(reg);
310     return 2;
311   } else if (format[1] == 't') {  // 'rt: Rt register
312     int reg = instr->RtField();
313     PrintRegister(reg);
314     return 2;
315   } else if (format[1] == 'l') {
316     // 'rlist: register list for load and store multiple instructions
317     ASSERT(STRING_STARTS_WITH(format, "rlist"));
318     int rlist = instr->RlistField();
319     int reg = 0;
320     Print("{");
321     // Print register list in ascending order, by scanning the bit mask.
322     while (rlist != 0) {
323       if ((rlist & 1) != 0) {
324         PrintRegister(reg);
325         if ((rlist >> 1) != 0) {
326           Print(", ");
327         }
328       }
329       reg++;
330       rlist >>= 1;
331     }
332     Print("}");
333     return 5;
334   }
335   UNREACHABLE();
336   return -1;
337 }
338 
339 
340 // Handle all VFP register based formatting in this function to reduce the
341 // complexity of FormatOption.
FormatVFPRegister(Instr * instr,const char * format)342 int Decoder::FormatVFPRegister(Instr* instr, const char* format) {
343   ASSERT((format[0] == 'S') || (format[0] == 'D'));
344 
345   if (format[1] == 'n') {
346     int reg = instr->VnField();
347     if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField()));
348     if (format[0] == 'D') PrintDRegister(reg);
349     return 2;
350   } else if (format[1] == 'm') {
351     int reg = instr->VmField();
352     if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->MField()));
353     if (format[0] == 'D') PrintDRegister(reg);
354     return 2;
355   } else if (format[1] == 'd') {
356     int reg = instr->VdField();
357     if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->DField()));
358     if (format[0] == 'D') PrintDRegister(reg);
359     return 2;
360   }
361 
362   UNREACHABLE();
363   return -1;
364 }
365 
366 
FormatVFPinstruction(Instr * instr,const char * format)367 int Decoder::FormatVFPinstruction(Instr* instr, const char* format) {
368     Print(format);
369     return 0;
370 }
371 
372 
373 // FormatOption takes a formatting string and interprets it based on
374 // the current instructions. The format string points to the first
375 // character of the option string (the option escape has already been
376 // consumed by the caller.)  FormatOption returns the number of
377 // characters that were consumed from the formatting string.
FormatOption(Instr * instr,const char * format)378 int Decoder::FormatOption(Instr* instr, const char* format) {
379   switch (format[0]) {
380     case 'a': {  // 'a: accumulate multiplies
381       if (instr->Bit(21) == 0) {
382         Print("ul");
383       } else {
384         Print("la");
385       }
386       return 1;
387     }
388     case 'b': {  // 'b: byte loads or stores
389       if (instr->HasB()) {
390         Print("b");
391       }
392       return 1;
393     }
394     case 'c': {  // 'cond: conditional execution
395       ASSERT(STRING_STARTS_WITH(format, "cond"));
396       PrintCondition(instr);
397       return 4;
398     }
399     case 'h': {  // 'h: halfword operation for extra loads and stores
400       if (instr->HasH()) {
401         Print("h");
402       } else {
403         Print("b");
404       }
405       return 1;
406     }
407     case 'l': {  // 'l: branch and link
408       if (instr->HasLink()) {
409         Print("l");
410       }
411       return 1;
412     }
413     case 'm': {
414       if (format[1] == 'e') {  // 'memop: load/store instructions
415         ASSERT(STRING_STARTS_WITH(format, "memop"));
416         if (instr->HasL()) {
417           Print("ldr");
418         } else {
419           Print("str");
420         }
421         return 5;
422       }
423       // 'msg: for simulator break instructions
424       ASSERT(STRING_STARTS_WITH(format, "msg"));
425       byte* str =
426           reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
427       out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
428                                            "%s", converter_.NameInCode(str));
429       return 3;
430     }
431     case 'o': {
432       if ((format[3] == '1') && (format[4] == '2')) {
433         // 'off12: 12-bit offset for load and store instructions
434         ASSERT(STRING_STARTS_WITH(format, "off12"));
435         out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
436                                              "%d", instr->Offset12Field());
437         return 5;
438       } else if ((format[3] == '1') && (format[4] == '6')) {
439         ASSERT(STRING_STARTS_WITH(format, "off16to20"));
440         out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
441                                            "%d", instr->Bits(20, 16) +1);
442         return 9;
443       } else if (format[3] == '7') {
444         ASSERT(STRING_STARTS_WITH(format, "off7to11"));
445         out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
446                                             "%d", instr->ShiftAmountField());
447         return 8;
448       }
449       // 'off8: 8-bit offset for extra load and store instructions
450       ASSERT(STRING_STARTS_WITH(format, "off8"));
451       int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
452       out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
453                                            "%d", offs8);
454       return 4;
455     }
456     case 'p': {  // 'pu: P and U bits for load and store instructions
457       ASSERT(STRING_STARTS_WITH(format, "pu"));
458       PrintPU(instr);
459       return 2;
460     }
461     case 'r': {
462       return FormatRegister(instr, format);
463     }
464     case 's': {
465       if (format[1] == 'h') {  // 'shift_op or 'shift_rm
466         if (format[6] == 'o') {  // 'shift_op
467           ASSERT(STRING_STARTS_WITH(format, "shift_op"));
468           if (instr->TypeField() == 0) {
469             PrintShiftRm(instr);
470           } else {
471             ASSERT(instr->TypeField() == 1);
472             PrintShiftImm(instr);
473           }
474           return 8;
475         } else {  // 'shift_rm
476           ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
477           PrintShiftRm(instr);
478           return 8;
479         }
480       } else if (format[1] == 'w') {  // 'swi
481         ASSERT(STRING_STARTS_WITH(format, "swi"));
482         PrintSoftwareInterrupt(instr->SwiField());
483         return 3;
484       } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
485         ASSERT(STRING_STARTS_WITH(format, "sign"));
486         if (instr->HasSign()) {
487           Print("s");
488         }
489         return 4;
490       }
491       // 's: S field of data processing instructions
492       if (instr->HasS()) {
493         Print("s");
494       }
495       return 1;
496     }
497     case 't': {  // 'target: target of branch instructions
498       ASSERT(STRING_STARTS_WITH(format, "target"));
499       int off = (instr->SImmed24Field() << 2) + 8;
500       out_buffer_pos_ += v8i::OS::SNPrintF(
501           out_buffer_ + out_buffer_pos_,
502           "%+d -> %s",
503           off,
504           converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
505       return 6;
506     }
507     case 'u': {  // 'u: signed or unsigned multiplies
508       // The manual gets the meaning of bit 22 backwards in the multiply
509       // instruction overview on page A3.16.2.  The instructions that
510       // exist in u and s variants are the following:
511       // smull A4.1.87
512       // umull A4.1.129
513       // umlal A4.1.128
514       // smlal A4.1.76
515       // For these 0 means u and 1 means s.  As can be seen on their individual
516       // pages.  The other 18 mul instructions have the bit set or unset in
517       // arbitrary ways that are unrelated to the signedness of the instruction.
518       // None of these 18 instructions exist in both a 'u' and an 's' variant.
519 
520       if (instr->Bit(22) == 0) {
521         Print("u");
522       } else {
523         Print("s");
524       }
525       return 1;
526     }
527     case 'v': {
528       return FormatVFPinstruction(instr, format);
529     }
530     case 'S':
531     case 'D': {
532       return FormatVFPRegister(instr, format);
533     }
534     case 'w': {  // 'w: W field of load and store instructions
535       if (instr->HasW()) {
536         Print("!");
537       }
538       return 1;
539     }
540     default: {
541       UNREACHABLE();
542       break;
543     }
544   }
545   UNREACHABLE();
546   return -1;
547 }
548 
549 
550 // Format takes a formatting string for a whole instruction and prints it into
551 // the output buffer. All escaped options are handed to FormatOption to be
552 // parsed further.
Format(Instr * instr,const char * format)553 void Decoder::Format(Instr* instr, const char* format) {
554   char cur = *format++;
555   while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
556     if (cur == '\'') {  // Single quote is used as the formatting escape.
557       format += FormatOption(instr, format);
558     } else {
559       out_buffer_[out_buffer_pos_++] = cur;
560     }
561     cur = *format++;
562   }
563   out_buffer_[out_buffer_pos_]  = '\0';
564 }
565 
566 
567 // For currently unimplemented decodings the disassembler calls Unknown(instr)
568 // which will just print "unknown" of the instruction bits.
Unknown(Instr * instr)569 void Decoder::Unknown(Instr* instr) {
570   Format(instr, "unknown");
571 }
572 
573 
DecodeType01(Instr * instr)574 void Decoder::DecodeType01(Instr* instr) {
575   int type = instr->TypeField();
576   if ((type == 0) && instr->IsSpecialType0()) {
577     // multiply instruction or extra loads and stores
578     if (instr->Bits(7, 4) == 9) {
579       if (instr->Bit(24) == 0) {
580         // multiply instructions
581         if (instr->Bit(23) == 0) {
582           if (instr->Bit(21) == 0) {
583             // The MUL instruction description (A 4.1.33) refers to Rd as being
584             // the destination for the operation, but it confusingly uses the
585             // Rn field to encode it.
586             Format(instr, "mul'cond's 'rn, 'rm, 'rs");
587           } else {
588             // The MLA instruction description (A 4.1.28) refers to the order
589             // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
590             // Rn field to encode the Rd register and the Rd field to encode
591             // the Rn register.
592             Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
593           }
594         } else {
595           // The signed/long multiply instructions use the terms RdHi and RdLo
596           // when referring to the target registers. They are mapped to the Rn
597           // and Rd fields as follows:
598           // RdLo == Rd field
599           // RdHi == Rn field
600           // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
601           Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
602         }
603       } else {
604         Unknown(instr);  // not used by V8
605       }
606     } else {
607       // extra load/store instructions
608       switch (instr->PUField()) {
609         case 0: {
610           if (instr->Bit(22) == 0) {
611             Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
612           } else {
613             Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
614           }
615           break;
616         }
617         case 1: {
618           if (instr->Bit(22) == 0) {
619             Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
620           } else {
621             Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
622           }
623           break;
624         }
625         case 2: {
626           if (instr->Bit(22) == 0) {
627             Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
628           } else {
629             Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
630           }
631           break;
632         }
633         case 3: {
634           if (instr->Bit(22) == 0) {
635             Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
636           } else {
637             Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
638           }
639           break;
640         }
641         default: {
642           // The PU field is a 2-bit field.
643           UNREACHABLE();
644           break;
645         }
646       }
647       return;
648     }
649   } else {
650     switch (instr->OpcodeField()) {
651       case AND: {
652         Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
653         break;
654       }
655       case EOR: {
656         Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
657         break;
658       }
659       case SUB: {
660         Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
661         break;
662       }
663       case RSB: {
664         Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
665         break;
666       }
667       case ADD: {
668         Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
669         break;
670       }
671       case ADC: {
672         Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
673         break;
674       }
675       case SBC: {
676         Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
677         break;
678       }
679       case RSC: {
680         Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
681         break;
682       }
683       case TST: {
684         if (instr->HasS()) {
685           Format(instr, "tst'cond 'rn, 'shift_op");
686         } else {
687           Unknown(instr);  // not used by V8
688         }
689         break;
690       }
691       case TEQ: {
692         if (instr->HasS()) {
693           Format(instr, "teq'cond 'rn, 'shift_op");
694         } else {
695           switch (instr->Bits(7, 4)) {
696             case BX:
697               Format(instr, "bx'cond 'rm");
698               break;
699             case BLX:
700               Format(instr, "blx'cond 'rm");
701               break;
702             default:
703               Unknown(instr);  // not used by V8
704               break;
705           }
706         }
707         break;
708       }
709       case CMP: {
710         if (instr->HasS()) {
711           Format(instr, "cmp'cond 'rn, 'shift_op");
712         } else {
713           Unknown(instr);  // not used by V8
714         }
715         break;
716       }
717       case CMN: {
718         if (instr->HasS()) {
719           Format(instr, "cmn'cond 'rn, 'shift_op");
720         } else {
721           switch (instr->Bits(7, 4)) {
722             case CLZ:
723               Format(instr, "clz'cond 'rd, 'rm");
724               break;
725             default:
726               Unknown(instr);  // not used by V8
727               break;
728           }
729         }
730         break;
731       }
732       case ORR: {
733         Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
734         break;
735       }
736       case MOV: {
737         Format(instr, "mov'cond's 'rd, 'shift_op");
738         break;
739       }
740       case BIC: {
741         Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
742         break;
743       }
744       case MVN: {
745         Format(instr, "mvn'cond's 'rd, 'shift_op");
746         break;
747       }
748       default: {
749         // The Opcode field is a 4-bit field.
750         UNREACHABLE();
751         break;
752       }
753     }
754   }
755 }
756 
757 
DecodeType2(Instr * instr)758 void Decoder::DecodeType2(Instr* instr) {
759   switch (instr->PUField()) {
760     case 0: {
761       if (instr->HasW()) {
762         Unknown(instr);  // not used in V8
763       }
764       Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
765       break;
766     }
767     case 1: {
768       if (instr->HasW()) {
769         Unknown(instr);  // not used in V8
770       }
771       Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
772       break;
773     }
774     case 2: {
775       Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
776       break;
777     }
778     case 3: {
779       Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
780       break;
781     }
782     default: {
783       // The PU field is a 2-bit field.
784       UNREACHABLE();
785       break;
786     }
787   }
788 }
789 
790 
DecodeType3(Instr * instr)791 void Decoder::DecodeType3(Instr* instr) {
792   switch (instr->PUField()) {
793     case 0: {
794       ASSERT(!instr->HasW());
795       Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
796       break;
797     }
798     case 1: {
799       ASSERT(!instr->HasW());
800       Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
801       break;
802     }
803     case 2: {
804       Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
805       break;
806     }
807     case 3: {
808       if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
809         uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
810         uint32_t lsbit = static_cast<uint32_t>(instr->ShiftAmountField());
811         uint32_t msbit = widthminus1 + lsbit;
812         if (msbit <= 31) {
813           Format(instr, "ubfx'cond 'rd, 'rm, #'off7to11, #'off16to20");
814         } else {
815           UNREACHABLE();
816         }
817       } else {
818         Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
819       }
820       break;
821     }
822     default: {
823       // The PU field is a 2-bit field.
824       UNREACHABLE();
825       break;
826     }
827   }
828 }
829 
830 
DecodeType4(Instr * instr)831 void Decoder::DecodeType4(Instr* instr) {
832   ASSERT(instr->Bit(22) == 0);  // Privileged mode currently not supported.
833   if (instr->HasL()) {
834     Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
835   } else {
836     Format(instr, "stm'cond'pu 'rn'w, 'rlist");
837   }
838 }
839 
840 
DecodeType5(Instr * instr)841 void Decoder::DecodeType5(Instr* instr) {
842   Format(instr, "b'l'cond 'target");
843 }
844 
845 
DecodeType6(Instr * instr)846 void Decoder::DecodeType6(Instr* instr) {
847   DecodeType6CoprocessorIns(instr);
848 }
849 
850 
DecodeType7(Instr * instr)851 void Decoder::DecodeType7(Instr* instr) {
852   if (instr->Bit(24) == 1) {
853     Format(instr, "swi'cond 'swi");
854   } else {
855     DecodeTypeVFP(instr);
856   }
857 }
858 
DecodeUnconditional(Instr * instr)859 void Decoder::DecodeUnconditional(Instr* instr) {
860   if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) {
861     Format(instr, "'memop'h'pu 'rd, ");
862     bool immediate = instr->HasB();
863     switch (instr->PUField()) {
864       case 0: {
865         // Post index, negative.
866         if (instr->HasW()) {
867           Unknown(instr);
868           break;
869         }
870         if (immediate) {
871           Format(instr, "['rn], #-'imm12");
872         } else {
873           Format(instr, "['rn], -'rm");
874         }
875         break;
876       }
877       case 1: {
878         // Post index, positive.
879         if (instr->HasW()) {
880           Unknown(instr);
881           break;
882         }
883         if (immediate) {
884           Format(instr, "['rn], #+'imm12");
885         } else {
886           Format(instr, "['rn], +'rm");
887         }
888         break;
889       }
890       case 2: {
891         // Pre index or offset, negative.
892         if (immediate) {
893           Format(instr, "['rn, #-'imm12]'w");
894         } else {
895           Format(instr, "['rn, -'rm]'w");
896         }
897         break;
898       }
899       case 3: {
900         // Pre index or offset, positive.
901         if (immediate) {
902           Format(instr, "['rn, #+'imm12]'w");
903         } else {
904           Format(instr, "['rn, +'rm]'w");
905         }
906         break;
907       }
908       default: {
909         // The PU field is a 2-bit field.
910         UNREACHABLE();
911         break;
912       }
913     }
914     return;
915   }
916   Format(instr, "break 'msg");
917 }
918 
919 
920 // void Decoder::DecodeTypeVFP(Instr* instr)
921 // vmov: Sn = Rt
922 // vmov: Rt = Sn
923 // vcvt: Dd = Sm
924 // vcvt: Sd = Dm
925 // Dd = vadd(Dn, Dm)
926 // Dd = vsub(Dn, Dm)
927 // Dd = vmul(Dn, Dm)
928 // Dd = vdiv(Dn, Dm)
929 // vcmp(Dd, Dm)
930 // VMRS
DecodeTypeVFP(Instr * instr)931 void Decoder::DecodeTypeVFP(Instr* instr) {
932   ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
933 
934   if (instr->Bit(23) == 1) {
935     if ((instr->Bits(21, 19) == 0x7) &&
936         (instr->Bits(18, 16) == 0x5) &&
937         (instr->Bits(11, 9) == 0x5) &&
938         (instr->Bit(8) == 1) &&
939         (instr->Bit(6) == 1) &&
940         (instr->Bit(4) == 0)) {
941       Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
942     } else if ((instr->Bits(21, 19) == 0x7) &&
943                (instr->Bits(18, 16) == 0x0) &&
944                (instr->Bits(11, 9) == 0x5) &&
945                (instr->Bit(8) == 1) &&
946                (instr->Bit(7) == 1) &&
947                (instr->Bit(6) == 1) &&
948                (instr->Bit(4) == 0)) {
949       Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
950     } else if ((instr->Bit(21) == 0x0) &&
951                (instr->Bit(20) == 0x0) &&
952                (instr->Bits(11, 9) == 0x5) &&
953                (instr->Bit(8) == 1) &&
954                (instr->Bit(6) == 0) &&
955                (instr->Bit(4) == 0)) {
956         Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
957     } else if ((instr->Bits(21, 20) == 0x3) &&
958                (instr->Bits(19, 16) == 0x4) &&
959                (instr->Bits(11, 9) == 0x5) &&
960                (instr->Bit(8) == 0x1) &&
961                (instr->Bit(6) == 0x1) &&
962                (instr->Bit(4) == 0x0)) {
963       Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
964     } else if ((instr->Bits(23, 20) == 0xF) &&
965                (instr->Bits(19, 16) == 0x1) &&
966                (instr->Bits(11, 8) == 0xA) &&
967                (instr->Bits(7, 5) == 0x0) &&
968                (instr->Bit(4) == 0x1)    &&
969                (instr->Bits(3, 0) == 0x0)) {
970         if (instr->Bits(15, 12) == 0xF)
971           Format(instr, "vmrs'cond APSR, FPSCR");
972         else
973           Unknown(instr);  // Not used by V8.
974     } else {
975       Unknown(instr);  // Not used by V8.
976     }
977   } else if (instr->Bit(21) == 1) {
978     if ((instr->Bit(20) == 0x1) &&
979         (instr->Bits(11, 9) == 0x5) &&
980         (instr->Bit(8) == 0x1) &&
981         (instr->Bit(6) == 0) &&
982         (instr->Bit(4) == 0)) {
983       Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
984     } else if ((instr->Bit(20) == 0x1) &&
985                (instr->Bits(11, 9) == 0x5) &&
986                (instr->Bit(8) == 0x1) &&
987                (instr->Bit(6) == 1) &&
988                (instr->Bit(4) == 0)) {
989       Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
990     } else if ((instr->Bit(20) == 0x0) &&
991                (instr->Bits(11, 9) == 0x5) &&
992                (instr->Bit(8) == 0x1) &&
993                (instr->Bit(6) == 0) &&
994                (instr->Bit(4) == 0)) {
995       Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
996     } else {
997       Unknown(instr);  // Not used by V8.
998     }
999   } else {
1000     if ((instr->Bit(20) == 0x0) &&
1001         (instr->Bits(11, 8) == 0xA) &&
1002         (instr->Bits(6, 5) == 0x0) &&
1003         (instr->Bit(4) == 1) &&
1004         (instr->Bits(3, 0) == 0x0)) {
1005       Format(instr, "vmov'cond 'Sn, 'rt");
1006     } else if ((instr->Bit(20) == 0x1) &&
1007                (instr->Bits(11, 8) == 0xA) &&
1008                (instr->Bits(6, 5) == 0x0) &&
1009                (instr->Bit(4) == 1) &&
1010                (instr->Bits(3, 0) == 0x0)) {
1011       Format(instr, "vmov'cond 'rt, 'Sn");
1012     } else {
1013       Unknown(instr);  // Not used by V8.
1014     }
1015   }
1016 }
1017 
1018 
1019 // Decode Type 6 coprocessor instructions.
1020 // Dm = vmov(Rt, Rt2)
1021 // <Rt, Rt2> = vmov(Dm)
1022 // Ddst = MEM(Rbase + 4*offset).
1023 // MEM(Rbase + 4*offset) = Dsrc.
DecodeType6CoprocessorIns(Instr * instr)1024 void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
1025   ASSERT((instr->TypeField() == 6));
1026 
1027   if (instr->CoprocessorField() != 0xB) {
1028     Unknown(instr);  // Not used by V8.
1029   } else {
1030     switch (instr->OpcodeField()) {
1031       case 0x2:
1032         // Load and store double to two GP registers
1033         if (instr->Bits(7, 4) != 0x1) {
1034           Unknown(instr);  // Not used by V8.
1035         } else if (instr->HasL()) {
1036           Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1037         } else {
1038           Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1039         }
1040         break;
1041       case 0x8:
1042         if (instr->HasL()) {
1043           Format(instr, "vldr'cond 'Dd, ['rn - 4*'off8]");
1044         } else {
1045           Format(instr, "vstr'cond 'Dd, ['rn - 4*'off8]");
1046         }
1047         break;
1048       case 0xC:
1049         if (instr->HasL()) {
1050           Format(instr, "vldr'cond 'Dd, ['rn + 4*'off8]");
1051         } else {
1052           Format(instr, "vstr'cond 'Dd, ['rn + 4*'off8]");
1053         }
1054         break;
1055       default:
1056         Unknown(instr);  // Not used by V8.
1057         break;
1058     }
1059   }
1060 }
1061 
1062 
1063 // Disassemble the instruction at *instr_ptr into the output buffer.
InstructionDecode(byte * instr_ptr)1064 int Decoder::InstructionDecode(byte* instr_ptr) {
1065   Instr* instr = Instr::At(instr_ptr);
1066   // Print raw instruction bytes.
1067   out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
1068                                        "%08x       ",
1069                                        instr->InstructionBits());
1070   if (instr->ConditionField() == special_condition) {
1071     DecodeUnconditional(instr);
1072     return Instr::kInstrSize;
1073   }
1074   switch (instr->TypeField()) {
1075     case 0:
1076     case 1: {
1077       DecodeType01(instr);
1078       break;
1079     }
1080     case 2: {
1081       DecodeType2(instr);
1082       break;
1083     }
1084     case 3: {
1085       DecodeType3(instr);
1086       break;
1087     }
1088     case 4: {
1089       DecodeType4(instr);
1090       break;
1091     }
1092     case 5: {
1093       DecodeType5(instr);
1094       break;
1095     }
1096     case 6: {
1097       DecodeType6(instr);
1098       break;
1099     }
1100     case 7: {
1101       DecodeType7(instr);
1102       break;
1103     }
1104     default: {
1105       // The type field is 3-bits in the ARM encoding.
1106       UNREACHABLE();
1107       break;
1108     }
1109   }
1110   return Instr::kInstrSize;
1111 }
1112 
1113 
1114 } }  // namespace assembler::arm
1115 
1116 
1117 
1118 //------------------------------------------------------------------------------
1119 
1120 namespace disasm {
1121 
1122 namespace v8i = v8::internal;
1123 
1124 
NameOfAddress(byte * addr) const1125 const char* NameConverter::NameOfAddress(byte* addr) const {
1126   static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
1127   v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
1128   return tmp_buffer.start();
1129 }
1130 
1131 
NameOfConstant(byte * addr) const1132 const char* NameConverter::NameOfConstant(byte* addr) const {
1133   return NameOfAddress(addr);
1134 }
1135 
1136 
NameOfCPURegister(int reg) const1137 const char* NameConverter::NameOfCPURegister(int reg) const {
1138   return assembler::arm::Registers::Name(reg);
1139 }
1140 
1141 
NameOfByteCPURegister(int reg) const1142 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1143   UNREACHABLE();  // ARM does not have the concept of a byte register
1144   return "nobytereg";
1145 }
1146 
1147 
NameOfXMMRegister(int reg) const1148 const char* NameConverter::NameOfXMMRegister(int reg) const {
1149   UNREACHABLE();  // ARM does not have any XMM registers
1150   return "noxmmreg";
1151 }
1152 
1153 
NameInCode(byte * addr) const1154 const char* NameConverter::NameInCode(byte* addr) const {
1155   // The default name converter is called for unknown code. So we will not try
1156   // to access any memory.
1157   return "";
1158 }
1159 
1160 
1161 //------------------------------------------------------------------------------
1162 
Disassembler(const NameConverter & converter)1163 Disassembler::Disassembler(const NameConverter& converter)
1164     : converter_(converter) {}
1165 
1166 
~Disassembler()1167 Disassembler::~Disassembler() {}
1168 
1169 
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)1170 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1171                                     byte* instruction) {
1172   assembler::arm::Decoder d(converter_, buffer);
1173   return d.InstructionDecode(instruction);
1174 }
1175 
1176 
ConstantPoolSizeAt(byte * instruction)1177 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1178   int instruction_bits = *(reinterpret_cast<int*>(instruction));
1179   if ((instruction_bits & 0xfff00000) == 0x03000000) {
1180     return instruction_bits & 0x0000ffff;
1181   } else {
1182     return -1;
1183   }
1184 }
1185 
1186 
Disassemble(FILE * f,byte * begin,byte * end)1187 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1188   NameConverter converter;
1189   Disassembler d(converter);
1190   for (byte* pc = begin; pc < end;) {
1191     v8::internal::EmbeddedVector<char, 128> buffer;
1192     buffer[0] = '\0';
1193     byte* prev_pc = pc;
1194     pc += d.InstructionDecode(buffer, pc);
1195     fprintf(f, "%p    %08x      %s\n",
1196             prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1197   }
1198 }
1199 
1200 
1201 }  // namespace disasm
1202