• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <assert.h>
6 #include <stdarg.h>
7 #include <stdio.h>
8 #include <string.h>
9 
10 #if V8_TARGET_ARCH_ARM64
11 
12 #include "src/arm64/decoder-arm64-inl.h"
13 #include "src/arm64/disasm-arm64.h"
14 #include "src/base/platform/platform.h"
15 #include "src/disasm.h"
16 #include "src/macro-assembler.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 
DisassemblingDecoder()22 DisassemblingDecoder::DisassemblingDecoder() {
23   buffer_size_ = 256;
24   buffer_ = reinterpret_cast<char*>(malloc(buffer_size_));
25   buffer_pos_ = 0;
26   own_buffer_ = true;
27 }
28 
29 
DisassemblingDecoder(char * text_buffer,int buffer_size)30 DisassemblingDecoder::DisassemblingDecoder(char* text_buffer, int buffer_size) {
31   buffer_size_ = buffer_size;
32   buffer_ = text_buffer;
33   buffer_pos_ = 0;
34   own_buffer_ = false;
35 }
36 
37 
~DisassemblingDecoder()38 DisassemblingDecoder::~DisassemblingDecoder() {
39   if (own_buffer_) {
40     free(buffer_);
41   }
42 }
43 
44 
GetOutput()45 char* DisassemblingDecoder::GetOutput() { return buffer_; }
46 
47 
VisitAddSubImmediate(Instruction * instr)48 void DisassemblingDecoder::VisitAddSubImmediate(Instruction* instr) {
49   bool rd_is_zr = RdIsZROrSP(instr);
50   bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
51                   (instr->ImmAddSub() == 0) ? true : false;
52   const char *mnemonic = "";
53   const char *form = "'Rds, 'Rns, 'IAddSub";
54   const char *form_cmp = "'Rns, 'IAddSub";
55   const char *form_mov = "'Rds, 'Rns";
56 
57   switch (instr->Mask(AddSubImmediateMask)) {
58     case ADD_w_imm:
59     case ADD_x_imm: {
60       mnemonic = "add";
61       if (stack_op) {
62         mnemonic = "mov";
63         form = form_mov;
64       }
65       break;
66     }
67     case ADDS_w_imm:
68     case ADDS_x_imm: {
69       mnemonic = "adds";
70       if (rd_is_zr) {
71         mnemonic = "cmn";
72         form = form_cmp;
73       }
74       break;
75     }
76     case SUB_w_imm:
77     case SUB_x_imm: mnemonic = "sub"; break;
78     case SUBS_w_imm:
79     case SUBS_x_imm: {
80       mnemonic = "subs";
81       if (rd_is_zr) {
82         mnemonic = "cmp";
83         form = form_cmp;
84       }
85       break;
86     }
87     default: UNREACHABLE();
88   }
89   Format(instr, mnemonic, form);
90 }
91 
92 
VisitAddSubShifted(Instruction * instr)93 void DisassemblingDecoder::VisitAddSubShifted(Instruction* instr) {
94   bool rd_is_zr = RdIsZROrSP(instr);
95   bool rn_is_zr = RnIsZROrSP(instr);
96   const char *mnemonic = "";
97   const char *form = "'Rd, 'Rn, 'Rm'HDP";
98   const char *form_cmp = "'Rn, 'Rm'HDP";
99   const char *form_neg = "'Rd, 'Rm'HDP";
100 
101   switch (instr->Mask(AddSubShiftedMask)) {
102     case ADD_w_shift:
103     case ADD_x_shift: mnemonic = "add"; break;
104     case ADDS_w_shift:
105     case ADDS_x_shift: {
106       mnemonic = "adds";
107       if (rd_is_zr) {
108         mnemonic = "cmn";
109         form = form_cmp;
110       }
111       break;
112     }
113     case SUB_w_shift:
114     case SUB_x_shift: {
115       mnemonic = "sub";
116       if (rn_is_zr) {
117         mnemonic = "neg";
118         form = form_neg;
119       }
120       break;
121     }
122     case SUBS_w_shift:
123     case SUBS_x_shift: {
124       mnemonic = "subs";
125       if (rd_is_zr) {
126         mnemonic = "cmp";
127         form = form_cmp;
128       } else if (rn_is_zr) {
129         mnemonic = "negs";
130         form = form_neg;
131       }
132       break;
133     }
134     default: UNREACHABLE();
135   }
136   Format(instr, mnemonic, form);
137 }
138 
139 
VisitAddSubExtended(Instruction * instr)140 void DisassemblingDecoder::VisitAddSubExtended(Instruction* instr) {
141   bool rd_is_zr = RdIsZROrSP(instr);
142   const char *mnemonic = "";
143   Extend mode = static_cast<Extend>(instr->ExtendMode());
144   const char *form = ((mode == UXTX) || (mode == SXTX)) ?
145                      "'Rds, 'Rns, 'Xm'Ext" : "'Rds, 'Rns, 'Wm'Ext";
146   const char *form_cmp = ((mode == UXTX) || (mode == SXTX)) ?
147                          "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext";
148 
149   switch (instr->Mask(AddSubExtendedMask)) {
150     case ADD_w_ext:
151     case ADD_x_ext: mnemonic = "add"; break;
152     case ADDS_w_ext:
153     case ADDS_x_ext: {
154       mnemonic = "adds";
155       if (rd_is_zr) {
156         mnemonic = "cmn";
157         form = form_cmp;
158       }
159       break;
160     }
161     case SUB_w_ext:
162     case SUB_x_ext: mnemonic = "sub"; break;
163     case SUBS_w_ext:
164     case SUBS_x_ext: {
165       mnemonic = "subs";
166       if (rd_is_zr) {
167         mnemonic = "cmp";
168         form = form_cmp;
169       }
170       break;
171     }
172     default: UNREACHABLE();
173   }
174   Format(instr, mnemonic, form);
175 }
176 
177 
VisitAddSubWithCarry(Instruction * instr)178 void DisassemblingDecoder::VisitAddSubWithCarry(Instruction* instr) {
179   bool rn_is_zr = RnIsZROrSP(instr);
180   const char *mnemonic = "";
181   const char *form = "'Rd, 'Rn, 'Rm";
182   const char *form_neg = "'Rd, 'Rm";
183 
184   switch (instr->Mask(AddSubWithCarryMask)) {
185     case ADC_w:
186     case ADC_x: mnemonic = "adc"; break;
187     case ADCS_w:
188     case ADCS_x: mnemonic = "adcs"; break;
189     case SBC_w:
190     case SBC_x: {
191       mnemonic = "sbc";
192       if (rn_is_zr) {
193         mnemonic = "ngc";
194         form = form_neg;
195       }
196       break;
197     }
198     case SBCS_w:
199     case SBCS_x: {
200       mnemonic = "sbcs";
201       if (rn_is_zr) {
202         mnemonic = "ngcs";
203         form = form_neg;
204       }
205       break;
206     }
207     default: UNREACHABLE();
208   }
209   Format(instr, mnemonic, form);
210 }
211 
212 
VisitLogicalImmediate(Instruction * instr)213 void DisassemblingDecoder::VisitLogicalImmediate(Instruction* instr) {
214   bool rd_is_zr = RdIsZROrSP(instr);
215   bool rn_is_zr = RnIsZROrSP(instr);
216   const char *mnemonic = "";
217   const char *form = "'Rds, 'Rn, 'ITri";
218 
219   if (instr->ImmLogical() == 0) {
220     // The immediate encoded in the instruction is not in the expected format.
221     Format(instr, "unallocated", "(LogicalImmediate)");
222     return;
223   }
224 
225   switch (instr->Mask(LogicalImmediateMask)) {
226     case AND_w_imm:
227     case AND_x_imm: mnemonic = "and"; break;
228     case ORR_w_imm:
229     case ORR_x_imm: {
230       mnemonic = "orr";
231       unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
232                                                         : kWRegSizeInBits;
233       if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->ImmLogical())) {
234         mnemonic = "mov";
235         form = "'Rds, 'ITri";
236       }
237       break;
238     }
239     case EOR_w_imm:
240     case EOR_x_imm: mnemonic = "eor"; break;
241     case ANDS_w_imm:
242     case ANDS_x_imm: {
243       mnemonic = "ands";
244       if (rd_is_zr) {
245         mnemonic = "tst";
246         form = "'Rn, 'ITri";
247       }
248       break;
249     }
250     default: UNREACHABLE();
251   }
252   Format(instr, mnemonic, form);
253 }
254 
255 
IsMovzMovnImm(unsigned reg_size,uint64_t value)256 bool DisassemblingDecoder::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
257   DCHECK((reg_size == kXRegSizeInBits) ||
258          ((reg_size == kWRegSizeInBits) && (value <= 0xffffffff)));
259 
260   // Test for movz: 16-bits set at positions 0, 16, 32 or 48.
261   if (((value & 0xffffffffffff0000UL) == 0UL) ||
262       ((value & 0xffffffff0000ffffUL) == 0UL) ||
263       ((value & 0xffff0000ffffffffUL) == 0UL) ||
264       ((value & 0x0000ffffffffffffUL) == 0UL)) {
265     return true;
266   }
267 
268   // Test for movn: NOT(16-bits set at positions 0, 16, 32 or 48).
269   if ((reg_size == kXRegSizeInBits) &&
270       (((value & 0xffffffffffff0000UL) == 0xffffffffffff0000UL) ||
271        ((value & 0xffffffff0000ffffUL) == 0xffffffff0000ffffUL) ||
272        ((value & 0xffff0000ffffffffUL) == 0xffff0000ffffffffUL) ||
273        ((value & 0x0000ffffffffffffUL) == 0x0000ffffffffffffUL))) {
274     return true;
275   }
276   if ((reg_size == kWRegSizeInBits) &&
277       (((value & 0xffff0000) == 0xffff0000) ||
278        ((value & 0x0000ffff) == 0x0000ffff))) {
279     return true;
280   }
281   return false;
282 }
283 
284 
VisitLogicalShifted(Instruction * instr)285 void DisassemblingDecoder::VisitLogicalShifted(Instruction* instr) {
286   bool rd_is_zr = RdIsZROrSP(instr);
287   bool rn_is_zr = RnIsZROrSP(instr);
288   const char *mnemonic = "";
289   const char *form = "'Rd, 'Rn, 'Rm'HLo";
290 
291   switch (instr->Mask(LogicalShiftedMask)) {
292     case AND_w:
293     case AND_x: mnemonic = "and"; break;
294     case BIC_w:
295     case BIC_x: mnemonic = "bic"; break;
296     case EOR_w:
297     case EOR_x: mnemonic = "eor"; break;
298     case EON_w:
299     case EON_x: mnemonic = "eon"; break;
300     case BICS_w:
301     case BICS_x: mnemonic = "bics"; break;
302     case ANDS_w:
303     case ANDS_x: {
304       mnemonic = "ands";
305       if (rd_is_zr) {
306         mnemonic = "tst";
307         form = "'Rn, 'Rm'HLo";
308       }
309       break;
310     }
311     case ORR_w:
312     case ORR_x: {
313       mnemonic = "orr";
314       if (rn_is_zr && (instr->ImmDPShift() == 0) && (instr->ShiftDP() == LSL)) {
315         mnemonic = "mov";
316         form = "'Rd, 'Rm";
317       }
318       break;
319     }
320     case ORN_w:
321     case ORN_x: {
322       mnemonic = "orn";
323       if (rn_is_zr) {
324         mnemonic = "mvn";
325         form = "'Rd, 'Rm'HLo";
326       }
327       break;
328     }
329     default: UNREACHABLE();
330   }
331 
332   Format(instr, mnemonic, form);
333 }
334 
335 
VisitConditionalCompareRegister(Instruction * instr)336 void DisassemblingDecoder::VisitConditionalCompareRegister(Instruction* instr) {
337   const char *mnemonic = "";
338   const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
339 
340   switch (instr->Mask(ConditionalCompareRegisterMask)) {
341     case CCMN_w:
342     case CCMN_x: mnemonic = "ccmn"; break;
343     case CCMP_w:
344     case CCMP_x: mnemonic = "ccmp"; break;
345     default: UNREACHABLE();
346   }
347   Format(instr, mnemonic, form);
348 }
349 
350 
VisitConditionalCompareImmediate(Instruction * instr)351 void DisassemblingDecoder::VisitConditionalCompareImmediate(
352     Instruction* instr) {
353   const char *mnemonic = "";
354   const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
355 
356   switch (instr->Mask(ConditionalCompareImmediateMask)) {
357     case CCMN_w_imm:
358     case CCMN_x_imm: mnemonic = "ccmn"; break;
359     case CCMP_w_imm:
360     case CCMP_x_imm: mnemonic = "ccmp"; break;
361     default: UNREACHABLE();
362   }
363   Format(instr, mnemonic, form);
364 }
365 
366 
VisitConditionalSelect(Instruction * instr)367 void DisassemblingDecoder::VisitConditionalSelect(Instruction* instr) {
368   bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
369   bool rn_is_rm = (instr->Rn() == instr->Rm());
370   const char *mnemonic = "";
371   const char *form = "'Rd, 'Rn, 'Rm, 'Cond";
372   const char *form_test = "'Rd, 'CInv";
373   const char *form_update = "'Rd, 'Rn, 'CInv";
374 
375   Condition cond = static_cast<Condition>(instr->Condition());
376   bool invertible_cond = (cond != al) && (cond != nv);
377 
378   switch (instr->Mask(ConditionalSelectMask)) {
379     case CSEL_w:
380     case CSEL_x: mnemonic = "csel"; break;
381     case CSINC_w:
382     case CSINC_x: {
383       mnemonic = "csinc";
384       if (rnm_is_zr && invertible_cond) {
385         mnemonic = "cset";
386         form = form_test;
387       } else if (rn_is_rm && invertible_cond) {
388         mnemonic = "cinc";
389         form = form_update;
390       }
391       break;
392     }
393     case CSINV_w:
394     case CSINV_x: {
395       mnemonic = "csinv";
396       if (rnm_is_zr && invertible_cond) {
397         mnemonic = "csetm";
398         form = form_test;
399       } else if (rn_is_rm && invertible_cond) {
400         mnemonic = "cinv";
401         form = form_update;
402       }
403       break;
404     }
405     case CSNEG_w:
406     case CSNEG_x: {
407       mnemonic = "csneg";
408       if (rn_is_rm && invertible_cond) {
409         mnemonic = "cneg";
410         form = form_update;
411       }
412       break;
413     }
414     default: UNREACHABLE();
415   }
416   Format(instr, mnemonic, form);
417 }
418 
419 
VisitBitfield(Instruction * instr)420 void DisassemblingDecoder::VisitBitfield(Instruction* instr) {
421   unsigned s = instr->ImmS();
422   unsigned r = instr->ImmR();
423   unsigned rd_size_minus_1 =
424     ((instr->SixtyFourBits() == 1) ? kXRegSizeInBits : kWRegSizeInBits) - 1;
425   const char *mnemonic = "";
426   const char *form = "";
427   const char *form_shift_right = "'Rd, 'Rn, 'IBr";
428   const char *form_extend = "'Rd, 'Wn";
429   const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1";
430   const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1";
431   const char *form_lsl = "'Rd, 'Rn, 'IBZ-r";
432 
433   switch (instr->Mask(BitfieldMask)) {
434     case SBFM_w:
435     case SBFM_x: {
436       mnemonic = "sbfx";
437       form = form_bfx;
438       if (r == 0) {
439         form = form_extend;
440         if (s == 7) {
441           mnemonic = "sxtb";
442         } else if (s == 15) {
443           mnemonic = "sxth";
444         } else if ((s == 31) && (instr->SixtyFourBits() == 1)) {
445           mnemonic = "sxtw";
446         } else {
447           form = form_bfx;
448         }
449       } else if (s == rd_size_minus_1) {
450         mnemonic = "asr";
451         form = form_shift_right;
452       } else if (s < r) {
453         mnemonic = "sbfiz";
454         form = form_bfiz;
455       }
456       break;
457     }
458     case UBFM_w:
459     case UBFM_x: {
460       mnemonic = "ubfx";
461       form = form_bfx;
462       if (r == 0) {
463         form = form_extend;
464         if (s == 7) {
465           mnemonic = "uxtb";
466         } else if (s == 15) {
467           mnemonic = "uxth";
468         } else {
469           form = form_bfx;
470         }
471       }
472       if (s == rd_size_minus_1) {
473         mnemonic = "lsr";
474         form = form_shift_right;
475       } else if (r == s + 1) {
476         mnemonic = "lsl";
477         form = form_lsl;
478       } else if (s < r) {
479         mnemonic = "ubfiz";
480         form = form_bfiz;
481       }
482       break;
483     }
484     case BFM_w:
485     case BFM_x: {
486       mnemonic = "bfxil";
487       form = form_bfx;
488       if (s < r) {
489         mnemonic = "bfi";
490         form = form_bfiz;
491       }
492     }
493   }
494   Format(instr, mnemonic, form);
495 }
496 
497 
VisitExtract(Instruction * instr)498 void DisassemblingDecoder::VisitExtract(Instruction* instr) {
499   const char *mnemonic = "";
500   const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
501 
502   switch (instr->Mask(ExtractMask)) {
503     case EXTR_w:
504     case EXTR_x: {
505       if (instr->Rn() == instr->Rm()) {
506         mnemonic = "ror";
507         form = "'Rd, 'Rn, 'IExtract";
508       } else {
509         mnemonic = "extr";
510       }
511       break;
512     }
513     default: UNREACHABLE();
514   }
515   Format(instr, mnemonic, form);
516 }
517 
518 
VisitPCRelAddressing(Instruction * instr)519 void DisassemblingDecoder::VisitPCRelAddressing(Instruction* instr) {
520   switch (instr->Mask(PCRelAddressingMask)) {
521     case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break;
522     // ADRP is not implemented.
523     default: Format(instr, "unimplemented", "(PCRelAddressing)");
524   }
525 }
526 
527 
VisitConditionalBranch(Instruction * instr)528 void DisassemblingDecoder::VisitConditionalBranch(Instruction* instr) {
529   switch (instr->Mask(ConditionalBranchMask)) {
530     case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
531     default: UNREACHABLE();
532   }
533 }
534 
535 
VisitUnconditionalBranchToRegister(Instruction * instr)536 void DisassemblingDecoder::VisitUnconditionalBranchToRegister(
537     Instruction* instr) {
538   const char *mnemonic = "unimplemented";
539   const char *form = "'Xn";
540 
541   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
542     case BR: mnemonic = "br"; break;
543     case BLR: mnemonic = "blr"; break;
544     case RET: {
545       mnemonic = "ret";
546       if (instr->Rn() == kLinkRegCode) {
547         form = NULL;
548       }
549       break;
550     }
551     default: form = "(UnconditionalBranchToRegister)";
552   }
553   Format(instr, mnemonic, form);
554 }
555 
556 
VisitUnconditionalBranch(Instruction * instr)557 void DisassemblingDecoder::VisitUnconditionalBranch(Instruction* instr) {
558   const char *mnemonic = "";
559   const char *form = "'BImmUncn";
560 
561   switch (instr->Mask(UnconditionalBranchMask)) {
562     case B: mnemonic = "b"; break;
563     case BL: mnemonic = "bl"; break;
564     default: UNREACHABLE();
565   }
566   Format(instr, mnemonic, form);
567 }
568 
569 
VisitDataProcessing1Source(Instruction * instr)570 void DisassemblingDecoder::VisitDataProcessing1Source(Instruction* instr) {
571   const char *mnemonic = "";
572   const char *form = "'Rd, 'Rn";
573 
574   switch (instr->Mask(DataProcessing1SourceMask)) {
575     #define FORMAT(A, B)  \
576     case A##_w:           \
577     case A##_x: mnemonic = B; break;
578     FORMAT(RBIT, "rbit");
579     FORMAT(REV16, "rev16");
580     FORMAT(REV, "rev");
581     FORMAT(CLZ, "clz");
582     FORMAT(CLS, "cls");
583     #undef FORMAT
584     case REV32_x: mnemonic = "rev32"; break;
585     default: UNREACHABLE();
586   }
587   Format(instr, mnemonic, form);
588 }
589 
590 
VisitDataProcessing2Source(Instruction * instr)591 void DisassemblingDecoder::VisitDataProcessing2Source(Instruction* instr) {
592   const char *mnemonic = "unimplemented";
593   const char *form = "'Rd, 'Rn, 'Rm";
594 
595   switch (instr->Mask(DataProcessing2SourceMask)) {
596     #define FORMAT(A, B)  \
597     case A##_w:           \
598     case A##_x: mnemonic = B; break;
599     FORMAT(UDIV, "udiv");
600     FORMAT(SDIV, "sdiv");
601     FORMAT(LSLV, "lsl");
602     FORMAT(LSRV, "lsr");
603     FORMAT(ASRV, "asr");
604     FORMAT(RORV, "ror");
605     #undef FORMAT
606     default: form = "(DataProcessing2Source)";
607   }
608   Format(instr, mnemonic, form);
609 }
610 
611 
VisitDataProcessing3Source(Instruction * instr)612 void DisassemblingDecoder::VisitDataProcessing3Source(Instruction* instr) {
613   bool ra_is_zr = RaIsZROrSP(instr);
614   const char *mnemonic = "";
615   const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
616   const char *form_rrr = "'Rd, 'Rn, 'Rm";
617   const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra";
618   const char *form_xww = "'Xd, 'Wn, 'Wm";
619   const char *form_xxx = "'Xd, 'Xn, 'Xm";
620 
621   switch (instr->Mask(DataProcessing3SourceMask)) {
622     case MADD_w:
623     case MADD_x: {
624       mnemonic = "madd";
625       form = form_rrrr;
626       if (ra_is_zr) {
627         mnemonic = "mul";
628         form = form_rrr;
629       }
630       break;
631     }
632     case MSUB_w:
633     case MSUB_x: {
634       mnemonic = "msub";
635       form = form_rrrr;
636       if (ra_is_zr) {
637         mnemonic = "mneg";
638         form = form_rrr;
639       }
640       break;
641     }
642     case SMADDL_x: {
643       mnemonic = "smaddl";
644       if (ra_is_zr) {
645         mnemonic = "smull";
646         form = form_xww;
647       }
648       break;
649     }
650     case SMSUBL_x: {
651       mnemonic = "smsubl";
652       if (ra_is_zr) {
653         mnemonic = "smnegl";
654         form = form_xww;
655       }
656       break;
657     }
658     case UMADDL_x: {
659       mnemonic = "umaddl";
660       if (ra_is_zr) {
661         mnemonic = "umull";
662         form = form_xww;
663       }
664       break;
665     }
666     case UMSUBL_x: {
667       mnemonic = "umsubl";
668       if (ra_is_zr) {
669         mnemonic = "umnegl";
670         form = form_xww;
671       }
672       break;
673     }
674     case SMULH_x: {
675       mnemonic = "smulh";
676       form = form_xxx;
677       break;
678     }
679     case UMULH_x: {
680       mnemonic = "umulh";
681       form = form_xxx;
682       break;
683     }
684     default: UNREACHABLE();
685   }
686   Format(instr, mnemonic, form);
687 }
688 
689 
VisitCompareBranch(Instruction * instr)690 void DisassemblingDecoder::VisitCompareBranch(Instruction* instr) {
691   const char *mnemonic = "";
692   const char *form = "'Rt, 'BImmCmpa";
693 
694   switch (instr->Mask(CompareBranchMask)) {
695     case CBZ_w:
696     case CBZ_x: mnemonic = "cbz"; break;
697     case CBNZ_w:
698     case CBNZ_x: mnemonic = "cbnz"; break;
699     default: UNREACHABLE();
700   }
701   Format(instr, mnemonic, form);
702 }
703 
704 
VisitTestBranch(Instruction * instr)705 void DisassemblingDecoder::VisitTestBranch(Instruction* instr) {
706   const char *mnemonic = "";
707   // If the top bit of the immediate is clear, the tested register is
708   // disassembled as Wt, otherwise Xt. As the top bit of the immediate is
709   // encoded in bit 31 of the instruction, we can reuse the Rt form, which
710   // uses bit 31 (normally "sf") to choose the register size.
711   const char *form = "'Rt, 'IS, 'BImmTest";
712 
713   switch (instr->Mask(TestBranchMask)) {
714     case TBZ: mnemonic = "tbz"; break;
715     case TBNZ: mnemonic = "tbnz"; break;
716     default: UNREACHABLE();
717   }
718   Format(instr, mnemonic, form);
719 }
720 
721 
VisitMoveWideImmediate(Instruction * instr)722 void DisassemblingDecoder::VisitMoveWideImmediate(Instruction* instr) {
723   const char *mnemonic = "";
724   const char *form = "'Rd, 'IMoveImm";
725 
726   // Print the shift separately for movk, to make it clear which half word will
727   // be overwritten. Movn and movz print the computed immediate, which includes
728   // shift calculation.
729   switch (instr->Mask(MoveWideImmediateMask)) {
730     case MOVN_w:
731     case MOVN_x: mnemonic = "movn"; break;
732     case MOVZ_w:
733     case MOVZ_x: mnemonic = "movz"; break;
734     case MOVK_w:
735     case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
736     default: UNREACHABLE();
737   }
738   Format(instr, mnemonic, form);
739 }
740 
741 
742 #define LOAD_STORE_LIST(V)    \
743   V(STRB_w, "strb", "'Wt")    \
744   V(STRH_w, "strh", "'Wt")    \
745   V(STR_w, "str", "'Wt")      \
746   V(STR_x, "str", "'Xt")      \
747   V(LDRB_w, "ldrb", "'Wt")    \
748   V(LDRH_w, "ldrh", "'Wt")    \
749   V(LDR_w, "ldr", "'Wt")      \
750   V(LDR_x, "ldr", "'Xt")      \
751   V(LDRSB_x, "ldrsb", "'Xt")  \
752   V(LDRSH_x, "ldrsh", "'Xt")  \
753   V(LDRSW_x, "ldrsw", "'Xt")  \
754   V(LDRSB_w, "ldrsb", "'Wt")  \
755   V(LDRSH_w, "ldrsh", "'Wt")  \
756   V(STR_s, "str", "'St")      \
757   V(STR_d, "str", "'Dt")      \
758   V(LDR_s, "ldr", "'St")      \
759   V(LDR_d, "ldr", "'Dt")
760 
VisitLoadStorePreIndex(Instruction * instr)761 void DisassemblingDecoder::VisitLoadStorePreIndex(Instruction* instr) {
762   const char *mnemonic = "unimplemented";
763   const char *form = "(LoadStorePreIndex)";
764 
765   switch (instr->Mask(LoadStorePreIndexMask)) {
766     #define LS_PREINDEX(A, B, C) \
767     case A##_pre: mnemonic = B; form = C ", ['Xns'ILS]!"; break;
768     LOAD_STORE_LIST(LS_PREINDEX)
769     #undef LS_PREINDEX
770   }
771   Format(instr, mnemonic, form);
772 }
773 
774 
VisitLoadStorePostIndex(Instruction * instr)775 void DisassemblingDecoder::VisitLoadStorePostIndex(Instruction* instr) {
776   const char *mnemonic = "unimplemented";
777   const char *form = "(LoadStorePostIndex)";
778 
779   switch (instr->Mask(LoadStorePostIndexMask)) {
780     #define LS_POSTINDEX(A, B, C) \
781     case A##_post: mnemonic = B; form = C ", ['Xns]'ILS"; break;
782     LOAD_STORE_LIST(LS_POSTINDEX)
783     #undef LS_POSTINDEX
784   }
785   Format(instr, mnemonic, form);
786 }
787 
788 
VisitLoadStoreUnsignedOffset(Instruction * instr)789 void DisassemblingDecoder::VisitLoadStoreUnsignedOffset(Instruction* instr) {
790   const char *mnemonic = "unimplemented";
791   const char *form = "(LoadStoreUnsignedOffset)";
792 
793   switch (instr->Mask(LoadStoreUnsignedOffsetMask)) {
794     #define LS_UNSIGNEDOFFSET(A, B, C) \
795     case A##_unsigned: mnemonic = B; form = C ", ['Xns'ILU]"; break;
796     LOAD_STORE_LIST(LS_UNSIGNEDOFFSET)
797     #undef LS_UNSIGNEDOFFSET
798     case PRFM_unsigned: mnemonic = "prfm"; form = "'PrefOp, ['Xn'ILU]";
799   }
800   Format(instr, mnemonic, form);
801 }
802 
803 
VisitLoadStoreRegisterOffset(Instruction * instr)804 void DisassemblingDecoder::VisitLoadStoreRegisterOffset(Instruction* instr) {
805   const char *mnemonic = "unimplemented";
806   const char *form = "(LoadStoreRegisterOffset)";
807 
808   switch (instr->Mask(LoadStoreRegisterOffsetMask)) {
809     #define LS_REGISTEROFFSET(A, B, C) \
810     case A##_reg: mnemonic = B; form = C ", ['Xns, 'Offsetreg]"; break;
811     LOAD_STORE_LIST(LS_REGISTEROFFSET)
812     #undef LS_REGISTEROFFSET
813     case PRFM_reg: mnemonic = "prfm"; form = "'PrefOp, ['Xns, 'Offsetreg]";
814   }
815   Format(instr, mnemonic, form);
816 }
817 
818 
VisitLoadStoreUnscaledOffset(Instruction * instr)819 void DisassemblingDecoder::VisitLoadStoreUnscaledOffset(Instruction* instr) {
820   const char *mnemonic = "unimplemented";
821   const char *form = "'Wt, ['Xns'ILS]";
822   const char *form_x = "'Xt, ['Xns'ILS]";
823   const char *form_s = "'St, ['Xns'ILS]";
824   const char *form_d = "'Dt, ['Xns'ILS]";
825 
826   switch (instr->Mask(LoadStoreUnscaledOffsetMask)) {
827     case STURB_w:  mnemonic = "sturb"; break;
828     case STURH_w:  mnemonic = "sturh"; break;
829     case STUR_w:   mnemonic = "stur"; break;
830     case STUR_x:   mnemonic = "stur"; form = form_x; break;
831     case STUR_s:   mnemonic = "stur"; form = form_s; break;
832     case STUR_d:   mnemonic = "stur"; form = form_d; break;
833     case LDURB_w:  mnemonic = "ldurb"; break;
834     case LDURH_w:  mnemonic = "ldurh"; break;
835     case LDUR_w:   mnemonic = "ldur"; break;
836     case LDUR_x:   mnemonic = "ldur"; form = form_x; break;
837     case LDUR_s:   mnemonic = "ldur"; form = form_s; break;
838     case LDUR_d:   mnemonic = "ldur"; form = form_d; break;
839     case LDURSB_x: form = form_x;  // Fall through.
840     case LDURSB_w: mnemonic = "ldursb"; break;
841     case LDURSH_x: form = form_x;  // Fall through.
842     case LDURSH_w: mnemonic = "ldursh"; break;
843     case LDURSW_x: mnemonic = "ldursw"; form = form_x; break;
844     default: form = "(LoadStoreUnscaledOffset)";
845   }
846   Format(instr, mnemonic, form);
847 }
848 
849 
VisitLoadLiteral(Instruction * instr)850 void DisassemblingDecoder::VisitLoadLiteral(Instruction* instr) {
851   const char *mnemonic = "ldr";
852   const char *form = "(LoadLiteral)";
853 
854   switch (instr->Mask(LoadLiteralMask)) {
855     case LDR_w_lit: form = "'Wt, 'ILLiteral 'LValue"; break;
856     case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break;
857     case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break;
858     case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break;
859     default: mnemonic = "unimplemented";
860   }
861   Format(instr, mnemonic, form);
862 }
863 
864 
865 #define LOAD_STORE_PAIR_LIST(V)         \
866   V(STP_w, "stp", "'Wt, 'Wt2", "4")     \
867   V(LDP_w, "ldp", "'Wt, 'Wt2", "4")     \
868   V(LDPSW_x, "ldpsw", "'Xt, 'Xt2", "4") \
869   V(STP_x, "stp", "'Xt, 'Xt2", "8")     \
870   V(LDP_x, "ldp", "'Xt, 'Xt2", "8")     \
871   V(STP_s, "stp", "'St, 'St2", "4")     \
872   V(LDP_s, "ldp", "'St, 'St2", "4")     \
873   V(STP_d, "stp", "'Dt, 'Dt2", "8")     \
874   V(LDP_d, "ldp", "'Dt, 'Dt2", "8")
875 
VisitLoadStorePairPostIndex(Instruction * instr)876 void DisassemblingDecoder::VisitLoadStorePairPostIndex(Instruction* instr) {
877   const char *mnemonic = "unimplemented";
878   const char *form = "(LoadStorePairPostIndex)";
879 
880   switch (instr->Mask(LoadStorePairPostIndexMask)) {
881     #define LSP_POSTINDEX(A, B, C, D) \
882     case A##_post: mnemonic = B; form = C ", ['Xns]'ILP" D; break;
883     LOAD_STORE_PAIR_LIST(LSP_POSTINDEX)
884     #undef LSP_POSTINDEX
885   }
886   Format(instr, mnemonic, form);
887 }
888 
889 
VisitLoadStorePairPreIndex(Instruction * instr)890 void DisassemblingDecoder::VisitLoadStorePairPreIndex(Instruction* instr) {
891   const char *mnemonic = "unimplemented";
892   const char *form = "(LoadStorePairPreIndex)";
893 
894   switch (instr->Mask(LoadStorePairPreIndexMask)) {
895     #define LSP_PREINDEX(A, B, C, D) \
896     case A##_pre: mnemonic = B; form = C ", ['Xns'ILP" D "]!"; break;
897     LOAD_STORE_PAIR_LIST(LSP_PREINDEX)
898     #undef LSP_PREINDEX
899   }
900   Format(instr, mnemonic, form);
901 }
902 
903 
VisitLoadStorePairOffset(Instruction * instr)904 void DisassemblingDecoder::VisitLoadStorePairOffset(Instruction* instr) {
905   const char *mnemonic = "unimplemented";
906   const char *form = "(LoadStorePairOffset)";
907 
908   switch (instr->Mask(LoadStorePairOffsetMask)) {
909     #define LSP_OFFSET(A, B, C, D) \
910     case A##_off: mnemonic = B; form = C ", ['Xns'ILP" D "]"; break;
911     LOAD_STORE_PAIR_LIST(LSP_OFFSET)
912     #undef LSP_OFFSET
913   }
914   Format(instr, mnemonic, form);
915 }
916 
VisitLoadStoreAcquireRelease(Instruction * instr)917 void DisassemblingDecoder::VisitLoadStoreAcquireRelease(Instruction *instr) {
918   const char *mnemonic = "unimplemented";
919   const char *form = "'Wt, ['Xn]";
920   const char *form_x = "'Xt, ['Xn]";
921   const char *form_stlx = "'Ws, 'Wt, ['Xn]";
922   const char *form_stlx_x = "'Ws, 'Xt, ['Xn]";
923 
924   switch (instr->Mask(LoadStoreAcquireReleaseMask)) {
925     case LDAXR_b: mnemonic = "ldaxrb"; break;
926     case STLR_b:  mnemonic = "stlrb"; break;
927     case LDAR_b:  mnemonic = "ldarb"; break;
928     case LDAXR_h: mnemonic = "ldaxrh"; break;
929     case STLR_h:  mnemonic = "stlrh"; break;
930     case LDAR_h:  mnemonic = "ldarh"; break;
931     case LDAXR_w: mnemonic = "ldaxr"; break;
932     case STLR_w:  mnemonic = "stlr"; break;
933     case LDAR_w:  mnemonic = "ldar"; break;
934     case LDAXR_x: mnemonic = "ldaxr"; form = form_x; break;
935     case STLR_x:  mnemonic = "stlr"; form = form_x; break;
936     case LDAR_x:  mnemonic = "ldar"; form = form_x; break;
937     case STLXR_h: mnemonic = "stlxrh"; form = form_stlx; break;
938     case STLXR_b: mnemonic = "stlxrb"; form = form_stlx; break;
939     case STLXR_w: mnemonic = "stlxr"; form = form_stlx; break;
940     case STLXR_x: mnemonic = "stlxr"; form = form_stlx_x; break;
941     default: form = "(LoadStoreAcquireReleaseMask)";
942   }
943   Format(instr, mnemonic, form);
944 }
945 
VisitFPCompare(Instruction * instr)946 void DisassemblingDecoder::VisitFPCompare(Instruction* instr) {
947   const char *mnemonic = "unimplemented";
948   const char *form = "'Fn, 'Fm";
949   const char *form_zero = "'Fn, #0.0";
950 
951   switch (instr->Mask(FPCompareMask)) {
952     case FCMP_s_zero:
953     case FCMP_d_zero: form = form_zero;  // Fall through.
954     case FCMP_s:
955     case FCMP_d: mnemonic = "fcmp"; break;
956     default: form = "(FPCompare)";
957   }
958   Format(instr, mnemonic, form);
959 }
960 
961 
VisitFPConditionalCompare(Instruction * instr)962 void DisassemblingDecoder::VisitFPConditionalCompare(Instruction* instr) {
963   const char *mnemonic = "unimplemented";
964   const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
965 
966   switch (instr->Mask(FPConditionalCompareMask)) {
967     case FCCMP_s:
968     case FCCMP_d: mnemonic = "fccmp"; break;
969     case FCCMPE_s:
970     case FCCMPE_d: mnemonic = "fccmpe"; break;
971     default: form = "(FPConditionalCompare)";
972   }
973   Format(instr, mnemonic, form);
974 }
975 
976 
VisitFPConditionalSelect(Instruction * instr)977 void DisassemblingDecoder::VisitFPConditionalSelect(Instruction* instr) {
978   const char *mnemonic = "";
979   const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
980 
981   switch (instr->Mask(FPConditionalSelectMask)) {
982     case FCSEL_s:
983     case FCSEL_d: mnemonic = "fcsel"; break;
984     default: UNREACHABLE();
985   }
986   Format(instr, mnemonic, form);
987 }
988 
989 
VisitFPDataProcessing1Source(Instruction * instr)990 void DisassemblingDecoder::VisitFPDataProcessing1Source(Instruction* instr) {
991   const char *mnemonic = "unimplemented";
992   const char *form = "'Fd, 'Fn";
993 
994   switch (instr->Mask(FPDataProcessing1SourceMask)) {
995     #define FORMAT(A, B)  \
996     case A##_s:           \
997     case A##_d: mnemonic = B; break;
998     FORMAT(FMOV, "fmov");
999     FORMAT(FABS, "fabs");
1000     FORMAT(FNEG, "fneg");
1001     FORMAT(FSQRT, "fsqrt");
1002     FORMAT(FRINTN, "frintn");
1003     FORMAT(FRINTP, "frintp");
1004     FORMAT(FRINTM, "frintm");
1005     FORMAT(FRINTZ, "frintz");
1006     FORMAT(FRINTA, "frinta");
1007     FORMAT(FRINTX, "frintx");
1008     FORMAT(FRINTI, "frinti");
1009     #undef FORMAT
1010     case FCVT_ds: mnemonic = "fcvt"; form = "'Dd, 'Sn"; break;
1011     case FCVT_sd: mnemonic = "fcvt"; form = "'Sd, 'Dn"; break;
1012     default: form = "(FPDataProcessing1Source)";
1013   }
1014   Format(instr, mnemonic, form);
1015 }
1016 
1017 
VisitFPDataProcessing2Source(Instruction * instr)1018 void DisassemblingDecoder::VisitFPDataProcessing2Source(Instruction* instr) {
1019   const char *mnemonic = "";
1020   const char *form = "'Fd, 'Fn, 'Fm";
1021 
1022   switch (instr->Mask(FPDataProcessing2SourceMask)) {
1023     #define FORMAT(A, B)  \
1024     case A##_s:           \
1025     case A##_d: mnemonic = B; break;
1026     FORMAT(FMUL, "fmul");
1027     FORMAT(FDIV, "fdiv");
1028     FORMAT(FADD, "fadd");
1029     FORMAT(FSUB, "fsub");
1030     FORMAT(FMAX, "fmax");
1031     FORMAT(FMIN, "fmin");
1032     FORMAT(FMAXNM, "fmaxnm");
1033     FORMAT(FMINNM, "fminnm");
1034     FORMAT(FNMUL, "fnmul");
1035     #undef FORMAT
1036     default: UNREACHABLE();
1037   }
1038   Format(instr, mnemonic, form);
1039 }
1040 
1041 
VisitFPDataProcessing3Source(Instruction * instr)1042 void DisassemblingDecoder::VisitFPDataProcessing3Source(Instruction* instr) {
1043   const char *mnemonic = "";
1044   const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
1045 
1046   switch (instr->Mask(FPDataProcessing3SourceMask)) {
1047     #define FORMAT(A, B)  \
1048     case A##_s:           \
1049     case A##_d: mnemonic = B; break;
1050     FORMAT(FMADD, "fmadd");
1051     FORMAT(FMSUB, "fmsub");
1052     FORMAT(FNMADD, "fnmadd");
1053     FORMAT(FNMSUB, "fnmsub");
1054     #undef FORMAT
1055     default: UNREACHABLE();
1056   }
1057   Format(instr, mnemonic, form);
1058 }
1059 
1060 
VisitFPImmediate(Instruction * instr)1061 void DisassemblingDecoder::VisitFPImmediate(Instruction* instr) {
1062   const char *mnemonic = "";
1063   const char *form = "(FPImmediate)";
1064 
1065   switch (instr->Mask(FPImmediateMask)) {
1066     case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
1067     case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
1068     default: UNREACHABLE();
1069   }
1070   Format(instr, mnemonic, form);
1071 }
1072 
1073 
VisitFPIntegerConvert(Instruction * instr)1074 void DisassemblingDecoder::VisitFPIntegerConvert(Instruction* instr) {
1075   const char *mnemonic = "unimplemented";
1076   const char *form = "(FPIntegerConvert)";
1077   const char *form_rf = "'Rd, 'Fn";
1078   const char *form_fr = "'Fd, 'Rn";
1079 
1080   switch (instr->Mask(FPIntegerConvertMask)) {
1081     case FMOV_ws:
1082     case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
1083     case FMOV_sw:
1084     case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
1085     case FCVTAS_ws:
1086     case FCVTAS_xs:
1087     case FCVTAS_wd:
1088     case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break;
1089     case FCVTAU_ws:
1090     case FCVTAU_xs:
1091     case FCVTAU_wd:
1092     case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break;
1093     case FCVTMS_ws:
1094     case FCVTMS_xs:
1095     case FCVTMS_wd:
1096     case FCVTMS_xd: mnemonic = "fcvtms"; form = form_rf; break;
1097     case FCVTMU_ws:
1098     case FCVTMU_xs:
1099     case FCVTMU_wd:
1100     case FCVTMU_xd: mnemonic = "fcvtmu"; form = form_rf; break;
1101     case FCVTNS_ws:
1102     case FCVTNS_xs:
1103     case FCVTNS_wd:
1104     case FCVTNS_xd: mnemonic = "fcvtns"; form = form_rf; break;
1105     case FCVTNU_ws:
1106     case FCVTNU_xs:
1107     case FCVTNU_wd:
1108     case FCVTNU_xd: mnemonic = "fcvtnu"; form = form_rf; break;
1109     case FCVTZU_xd:
1110     case FCVTZU_ws:
1111     case FCVTZU_wd:
1112     case FCVTZU_xs: mnemonic = "fcvtzu"; form = form_rf; break;
1113     case FCVTZS_xd:
1114     case FCVTZS_wd:
1115     case FCVTZS_xs:
1116     case FCVTZS_ws: mnemonic = "fcvtzs"; form = form_rf; break;
1117     case SCVTF_sw:
1118     case SCVTF_sx:
1119     case SCVTF_dw:
1120     case SCVTF_dx: mnemonic = "scvtf"; form = form_fr; break;
1121     case UCVTF_sw:
1122     case UCVTF_sx:
1123     case UCVTF_dw:
1124     case UCVTF_dx: mnemonic = "ucvtf"; form = form_fr; break;
1125   }
1126   Format(instr, mnemonic, form);
1127 }
1128 
1129 
VisitFPFixedPointConvert(Instruction * instr)1130 void DisassemblingDecoder::VisitFPFixedPointConvert(Instruction* instr) {
1131   const char *mnemonic = "";
1132   const char *form = "'Rd, 'Fn, 'IFPFBits";
1133   const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
1134 
1135   switch (instr->Mask(FPFixedPointConvertMask)) {
1136     case FCVTZS_ws_fixed:
1137     case FCVTZS_xs_fixed:
1138     case FCVTZS_wd_fixed:
1139     case FCVTZS_xd_fixed: mnemonic = "fcvtzs"; break;
1140     case FCVTZU_ws_fixed:
1141     case FCVTZU_xs_fixed:
1142     case FCVTZU_wd_fixed:
1143     case FCVTZU_xd_fixed: mnemonic = "fcvtzu"; break;
1144     case SCVTF_sw_fixed:
1145     case SCVTF_sx_fixed:
1146     case SCVTF_dw_fixed:
1147     case SCVTF_dx_fixed: mnemonic = "scvtf"; form = form_fr; break;
1148     case UCVTF_sw_fixed:
1149     case UCVTF_sx_fixed:
1150     case UCVTF_dw_fixed:
1151     case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
1152   }
1153   Format(instr, mnemonic, form);
1154 }
1155 
1156 
VisitSystem(Instruction * instr)1157 void DisassemblingDecoder::VisitSystem(Instruction* instr) {
1158   // Some system instructions hijack their Op and Cp fields to represent a
1159   // range of immediates instead of indicating a different instruction. This
1160   // makes the decoding tricky.
1161   const char *mnemonic = "unimplemented";
1162   const char *form = "(System)";
1163 
1164   if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
1165     switch (instr->Mask(SystemSysRegMask)) {
1166       case MRS: {
1167         mnemonic = "mrs";
1168         switch (instr->ImmSystemRegister()) {
1169           case NZCV: form = "'Xt, nzcv"; break;
1170           case FPCR: form = "'Xt, fpcr"; break;
1171           default: form = "'Xt, (unknown)"; break;
1172         }
1173         break;
1174       }
1175       case MSR: {
1176         mnemonic = "msr";
1177         switch (instr->ImmSystemRegister()) {
1178           case NZCV: form = "nzcv, 'Xt"; break;
1179           case FPCR: form = "fpcr, 'Xt"; break;
1180           default: form = "(unknown), 'Xt"; break;
1181         }
1182         break;
1183       }
1184     }
1185   } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
1186     DCHECK(instr->Mask(SystemHintMask) == HINT);
1187     switch (instr->ImmHint()) {
1188       case NOP: {
1189         mnemonic = "nop";
1190         form = NULL;
1191         break;
1192       }
1193     }
1194   } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
1195     switch (instr->Mask(MemBarrierMask)) {
1196       case DMB: {
1197         mnemonic = "dmb";
1198         form = "'M";
1199         break;
1200       }
1201       case DSB: {
1202         mnemonic = "dsb";
1203         form = "'M";
1204         break;
1205       }
1206       case ISB: {
1207         mnemonic = "isb";
1208         form = NULL;
1209         break;
1210       }
1211     }
1212   }
1213 
1214   Format(instr, mnemonic, form);
1215 }
1216 
1217 
VisitException(Instruction * instr)1218 void DisassemblingDecoder::VisitException(Instruction* instr) {
1219   const char *mnemonic = "unimplemented";
1220   const char *form = "'IDebug";
1221 
1222   switch (instr->Mask(ExceptionMask)) {
1223     case HLT: mnemonic = "hlt"; break;
1224     case BRK: mnemonic = "brk"; break;
1225     case SVC: mnemonic = "svc"; break;
1226     case HVC: mnemonic = "hvc"; break;
1227     case SMC: mnemonic = "smc"; break;
1228     case DCPS1: mnemonic = "dcps1"; form = "{'IDebug}"; break;
1229     case DCPS2: mnemonic = "dcps2"; form = "{'IDebug}"; break;
1230     case DCPS3: mnemonic = "dcps3"; form = "{'IDebug}"; break;
1231     default: form = "(Exception)";
1232   }
1233   Format(instr, mnemonic, form);
1234 }
1235 
1236 
VisitUnimplemented(Instruction * instr)1237 void DisassemblingDecoder::VisitUnimplemented(Instruction* instr) {
1238   Format(instr, "unimplemented", "(Unimplemented)");
1239 }
1240 
1241 
VisitUnallocated(Instruction * instr)1242 void DisassemblingDecoder::VisitUnallocated(Instruction* instr) {
1243   Format(instr, "unallocated", "(Unallocated)");
1244 }
1245 
1246 
ProcessOutput(Instruction *)1247 void DisassemblingDecoder::ProcessOutput(Instruction* /*instr*/) {
1248   // The base disasm does nothing more than disassembling into a buffer.
1249 }
1250 
1251 
Format(Instruction * instr,const char * mnemonic,const char * format)1252 void DisassemblingDecoder::Format(Instruction* instr, const char* mnemonic,
1253                                   const char* format) {
1254   // TODO(mcapewel) don't think I can use the instr address here - there needs
1255   //                to be a base address too
1256   DCHECK(mnemonic != NULL);
1257   ResetOutput();
1258   Substitute(instr, mnemonic);
1259   if (format != NULL) {
1260     buffer_[buffer_pos_++] = ' ';
1261     Substitute(instr, format);
1262   }
1263   buffer_[buffer_pos_] = 0;
1264   ProcessOutput(instr);
1265 }
1266 
1267 
Substitute(Instruction * instr,const char * string)1268 void DisassemblingDecoder::Substitute(Instruction* instr, const char* string) {
1269   char chr = *string++;
1270   while (chr != '\0') {
1271     if (chr == '\'') {
1272       string += SubstituteField(instr, string);
1273     } else {
1274       buffer_[buffer_pos_++] = chr;
1275     }
1276     chr = *string++;
1277   }
1278 }
1279 
1280 
SubstituteField(Instruction * instr,const char * format)1281 int DisassemblingDecoder::SubstituteField(Instruction* instr,
1282                                           const char* format) {
1283   switch (format[0]) {
1284     case 'R':  // Register. X or W, selected by sf bit.
1285     case 'F':  // FP Register. S or D, selected by type field.
1286     case 'W':
1287     case 'X':
1288     case 'S':
1289     case 'D': return SubstituteRegisterField(instr, format);
1290     case 'I': return SubstituteImmediateField(instr, format);
1291     case 'L': return SubstituteLiteralField(instr, format);
1292     case 'H': return SubstituteShiftField(instr, format);
1293     case 'P': return SubstitutePrefetchField(instr, format);
1294     case 'C': return SubstituteConditionField(instr, format);
1295     case 'E': return SubstituteExtendField(instr, format);
1296     case 'A': return SubstitutePCRelAddressField(instr, format);
1297     case 'B': return SubstituteBranchTargetField(instr, format);
1298     case 'O': return SubstituteLSRegOffsetField(instr, format);
1299     case 'M': return SubstituteBarrierField(instr, format);
1300     default: {
1301       UNREACHABLE();
1302       return 1;
1303     }
1304   }
1305 }
1306 
1307 
SubstituteRegisterField(Instruction * instr,const char * format)1308 int DisassemblingDecoder::SubstituteRegisterField(Instruction* instr,
1309                                                   const char* format) {
1310   unsigned reg_num = 0;
1311   unsigned field_len = 2;
1312   switch (format[1]) {
1313     case 'd': reg_num = instr->Rd(); break;
1314     case 'n': reg_num = instr->Rn(); break;
1315     case 'm': reg_num = instr->Rm(); break;
1316     case 'a': reg_num = instr->Ra(); break;
1317     case 't': {
1318       if (format[2] == '2') {
1319         reg_num = instr->Rt2();
1320         field_len = 3;
1321       } else {
1322         reg_num = instr->Rt();
1323       }
1324       break;
1325     }
1326     case 's':
1327       reg_num = instr->Rs();
1328       break;
1329     default: UNREACHABLE();
1330   }
1331 
1332   // Increase field length for registers tagged as stack.
1333   if (format[2] == 's') {
1334     field_len = 3;
1335   }
1336 
1337   char reg_type;
1338   if (format[0] == 'R') {
1339     // Register type is R: use sf bit to choose X and W.
1340     reg_type = instr->SixtyFourBits() ? 'x' : 'w';
1341   } else if (format[0] == 'F') {
1342     // Floating-point register: use type field to choose S or D.
1343     reg_type = ((instr->FPType() & 1) == 0) ? 's' : 'd';
1344   } else {
1345     // Register type is specified. Make it lower case.
1346     reg_type = format[0] + 0x20;
1347   }
1348 
1349   if ((reg_num != kZeroRegCode) || (reg_type == 's') || (reg_type == 'd')) {
1350     // A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31.
1351 
1352     // Filter special registers
1353     if ((reg_type == 'x') && (reg_num == 27)) {
1354       AppendToOutput("cp");
1355     } else if ((reg_type == 'x') && (reg_num == 28)) {
1356       AppendToOutput("jssp");
1357     } else if ((reg_type == 'x') && (reg_num == 29)) {
1358       AppendToOutput("fp");
1359     } else if ((reg_type == 'x') && (reg_num == 30)) {
1360       AppendToOutput("lr");
1361     } else {
1362       AppendToOutput("%c%d", reg_type, reg_num);
1363     }
1364   } else if (format[2] == 's') {
1365     // Disassemble w31/x31 as stack pointer wcsp/csp.
1366     AppendToOutput("%s", (reg_type == 'w') ? "wcsp" : "csp");
1367   } else {
1368     // Disassemble w31/x31 as zero register wzr/xzr.
1369     AppendToOutput("%czr", reg_type);
1370   }
1371 
1372   return field_len;
1373 }
1374 
1375 
SubstituteImmediateField(Instruction * instr,const char * format)1376 int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr,
1377                                                    const char* format) {
1378   DCHECK(format[0] == 'I');
1379 
1380   switch (format[1]) {
1381     case 'M': {  // IMoveImm or IMoveLSL.
1382       if (format[5] == 'I') {
1383         uint64_t imm = static_cast<uint64_t>(instr->ImmMoveWide())
1384                        << (16 * instr->ShiftMoveWide());
1385         AppendToOutput("#0x%" PRIx64, imm);
1386       } else {
1387         DCHECK(format[5] == 'L');
1388         AppendToOutput("#0x%" PRIx32, instr->ImmMoveWide());
1389         if (instr->ShiftMoveWide() > 0) {
1390           AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
1391         }
1392       }
1393       return 8;
1394     }
1395     case 'L': {
1396       switch (format[2]) {
1397         case 'L': {  // ILLiteral - Immediate Load Literal.
1398           AppendToOutput("pc%+" PRId32, instr->ImmLLiteral()
1399                                             << kLoadLiteralScaleLog2);
1400           return 9;
1401         }
1402         case 'S': {  // ILS - Immediate Load/Store.
1403           if (instr->ImmLS() != 0) {
1404             AppendToOutput(", #%" PRId32, instr->ImmLS());
1405           }
1406           return 3;
1407         }
1408         case 'P': {  // ILPx - Immediate Load/Store Pair, x = access size.
1409           if (instr->ImmLSPair() != 0) {
1410             // format[3] is the scale value. Convert to a number.
1411             int scale = format[3] - 0x30;
1412             AppendToOutput(", #%" PRId32, instr->ImmLSPair() * scale);
1413           }
1414           return 4;
1415         }
1416         case 'U': {  // ILU - Immediate Load/Store Unsigned.
1417           if (instr->ImmLSUnsigned() != 0) {
1418             AppendToOutput(", #%" PRId32, instr->ImmLSUnsigned()
1419                                               << instr->SizeLS());
1420           }
1421           return 3;
1422         }
1423       }
1424     }
1425     case 'C': {  // ICondB - Immediate Conditional Branch.
1426       int64_t offset = instr->ImmCondBranch() << 2;
1427       char sign = (offset >= 0) ? '+' : '-';
1428       AppendToOutput("#%c0x%" PRIx64, sign, offset);
1429       return 6;
1430     }
1431     case 'A': {  // IAddSub.
1432       DCHECK(instr->ShiftAddSub() <= 1);
1433       int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
1434       AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
1435       return 7;
1436     }
1437     case 'F': {  // IFPSingle, IFPDouble or IFPFBits.
1438       if (format[3] == 'F') {  // IFPFBits.
1439         AppendToOutput("#%d", 64 - instr->FPScale());
1440         return 8;
1441       } else {
1442         AppendToOutput("#0x%" PRIx32 " (%.4f)", instr->ImmFP(),
1443                        format[3] == 'S' ? instr->ImmFP32() : instr->ImmFP64());
1444         return 9;
1445       }
1446     }
1447     case 'T': {  // ITri - Immediate Triangular Encoded.
1448       AppendToOutput("#0x%" PRIx64, instr->ImmLogical());
1449       return 4;
1450     }
1451     case 'N': {  // INzcv.
1452       int nzcv = (instr->Nzcv() << Flags_offset);
1453       AppendToOutput("#%c%c%c%c", ((nzcv & NFlag) == 0) ? 'n' : 'N',
1454                                   ((nzcv & ZFlag) == 0) ? 'z' : 'Z',
1455                                   ((nzcv & CFlag) == 0) ? 'c' : 'C',
1456                                   ((nzcv & VFlag) == 0) ? 'v' : 'V');
1457       return 5;
1458     }
1459     case 'P': {  // IP - Conditional compare.
1460       AppendToOutput("#%d", instr->ImmCondCmp());
1461       return 2;
1462     }
1463     case 'B': {  // Bitfields.
1464       return SubstituteBitfieldImmediateField(instr, format);
1465     }
1466     case 'E': {  // IExtract.
1467       AppendToOutput("#%d", instr->ImmS());
1468       return 8;
1469     }
1470     case 'S': {  // IS - Test and branch bit.
1471       AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
1472                             instr->ImmTestBranchBit40());
1473       return 2;
1474     }
1475     case 'D': {  // IDebug - HLT and BRK instructions.
1476       AppendToOutput("#0x%x", instr->ImmException());
1477       return 6;
1478     }
1479     default: {
1480       UNREACHABLE();
1481       return 0;
1482     }
1483   }
1484 }
1485 
1486 
SubstituteBitfieldImmediateField(Instruction * instr,const char * format)1487 int DisassemblingDecoder::SubstituteBitfieldImmediateField(Instruction* instr,
1488                                                            const char* format) {
1489   DCHECK((format[0] == 'I') && (format[1] == 'B'));
1490   unsigned r = instr->ImmR();
1491   unsigned s = instr->ImmS();
1492 
1493   switch (format[2]) {
1494     case 'r': {  // IBr.
1495       AppendToOutput("#%d", r);
1496       return 3;
1497     }
1498     case 's': {  // IBs+1 or IBs-r+1.
1499       if (format[3] == '+') {
1500         AppendToOutput("#%d", s + 1);
1501         return 5;
1502       } else {
1503         DCHECK(format[3] == '-');
1504         AppendToOutput("#%d", s - r + 1);
1505         return 7;
1506       }
1507     }
1508     case 'Z': {  // IBZ-r.
1509       DCHECK((format[3] == '-') && (format[4] == 'r'));
1510       unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits
1511                                                         : kWRegSizeInBits;
1512       AppendToOutput("#%d", reg_size - r);
1513       return 5;
1514     }
1515     default: {
1516       UNREACHABLE();
1517       return 0;
1518     }
1519   }
1520 }
1521 
1522 
SubstituteLiteralField(Instruction * instr,const char * format)1523 int DisassemblingDecoder::SubstituteLiteralField(Instruction* instr,
1524                                                  const char* format) {
1525   DCHECK(strncmp(format, "LValue", 6) == 0);
1526   USE(format);
1527 
1528   switch (instr->Mask(LoadLiteralMask)) {
1529     case LDR_w_lit:
1530     case LDR_x_lit:
1531     case LDR_s_lit:
1532     case LDR_d_lit:
1533       AppendToOutput("(addr 0x%016" PRIxPTR ")", instr->LiteralAddress());
1534       break;
1535     default: UNREACHABLE();
1536   }
1537 
1538   return 6;
1539 }
1540 
1541 
SubstituteShiftField(Instruction * instr,const char * format)1542 int DisassemblingDecoder::SubstituteShiftField(Instruction* instr,
1543                                                const char* format) {
1544   DCHECK(format[0] == 'H');
1545   DCHECK(instr->ShiftDP() <= 0x3);
1546 
1547   switch (format[1]) {
1548     case 'D': {  // HDP.
1549       DCHECK(instr->ShiftDP() != ROR);
1550     }  // Fall through.
1551     case 'L': {  // HLo.
1552       if (instr->ImmDPShift() != 0) {
1553         const char* shift_type[] = {"lsl", "lsr", "asr", "ror"};
1554         AppendToOutput(", %s #%" PRId32, shift_type[instr->ShiftDP()],
1555                        instr->ImmDPShift());
1556       }
1557       return 3;
1558     }
1559     default:
1560       UNREACHABLE();
1561       return 0;
1562   }
1563 }
1564 
1565 
SubstituteConditionField(Instruction * instr,const char * format)1566 int DisassemblingDecoder::SubstituteConditionField(Instruction* instr,
1567                                                    const char* format) {
1568   DCHECK(format[0] == 'C');
1569   const char* condition_code[] = { "eq", "ne", "hs", "lo",
1570                                    "mi", "pl", "vs", "vc",
1571                                    "hi", "ls", "ge", "lt",
1572                                    "gt", "le", "al", "nv" };
1573   int cond;
1574   switch (format[1]) {
1575     case 'B': cond = instr->ConditionBranch(); break;
1576     case 'I': {
1577       cond = NegateCondition(static_cast<Condition>(instr->Condition()));
1578       break;
1579     }
1580     default: cond = instr->Condition();
1581   }
1582   AppendToOutput("%s", condition_code[cond]);
1583   return 4;
1584 }
1585 
1586 
SubstitutePCRelAddressField(Instruction * instr,const char * format)1587 int DisassemblingDecoder::SubstitutePCRelAddressField(Instruction* instr,
1588                                                       const char* format) {
1589   USE(format);
1590   DCHECK(strncmp(format, "AddrPCRel", 9) == 0);
1591 
1592   int offset = instr->ImmPCRel();
1593 
1594   // Only ADR (AddrPCRelByte) is supported.
1595   DCHECK(strcmp(format, "AddrPCRelByte") == 0);
1596 
1597   char sign = '+';
1598   if (offset < 0) {
1599     offset = -offset;
1600     sign = '-';
1601   }
1602   AppendToOutput("#%c0x%x (addr %p)", sign, offset,
1603                  instr->InstructionAtOffset(offset, Instruction::NO_CHECK));
1604   return 13;
1605 }
1606 
1607 
SubstituteBranchTargetField(Instruction * instr,const char * format)1608 int DisassemblingDecoder::SubstituteBranchTargetField(Instruction* instr,
1609                                                       const char* format) {
1610   DCHECK(strncmp(format, "BImm", 4) == 0);
1611 
1612   int64_t offset = 0;
1613   switch (format[5]) {
1614     // BImmUncn - unconditional branch immediate.
1615     case 'n': offset = instr->ImmUncondBranch(); break;
1616     // BImmCond - conditional branch immediate.
1617     case 'o': offset = instr->ImmCondBranch(); break;
1618     // BImmCmpa - compare and branch immediate.
1619     case 'm': offset = instr->ImmCmpBranch(); break;
1620     // BImmTest - test and branch immediate.
1621     case 'e': offset = instr->ImmTestBranch(); break;
1622     default: UNREACHABLE();
1623   }
1624   offset <<= kInstructionSizeLog2;
1625   char sign = '+';
1626   if (offset < 0) {
1627     sign = '-';
1628   }
1629   AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, Abs(offset),
1630                  instr->InstructionAtOffset(offset), Instruction::NO_CHECK);
1631   return 8;
1632 }
1633 
1634 
SubstituteExtendField(Instruction * instr,const char * format)1635 int DisassemblingDecoder::SubstituteExtendField(Instruction* instr,
1636                                                 const char* format) {
1637   DCHECK(strncmp(format, "Ext", 3) == 0);
1638   DCHECK(instr->ExtendMode() <= 7);
1639   USE(format);
1640 
1641   const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
1642                                 "sxtb", "sxth", "sxtw", "sxtx" };
1643 
1644   // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit
1645   // registers becomes lsl.
1646   if (((instr->Rd() == kZeroRegCode) || (instr->Rn() == kZeroRegCode)) &&
1647       (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
1648        (instr->ExtendMode() == UXTX))) {
1649     if (instr->ImmExtendShift() > 0) {
1650       AppendToOutput(", lsl #%d", instr->ImmExtendShift());
1651     }
1652   } else {
1653     AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
1654     if (instr->ImmExtendShift() > 0) {
1655       AppendToOutput(" #%d", instr->ImmExtendShift());
1656     }
1657   }
1658   return 3;
1659 }
1660 
1661 
SubstituteLSRegOffsetField(Instruction * instr,const char * format)1662 int DisassemblingDecoder::SubstituteLSRegOffsetField(Instruction* instr,
1663                                                      const char* format) {
1664   DCHECK(strncmp(format, "Offsetreg", 9) == 0);
1665   const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
1666                                 "undefined", "undefined", "sxtw", "sxtx" };
1667   USE(format);
1668 
1669   unsigned shift = instr->ImmShiftLS();
1670   Extend ext = static_cast<Extend>(instr->ExtendMode());
1671   char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x';
1672 
1673   unsigned rm = instr->Rm();
1674   if (rm == kZeroRegCode) {
1675     AppendToOutput("%czr", reg_type);
1676   } else {
1677     AppendToOutput("%c%d", reg_type, rm);
1678   }
1679 
1680   // Extend mode UXTX is an alias for shift mode LSL here.
1681   if (!((ext == UXTX) && (shift == 0))) {
1682     AppendToOutput(", %s", extend_mode[ext]);
1683     if (shift != 0) {
1684       AppendToOutput(" #%d", instr->SizeLS());
1685     }
1686   }
1687   return 9;
1688 }
1689 
1690 
SubstitutePrefetchField(Instruction * instr,const char * format)1691 int DisassemblingDecoder::SubstitutePrefetchField(Instruction* instr,
1692                                                   const char* format) {
1693   DCHECK(format[0] == 'P');
1694   USE(format);
1695 
1696   int prefetch_mode = instr->PrefetchMode();
1697 
1698   const char* ls = (prefetch_mode & 0x10) ? "st" : "ld";
1699   int level = (prefetch_mode >> 1) + 1;
1700   const char* ks = (prefetch_mode & 1) ? "strm" : "keep";
1701 
1702   AppendToOutput("p%sl%d%s", ls, level, ks);
1703   return 6;
1704 }
1705 
SubstituteBarrierField(Instruction * instr,const char * format)1706 int DisassemblingDecoder::SubstituteBarrierField(Instruction* instr,
1707                                                  const char* format) {
1708   DCHECK(format[0] == 'M');
1709   USE(format);
1710 
1711   static const char* const options[4][4] = {
1712     { "sy (0b0000)", "oshld", "oshst", "osh" },
1713     { "sy (0b0100)", "nshld", "nshst", "nsh" },
1714     { "sy (0b1000)", "ishld", "ishst", "ish" },
1715     { "sy (0b1100)", "ld", "st", "sy" }
1716   };
1717   int domain = instr->ImmBarrierDomain();
1718   int type = instr->ImmBarrierType();
1719 
1720   AppendToOutput("%s", options[domain][type]);
1721   return 1;
1722 }
1723 
1724 
ResetOutput()1725 void DisassemblingDecoder::ResetOutput() {
1726   buffer_pos_ = 0;
1727   buffer_[buffer_pos_] = 0;
1728 }
1729 
1730 
AppendToOutput(const char * format,...)1731 void DisassemblingDecoder::AppendToOutput(const char* format, ...) {
1732   va_list args;
1733   va_start(args, format);
1734   buffer_pos_ += vsnprintf(&buffer_[buffer_pos_], buffer_size_, format, args);
1735   va_end(args);
1736 }
1737 
1738 
ProcessOutput(Instruction * instr)1739 void PrintDisassembler::ProcessOutput(Instruction* instr) {
1740   fprintf(stream_, "0x%016" PRIx64 "  %08" PRIx32 "\t\t%s\n",
1741           reinterpret_cast<uint64_t>(instr), instr->InstructionBits(),
1742           GetOutput());
1743 }
1744 
1745 }  // namespace internal
1746 }  // namespace v8
1747 
1748 
1749 namespace disasm {
1750 
1751 
NameOfAddress(byte * addr) const1752 const char* NameConverter::NameOfAddress(byte* addr) const {
1753   v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void *>(addr));
1754   return tmp_buffer_.start();
1755 }
1756 
1757 
NameOfConstant(byte * addr) const1758 const char* NameConverter::NameOfConstant(byte* addr) const {
1759   return NameOfAddress(addr);
1760 }
1761 
1762 
NameOfCPURegister(int reg) const1763 const char* NameConverter::NameOfCPURegister(int reg) const {
1764   unsigned ureg = reg;  // Avoid warnings about signed/unsigned comparisons.
1765   if (ureg >= v8::internal::kNumberOfRegisters) {
1766     return "noreg";
1767   }
1768   if (ureg == v8::internal::kZeroRegCode) {
1769     return "xzr";
1770   }
1771   v8::internal::SNPrintF(tmp_buffer_, "x%u", ureg);
1772   return tmp_buffer_.start();
1773 }
1774 
1775 
NameOfByteCPURegister(int reg) const1776 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1777   UNREACHABLE();  // ARM64 does not have the concept of a byte register
1778   return "nobytereg";
1779 }
1780 
1781 
NameOfXMMRegister(int reg) const1782 const char* NameConverter::NameOfXMMRegister(int reg) const {
1783   UNREACHABLE();  // ARM64 does not have any XMM registers
1784   return "noxmmreg";
1785 }
1786 
1787 
NameInCode(byte * addr) const1788 const char* NameConverter::NameInCode(byte* addr) const {
1789   // The default name converter is called for unknown code, so we will not try
1790   // to access any memory.
1791   return "";
1792 }
1793 
1794 
1795 //------------------------------------------------------------------------------
1796 
1797 class BufferDisassembler : public v8::internal::DisassemblingDecoder {
1798  public:
BufferDisassembler(v8::internal::Vector<char> out_buffer)1799   explicit BufferDisassembler(v8::internal::Vector<char> out_buffer)
1800       : out_buffer_(out_buffer) { }
1801 
~BufferDisassembler()1802   ~BufferDisassembler() { }
1803 
ProcessOutput(v8::internal::Instruction * instr)1804   virtual void ProcessOutput(v8::internal::Instruction* instr) {
1805     v8::internal::SNPrintF(out_buffer_, "%08" PRIx32 "       %s",
1806                            instr->InstructionBits(), GetOutput());
1807   }
1808 
1809  private:
1810   v8::internal::Vector<char> out_buffer_;
1811 };
1812 
Disassembler(const NameConverter & converter)1813 Disassembler::Disassembler(const NameConverter& converter)
1814     : converter_(converter) {}
1815 
1816 
~Disassembler()1817 Disassembler::~Disassembler() { USE(converter_); }
1818 
1819 
InstructionDecode(v8::internal::Vector<char> buffer,byte * instr)1820 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1821                                     byte* instr) {
1822   v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder;
1823   BufferDisassembler disasm(buffer);
1824   decoder.AppendVisitor(&disasm);
1825 
1826   decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(instr));
1827   return v8::internal::kInstructionSize;
1828 }
1829 
1830 
ConstantPoolSizeAt(byte * instr)1831 int Disassembler::ConstantPoolSizeAt(byte* instr) {
1832   return v8::internal::Assembler::ConstantPoolSizeAt(
1833       reinterpret_cast<v8::internal::Instruction*>(instr));
1834 }
1835 
1836 
Disassemble(FILE * file,byte * start,byte * end)1837 void Disassembler::Disassemble(FILE* file, byte* start, byte* end) {
1838   v8::internal::Decoder<v8::internal::DispatchingDecoderVisitor> decoder;
1839   v8::internal::PrintDisassembler disasm(file);
1840   decoder.AppendVisitor(&disasm);
1841 
1842   for (byte* pc = start; pc < end; pc += v8::internal::kInstructionSize) {
1843     decoder.Decode(reinterpret_cast<v8::internal::Instruction*>(pc));
1844   }
1845 }
1846 
1847 }  // namespace disasm
1848 
1849 #endif  // V8_TARGET_ARCH_ARM64
1850