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