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