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::kPcLoadDelta;
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 1:
790 Format(instr, "ldrexd'cond 'rt, ['rn]");
791 break;
792 case 2:
793 Format(instr, "ldrexb'cond 'rt, ['rn]");
794 break;
795 case 3:
796 Format(instr, "ldrexh'cond 'rt, ['rn]");
797 break;
798 default:
799 UNREACHABLE();
800 break;
801 }
802 } else {
803 // strex
804 // The instruction is documented as strex rd, rt, [rn], but the
805 // "rt" register is using the rm bits.
806 switch (instr->Bits(22, 21)) {
807 case 0:
808 Format(instr, "strex'cond 'rd, 'rm, ['rn]");
809 break;
810 case 1:
811 Format(instr, "strexd'cond 'rd, 'rm, ['rn]");
812 break;
813 case 2:
814 Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
815 break;
816 case 3:
817 Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
818 break;
819 default:
820 UNREACHABLE();
821 break;
822 }
823 }
824 } else {
825 Unknown(instr); // not used by V8
826 }
827 }
828 } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xD) == 0xD)) {
829 // ldrd, strd
830 switch (instr->PUField()) {
831 case da_x: {
832 if (instr->Bit(22) == 0) {
833 Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
834 } else {
835 Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
836 }
837 break;
838 }
839 case ia_x: {
840 if (instr->Bit(22) == 0) {
841 Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
842 } else {
843 Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
844 }
845 break;
846 }
847 case db_x: {
848 if (instr->Bit(22) == 0) {
849 Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
850 } else {
851 Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
852 }
853 break;
854 }
855 case ib_x: {
856 if (instr->Bit(22) == 0) {
857 Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
858 } else {
859 Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
860 }
861 break;
862 }
863 default: {
864 // The PU field is a 2-bit field.
865 UNREACHABLE();
866 break;
867 }
868 }
869 } else {
870 // extra load/store instructions
871 switch (instr->PUField()) {
872 case da_x: {
873 if (instr->Bit(22) == 0) {
874 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
875 } else {
876 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
877 }
878 break;
879 }
880 case ia_x: {
881 if (instr->Bit(22) == 0) {
882 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
883 } else {
884 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
885 }
886 break;
887 }
888 case db_x: {
889 if (instr->Bit(22) == 0) {
890 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
891 } else {
892 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
893 }
894 break;
895 }
896 case ib_x: {
897 if (instr->Bit(22) == 0) {
898 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
899 } else {
900 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
901 }
902 break;
903 }
904 default: {
905 // The PU field is a 2-bit field.
906 UNREACHABLE();
907 break;
908 }
909 }
910 return;
911 }
912 } else if ((type == 0) && instr->IsMiscType0()) {
913 if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
914 (instr->Bits(15, 4) == 0xF00)) {
915 Format(instr, "msr'cond 'spec_reg'spec_reg_fields, 'rm");
916 } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
917 (instr->Bits(11, 0) == 0)) {
918 Format(instr, "mrs'cond 'rd, 'spec_reg");
919 } else if (instr->Bits(22, 21) == 1) {
920 switch (instr->BitField(7, 4)) {
921 case BX:
922 Format(instr, "bx'cond 'rm");
923 break;
924 case BLX:
925 Format(instr, "blx'cond 'rm");
926 break;
927 case BKPT:
928 Format(instr, "bkpt 'off0to3and8to19");
929 break;
930 default:
931 Unknown(instr); // not used by V8
932 break;
933 }
934 } else if (instr->Bits(22, 21) == 3) {
935 switch (instr->BitField(7, 4)) {
936 case CLZ:
937 Format(instr, "clz'cond 'rd, 'rm");
938 break;
939 default:
940 Unknown(instr); // not used by V8
941 break;
942 }
943 } else {
944 Unknown(instr); // not used by V8
945 }
946 } else if ((type == 1) && instr->IsNopLikeType1()) {
947 if (instr->BitField(7, 0) == 0) {
948 Format(instr, "nop'cond");
949 } else if (instr->BitField(7, 0) == 20) {
950 Format(instr, "csdb");
951 } else {
952 Unknown(instr); // Not used in V8.
953 }
954 } else {
955 switch (instr->OpcodeField()) {
956 case AND: {
957 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
958 break;
959 }
960 case EOR: {
961 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
962 break;
963 }
964 case SUB: {
965 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
966 break;
967 }
968 case RSB: {
969 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
970 break;
971 }
972 case ADD: {
973 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
974 break;
975 }
976 case ADC: {
977 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
978 break;
979 }
980 case SBC: {
981 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
982 break;
983 }
984 case RSC: {
985 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
986 break;
987 }
988 case TST: {
989 if (instr->HasS()) {
990 Format(instr, "tst'cond 'rn, 'shift_op");
991 } else {
992 Format(instr, "movw'cond 'mw");
993 }
994 break;
995 }
996 case TEQ: {
997 if (instr->HasS()) {
998 Format(instr, "teq'cond 'rn, 'shift_op");
999 } else {
1000 // Other instructions matching this pattern are handled in the
1001 // miscellaneous instructions part above.
1002 UNREACHABLE();
1003 }
1004 break;
1005 }
1006 case CMP: {
1007 if (instr->HasS()) {
1008 Format(instr, "cmp'cond 'rn, 'shift_op");
1009 } else {
1010 Format(instr, "movt'cond 'mw");
1011 }
1012 break;
1013 }
1014 case CMN: {
1015 if (instr->HasS()) {
1016 Format(instr, "cmn'cond 'rn, 'shift_op");
1017 } else {
1018 // Other instructions matching this pattern are handled in the
1019 // miscellaneous instructions part above.
1020 UNREACHABLE();
1021 }
1022 break;
1023 }
1024 case ORR: {
1025 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
1026 break;
1027 }
1028 case MOV: {
1029 Format(instr, "mov'cond's 'rd, 'shift_op");
1030 break;
1031 }
1032 case BIC: {
1033 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
1034 break;
1035 }
1036 case MVN: {
1037 Format(instr, "mvn'cond's 'rd, 'shift_op");
1038 break;
1039 }
1040 default: {
1041 // The Opcode field is a 4-bit field.
1042 UNREACHABLE();
1043 break;
1044 }
1045 }
1046 }
1047 }
1048
1049
DecodeType2(Instruction * instr)1050 void Decoder::DecodeType2(Instruction* instr) {
1051 switch (instr->PUField()) {
1052 case da_x: {
1053 if (instr->HasW()) {
1054 Unknown(instr); // not used in V8
1055 return;
1056 }
1057 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
1058 break;
1059 }
1060 case ia_x: {
1061 if (instr->HasW()) {
1062 Unknown(instr); // not used in V8
1063 return;
1064 }
1065 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
1066 break;
1067 }
1068 case db_x: {
1069 if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
1070 Format(instr, "'memop'cond'b 'rd, [pc, #-'off12]'w (addr 'A)");
1071 } else {
1072 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
1073 }
1074 break;
1075 }
1076 case ib_x: {
1077 if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
1078 Format(instr, "'memop'cond'b 'rd, [pc, #+'off12]'w (addr 'A)");
1079 } else {
1080 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
1081 }
1082 break;
1083 }
1084 default: {
1085 // The PU field is a 2-bit field.
1086 UNREACHABLE();
1087 break;
1088 }
1089 }
1090 }
1091
1092
DecodeType3(Instruction * instr)1093 void Decoder::DecodeType3(Instruction* instr) {
1094 switch (instr->PUField()) {
1095 case da_x: {
1096 VERIFY(!instr->HasW());
1097 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
1098 break;
1099 }
1100 case ia_x: {
1101 if (instr->Bit(4) == 0) {
1102 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
1103 } else {
1104 if (instr->Bit(5) == 0) {
1105 switch (instr->Bits(22, 21)) {
1106 case 0:
1107 if (instr->Bit(20) == 0) {
1108 if (instr->Bit(6) == 0) {
1109 Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
1110 } else {
1111 if (instr->Bits(11, 7) == 0) {
1112 Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
1113 } else {
1114 Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
1115 }
1116 }
1117 } else {
1118 UNREACHABLE();
1119 }
1120 break;
1121 case 1:
1122 UNREACHABLE();
1123 break;
1124 case 2:
1125 UNREACHABLE();
1126 break;
1127 case 3:
1128 Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
1129 break;
1130 }
1131 } else {
1132 switch (instr->Bits(22, 21)) {
1133 case 0:
1134 UNREACHABLE();
1135 break;
1136 case 1:
1137 if (instr->Bits(9, 6) == 1) {
1138 if (instr->Bit(20) == 0) {
1139 if (instr->Bits(19, 16) == 0xF) {
1140 switch (instr->Bits(11, 10)) {
1141 case 0:
1142 Format(instr, "sxtb'cond 'rd, 'rm");
1143 break;
1144 case 1:
1145 Format(instr, "sxtb'cond 'rd, 'rm, ror #8");
1146 break;
1147 case 2:
1148 Format(instr, "sxtb'cond 'rd, 'rm, ror #16");
1149 break;
1150 case 3:
1151 Format(instr, "sxtb'cond 'rd, 'rm, ror #24");
1152 break;
1153 }
1154 } else {
1155 switch (instr->Bits(11, 10)) {
1156 case 0:
1157 Format(instr, "sxtab'cond 'rd, 'rn, 'rm");
1158 break;
1159 case 1:
1160 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8");
1161 break;
1162 case 2:
1163 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16");
1164 break;
1165 case 3:
1166 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24");
1167 break;
1168 }
1169 }
1170 } else {
1171 if (instr->Bits(19, 16) == 0xF) {
1172 switch (instr->Bits(11, 10)) {
1173 case 0:
1174 Format(instr, "sxth'cond 'rd, 'rm");
1175 break;
1176 case 1:
1177 Format(instr, "sxth'cond 'rd, 'rm, ror #8");
1178 break;
1179 case 2:
1180 Format(instr, "sxth'cond 'rd, 'rm, ror #16");
1181 break;
1182 case 3:
1183 Format(instr, "sxth'cond 'rd, 'rm, ror #24");
1184 break;
1185 }
1186 } else {
1187 switch (instr->Bits(11, 10)) {
1188 case 0:
1189 Format(instr, "sxtah'cond 'rd, 'rn, 'rm");
1190 break;
1191 case 1:
1192 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8");
1193 break;
1194 case 2:
1195 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16");
1196 break;
1197 case 3:
1198 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24");
1199 break;
1200 }
1201 }
1202 }
1203 } else if (instr->Bits(27, 16) == 0x6BF &&
1204 instr->Bits(11, 4) == 0xF3) {
1205 Format(instr, "rev'cond 'rd, 'rm");
1206 } else {
1207 UNREACHABLE();
1208 }
1209 break;
1210 case 2:
1211 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
1212 if (instr->Bits(19, 16) == 0xF) {
1213 switch (instr->Bits(11, 10)) {
1214 case 0:
1215 Format(instr, "uxtb16'cond 'rd, 'rm");
1216 break;
1217 case 1:
1218 Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
1219 break;
1220 case 2:
1221 Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
1222 break;
1223 case 3:
1224 Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
1225 break;
1226 }
1227 } else {
1228 UNREACHABLE();
1229 }
1230 } else {
1231 UNREACHABLE();
1232 }
1233 break;
1234 case 3:
1235 if ((instr->Bits(9, 6) == 1)) {
1236 if ((instr->Bit(20) == 0)) {
1237 if (instr->Bits(19, 16) == 0xF) {
1238 switch (instr->Bits(11, 10)) {
1239 case 0:
1240 Format(instr, "uxtb'cond 'rd, 'rm");
1241 break;
1242 case 1:
1243 Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
1244 break;
1245 case 2:
1246 Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
1247 break;
1248 case 3:
1249 Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
1250 break;
1251 }
1252 } else {
1253 switch (instr->Bits(11, 10)) {
1254 case 0:
1255 Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
1256 break;
1257 case 1:
1258 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
1259 break;
1260 case 2:
1261 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
1262 break;
1263 case 3:
1264 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
1265 break;
1266 }
1267 }
1268 } else {
1269 if (instr->Bits(19, 16) == 0xF) {
1270 switch (instr->Bits(11, 10)) {
1271 case 0:
1272 Format(instr, "uxth'cond 'rd, 'rm");
1273 break;
1274 case 1:
1275 Format(instr, "uxth'cond 'rd, 'rm, ror #8");
1276 break;
1277 case 2:
1278 Format(instr, "uxth'cond 'rd, 'rm, ror #16");
1279 break;
1280 case 3:
1281 Format(instr, "uxth'cond 'rd, 'rm, ror #24");
1282 break;
1283 }
1284 } else {
1285 switch (instr->Bits(11, 10)) {
1286 case 0:
1287 Format(instr, "uxtah'cond 'rd, 'rn, 'rm");
1288 break;
1289 case 1:
1290 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8");
1291 break;
1292 case 2:
1293 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16");
1294 break;
1295 case 3:
1296 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24");
1297 break;
1298 }
1299 }
1300 }
1301 } else {
1302 // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001
1303 if ((instr->Bits(20, 16) == 0x1F) &&
1304 (instr->Bits(11, 4) == 0xF3)) {
1305 Format(instr, "rbit'cond 'rd, 'rm");
1306 } else {
1307 UNREACHABLE();
1308 }
1309 }
1310 break;
1311 }
1312 }
1313 }
1314 break;
1315 }
1316 case db_x: {
1317 if (instr->Bits(22, 20) == 0x5) {
1318 if (instr->Bits(7, 4) == 0x1) {
1319 if (instr->Bits(15, 12) == 0xF) {
1320 Format(instr, "smmul'cond 'rn, 'rm, 'rs");
1321 } else {
1322 // SMMLA (in V8 notation matching ARM ISA format)
1323 Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
1324 }
1325 break;
1326 }
1327 }
1328 if (instr->Bits(5, 4) == 0x1) {
1329 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
1330 if (instr->Bit(21) == 0x1) {
1331 // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1332 Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
1333 } else {
1334 // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1335 Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
1336 }
1337 break;
1338 }
1339 }
1340 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1341 break;
1342 }
1343 case ib_x: {
1344 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1345 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1346 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1347 uint32_t msbit = widthminus1 + lsbit;
1348 if (msbit <= 31) {
1349 if (instr->Bit(22)) {
1350 Format(instr, "ubfx'cond 'rd, 'rm, 'f");
1351 } else {
1352 Format(instr, "sbfx'cond 'rd, 'rm, 'f");
1353 }
1354 } else {
1355 UNREACHABLE();
1356 }
1357 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
1358 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1359 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
1360 if (msbit >= lsbit) {
1361 if (instr->RmValue() == 15) {
1362 Format(instr, "bfc'cond 'rd, 'f");
1363 } else {
1364 Format(instr, "bfi'cond 'rd, 'rm, 'f");
1365 }
1366 } else {
1367 UNREACHABLE();
1368 }
1369 } else {
1370 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1371 }
1372 break;
1373 }
1374 default: {
1375 // The PU field is a 2-bit field.
1376 UNREACHABLE();
1377 break;
1378 }
1379 }
1380 }
1381
1382
DecodeType4(Instruction * instr)1383 void Decoder::DecodeType4(Instruction* instr) {
1384 if (instr->Bit(22) != 0) {
1385 // Privileged mode currently not supported.
1386 Unknown(instr);
1387 } else {
1388 if (instr->HasL()) {
1389 Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1390 } else {
1391 Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1392 }
1393 }
1394 }
1395
1396
DecodeType5(Instruction * instr)1397 void Decoder::DecodeType5(Instruction* instr) {
1398 Format(instr, "b'l'cond 'target");
1399 }
1400
1401
DecodeType6(Instruction * instr)1402 void Decoder::DecodeType6(Instruction* instr) {
1403 DecodeType6CoprocessorIns(instr);
1404 }
1405
1406
DecodeType7(Instruction * instr)1407 int Decoder::DecodeType7(Instruction* instr) {
1408 if (instr->Bit(24) == 1) {
1409 if (instr->SvcValue() >= kStopCode) {
1410 Format(instr, "stop'cond 'svc");
1411 } else {
1412 Format(instr, "svc'cond 'svc");
1413 }
1414 } else {
1415 switch (instr->CoprocessorValue()) {
1416 case 10: // Fall through.
1417 case 11:
1418 DecodeTypeVFP(instr);
1419 break;
1420 case 15:
1421 DecodeTypeCP15(instr);
1422 break;
1423 default:
1424 Unknown(instr);
1425 break;
1426 }
1427 }
1428 return kInstrSize;
1429 }
1430
1431
1432 // void Decoder::DecodeTypeVFP(Instruction* instr)
1433 // vmov: Sn = Rt
1434 // vmov: Rt = Sn
1435 // vcvt: Dd = Sm
1436 // vcvt: Sd = Dm
1437 // vcvt.f64.s32 Dd, Dd, #<fbits>
1438 // Dd = vabs(Dm)
1439 // Sd = vabs(Sm)
1440 // Dd = vneg(Dm)
1441 // Sd = vneg(Sm)
1442 // Dd = vadd(Dn, Dm)
1443 // Sd = vadd(Sn, Sm)
1444 // Dd = vsub(Dn, Dm)
1445 // Sd = vsub(Sn, Sm)
1446 // Dd = vmul(Dn, Dm)
1447 // Sd = vmul(Sn, Sm)
1448 // Dd = vmla(Dn, Dm)
1449 // Sd = vmla(Sn, Sm)
1450 // Dd = vmls(Dn, Dm)
1451 // Sd = vmls(Sn, Sm)
1452 // Dd = vdiv(Dn, Dm)
1453 // Sd = vdiv(Sn, Sm)
1454 // vcmp(Dd, Dm)
1455 // vcmp(Sd, Sm)
1456 // Dd = vsqrt(Dm)
1457 // Sd = vsqrt(Sm)
1458 // vmrs
1459 // vmsr
1460 // Qd = vdup.size(Qd, Rt)
1461 // vmov.size: Dd[i] = Rt
1462 // vmov.sign.size: Rt = Dn[i]
DecodeTypeVFP(Instruction * instr)1463 void Decoder::DecodeTypeVFP(Instruction* instr) {
1464 VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
1465 VERIFY(instr->Bits(11, 9) == 0x5);
1466
1467 if (instr->Bit(4) == 0) {
1468 if (instr->Opc1Value() == 0x7) {
1469 // Other data processing instructions
1470 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
1471 // vmov register to register.
1472 if (instr->SzValue() == 0x1) {
1473 Format(instr, "vmov'cond.f64 'Dd, 'Dm");
1474 } else {
1475 Format(instr, "vmov'cond.f32 'Sd, 'Sm");
1476 }
1477 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
1478 // vabs
1479 if (instr->SzValue() == 0x1) {
1480 Format(instr, "vabs'cond.f64 'Dd, 'Dm");
1481 } else {
1482 Format(instr, "vabs'cond.f32 'Sd, 'Sm");
1483 }
1484 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
1485 // vneg
1486 if (instr->SzValue() == 0x1) {
1487 Format(instr, "vneg'cond.f64 'Dd, 'Dm");
1488 } else {
1489 Format(instr, "vneg'cond.f32 'Sd, 'Sm");
1490 }
1491 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
1492 DecodeVCVTBetweenDoubleAndSingle(instr);
1493 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
1494 DecodeVCVTBetweenFloatingPointAndInteger(instr);
1495 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
1496 (instr->Bit(8) == 1)) {
1497 // vcvt.f64.s32 Dd, Dd, #<fbits>
1498 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
1499 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
1500 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1501 ", #%d", fraction_bits);
1502 } else if (((instr->Opc2Value() >> 1) == 0x6) &&
1503 (instr->Opc3Value() & 0x1)) {
1504 DecodeVCVTBetweenFloatingPointAndInteger(instr);
1505 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1506 (instr->Opc3Value() & 0x1)) {
1507 DecodeVCMP(instr);
1508 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
1509 if (instr->SzValue() == 0x1) {
1510 Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
1511 } else {
1512 Format(instr, "vsqrt'cond.f32 'Sd, 'Sm");
1513 }
1514 } else if (instr->Opc3Value() == 0x0) {
1515 if (instr->SzValue() == 0x1) {
1516 Format(instr, "vmov'cond.f64 'Dd, 'd");
1517 } else {
1518 Format(instr, "vmov'cond.f32 'Sd, 'd");
1519 }
1520 } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) {
1521 // vrintz - round towards zero (truncate)
1522 if (instr->SzValue() == 0x1) {
1523 Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm");
1524 } else {
1525 Format(instr, "vrintz'cond.f32.f32 'Sd, 'Sm");
1526 }
1527 } else {
1528 Unknown(instr); // Not used by V8.
1529 }
1530 } else if (instr->Opc1Value() == 0x3) {
1531 if (instr->SzValue() == 0x1) {
1532 if (instr->Opc3Value() & 0x1) {
1533 Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
1534 } else {
1535 Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
1536 }
1537 } else {
1538 if (instr->Opc3Value() & 0x1) {
1539 Format(instr, "vsub'cond.f32 'Sd, 'Sn, 'Sm");
1540 } else {
1541 Format(instr, "vadd'cond.f32 'Sd, 'Sn, 'Sm");
1542 }
1543 }
1544 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
1545 if (instr->SzValue() == 0x1) {
1546 Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
1547 } else {
1548 Format(instr, "vmul'cond.f32 'Sd, 'Sn, 'Sm");
1549 }
1550 } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
1551 if (instr->SzValue() == 0x1) {
1552 Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
1553 } else {
1554 Format(instr, "vmla'cond.f32 'Sd, 'Sn, 'Sm");
1555 }
1556 } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
1557 if (instr->SzValue() == 0x1) {
1558 Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
1559 } else {
1560 Format(instr, "vmls'cond.f32 'Sd, 'Sn, 'Sm");
1561 }
1562 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
1563 if (instr->SzValue() == 0x1) {
1564 Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
1565 } else {
1566 Format(instr, "vdiv'cond.f32 'Sd, 'Sn, 'Sm");
1567 }
1568 } else {
1569 Unknown(instr); // Not used by V8.
1570 }
1571 } else {
1572 if ((instr->VCValue() == 0x0) &&
1573 (instr->VAValue() == 0x0)) {
1574 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1575 } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
1576 const char* rt_name = converter_.NameOfCPURegister(instr->RtValue());
1577 if (instr->Bit(23) == 0) {
1578 int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
1579 if ((opc1_opc2 & 0xB) == 0) {
1580 // NeonS32/NeonU32
1581 if (instr->Bit(21) == 0x0) {
1582 Format(instr, "vmov'cond.32 'Dd[0], 'rt");
1583 } else {
1584 Format(instr, "vmov'cond.32 'Dd[1], 'rt");
1585 }
1586 } else {
1587 int vd = 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.8 d%d[%d], %s", vd, i, rt_name);
1593 } else if ((opc1_opc2 & 0x1) != 0) {
1594 // NeonS16 / NeonU16
1595 int i = (opc1_opc2 >> 1) & 0x3;
1596 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1597 "vmov.16 d%d[%d], %s", vd, i, rt_name);
1598 } else {
1599 Unknown(instr);
1600 }
1601 }
1602 } else {
1603 int size = 32;
1604 if (instr->Bit(5) != 0) {
1605 size = 16;
1606 } else if (instr->Bit(22) != 0) {
1607 size = 8;
1608 }
1609 int Vd = instr->VFPNRegValue(kSimd128Precision);
1610 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1611 "vdup.%i q%d, %s", size, Vd, rt_name);
1612 }
1613 } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
1614 int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
1615 if ((opc1_opc2 & 0xB) == 0) {
1616 // NeonS32 / NeonU32
1617 if (instr->Bit(21) == 0x0) {
1618 Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
1619 } else {
1620 Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
1621 }
1622 } else {
1623 char sign = instr->Bit(23) != 0 ? 'u' : 's';
1624 const char* rt_name = converter_.NameOfCPURegister(instr->RtValue());
1625 int vn = instr->VFPNRegValue(kDoublePrecision);
1626 if ((opc1_opc2 & 0x8) != 0) {
1627 // NeonS8 / NeonU8
1628 int i = opc1_opc2 & 0x7;
1629 out_buffer_pos_ +=
1630 SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%c8 %s, d%d[%d]",
1631 sign, rt_name, vn, i);
1632 } else if ((opc1_opc2 & 0x1) != 0) {
1633 // NeonS16 / NeonU16
1634 int i = (opc1_opc2 >> 1) & 0x3;
1635 out_buffer_pos_ +=
1636 SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%c16 %s, d%d[%d]",
1637 sign, rt_name, vn, i);
1638 } else {
1639 Unknown(instr);
1640 }
1641 }
1642 } else if ((instr->VCValue() == 0x0) &&
1643 (instr->VAValue() == 0x7) &&
1644 (instr->Bits(19, 16) == 0x1)) {
1645 if (instr->VLValue() == 0) {
1646 if (instr->Bits(15, 12) == 0xF) {
1647 Format(instr, "vmsr'cond FPSCR, APSR");
1648 } else {
1649 Format(instr, "vmsr'cond FPSCR, 'rt");
1650 }
1651 } else {
1652 if (instr->Bits(15, 12) == 0xF) {
1653 Format(instr, "vmrs'cond APSR, FPSCR");
1654 } else {
1655 Format(instr, "vmrs'cond 'rt, FPSCR");
1656 }
1657 }
1658 } else {
1659 Unknown(instr); // Not used by V8.
1660 }
1661 }
1662 }
1663
DecodeTypeCP15(Instruction * instr)1664 void Decoder::DecodeTypeCP15(Instruction* instr) {
1665 VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
1666 VERIFY(instr->CoprocessorValue() == 15);
1667
1668 if (instr->Bit(4) == 1) {
1669 int crn = instr->Bits(19, 16);
1670 int crm = instr->Bits(3, 0);
1671 int opc1 = instr->Bits(23, 21);
1672 int opc2 = instr->Bits(7, 5);
1673 if ((opc1 == 0) && (crn == 7)) {
1674 // ARMv6 memory barrier operations.
1675 // Details available in ARM DDI 0406C.b, B3-1750.
1676 if ((crm == 10) && (opc2 == 5)) {
1677 Format(instr, "mcr'cond (CP15DMB)");
1678 } else if ((crm == 10) && (opc2 == 4)) {
1679 Format(instr, "mcr'cond (CP15DSB)");
1680 } else if ((crm == 5) && (opc2 == 4)) {
1681 Format(instr, "mcr'cond (CP15ISB)");
1682 } else {
1683 Unknown(instr);
1684 }
1685 } else {
1686 Unknown(instr);
1687 }
1688 } else {
1689 Unknown(instr);
1690 }
1691 }
1692
DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction * instr)1693 void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
1694 Instruction* instr) {
1695 VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
1696 (instr->VAValue() == 0x0));
1697
1698 bool to_arm_register = (instr->VLValue() == 0x1);
1699
1700 if (to_arm_register) {
1701 Format(instr, "vmov'cond 'rt, 'Sn");
1702 } else {
1703 Format(instr, "vmov'cond 'Sn, 'rt");
1704 }
1705 }
1706
1707
DecodeVCMP(Instruction * instr)1708 void Decoder::DecodeVCMP(Instruction* instr) {
1709 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1710 VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1711 (instr->Opc3Value() & 0x1));
1712
1713 // Comparison.
1714 bool dp_operation = (instr->SzValue() == 1);
1715 bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1716
1717 if (dp_operation && !raise_exception_for_qnan) {
1718 if (instr->Opc2Value() == 0x4) {
1719 Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
1720 } else if (instr->Opc2Value() == 0x5) {
1721 Format(instr, "vcmp'cond.f64 'Dd, #0.0");
1722 } else {
1723 Unknown(instr); // invalid
1724 }
1725 } else if (!raise_exception_for_qnan) {
1726 if (instr->Opc2Value() == 0x4) {
1727 Format(instr, "vcmp'cond.f32 'Sd, 'Sm");
1728 } else if (instr->Opc2Value() == 0x5) {
1729 Format(instr, "vcmp'cond.f32 'Sd, #0.0");
1730 } else {
1731 Unknown(instr); // invalid
1732 }
1733 } else {
1734 Unknown(instr); // Not used by V8.
1735 }
1736 }
1737
1738
DecodeVCVTBetweenDoubleAndSingle(Instruction * instr)1739 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
1740 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1741 VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
1742
1743 bool double_to_single = (instr->SzValue() == 1);
1744
1745 if (double_to_single) {
1746 Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
1747 } else {
1748 Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
1749 }
1750 }
1751
1752
DecodeVCVTBetweenFloatingPointAndInteger(Instruction * instr)1753 void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
1754 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1755 VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
1756 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
1757
1758 bool to_integer = (instr->Bit(18) == 1);
1759 bool dp_operation = (instr->SzValue() == 1);
1760 if (to_integer) {
1761 bool unsigned_integer = (instr->Bit(16) == 0);
1762
1763 if (dp_operation) {
1764 if (unsigned_integer) {
1765 Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
1766 } else {
1767 Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
1768 }
1769 } else {
1770 if (unsigned_integer) {
1771 Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
1772 } else {
1773 Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
1774 }
1775 }
1776 } else {
1777 bool unsigned_integer = (instr->Bit(7) == 0);
1778
1779 if (dp_operation) {
1780 if (unsigned_integer) {
1781 Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
1782 } else {
1783 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
1784 }
1785 } else {
1786 if (unsigned_integer) {
1787 Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
1788 } else {
1789 Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
1790 }
1791 }
1792 }
1793 }
1794
1795
1796 // Decode Type 6 coprocessor instructions.
1797 // Dm = vmov(Rt, Rt2)
1798 // <Rt, Rt2> = vmov(Dm)
1799 // Ddst = MEM(Rbase + 4*offset).
1800 // MEM(Rbase + 4*offset) = Dsrc.
DecodeType6CoprocessorIns(Instruction * instr)1801 void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
1802 VERIFY(instr->TypeValue() == 6);
1803
1804 if (instr->CoprocessorValue() == 0xA) {
1805 switch (instr->OpcodeValue()) {
1806 case 0x8:
1807 case 0xA:
1808 if (instr->HasL()) {
1809 Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1810 } else {
1811 Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1812 }
1813 break;
1814 case 0xC:
1815 case 0xE:
1816 if (instr->HasL()) {
1817 Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1818 } else {
1819 Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1820 }
1821 break;
1822 case 0x4:
1823 case 0x5:
1824 case 0x6:
1825 case 0x7:
1826 case 0x9:
1827 case 0xB: {
1828 bool to_vfp_register = (instr->VLValue() == 0x1);
1829 if (to_vfp_register) {
1830 Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
1831 } else {
1832 Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
1833 }
1834 break;
1835 }
1836 default:
1837 Unknown(instr); // Not used by V8.
1838 }
1839 } else if (instr->CoprocessorValue() == 0xB) {
1840 switch (instr->OpcodeValue()) {
1841 case 0x2:
1842 // Load and store double to two GP registers
1843 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
1844 Unknown(instr); // Not used by V8.
1845 } else if (instr->HasL()) {
1846 Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1847 } else {
1848 Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1849 }
1850 break;
1851 case 0x8:
1852 case 0xA:
1853 if (instr->HasL()) {
1854 Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1855 } else {
1856 Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1857 }
1858 break;
1859 case 0xC:
1860 case 0xE:
1861 if (instr->HasL()) {
1862 Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1863 } else {
1864 Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1865 }
1866 break;
1867 case 0x4:
1868 case 0x5:
1869 case 0x6:
1870 case 0x7:
1871 case 0x9:
1872 case 0xB: {
1873 bool to_vfp_register = (instr->VLValue() == 0x1);
1874 if (to_vfp_register) {
1875 Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
1876 } else {
1877 Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
1878 }
1879 break;
1880 }
1881 default:
1882 Unknown(instr); // Not used by V8.
1883 }
1884 } else {
1885 Unknown(instr); // Not used by V8.
1886 }
1887 }
1888
1889
1890 static const char* const barrier_option_names[] = {
1891 "invalid", "oshld", "oshst", "osh", "invalid", "nshld", "nshst", "nsh",
1892 "invalid", "ishld", "ishst", "ish", "invalid", "ld", "st", "sy",
1893 };
1894
1895
DecodeSpecialCondition(Instruction * instr)1896 void Decoder::DecodeSpecialCondition(Instruction* instr) {
1897 switch (instr->SpecialValue()) {
1898 case 4: {
1899 int Vd, Vm, Vn;
1900 if (instr->Bit(6) == 0) {
1901 Vd = instr->VFPDRegValue(kDoublePrecision);
1902 Vm = instr->VFPMRegValue(kDoublePrecision);
1903 Vn = instr->VFPNRegValue(kDoublePrecision);
1904 } else {
1905 Vd = instr->VFPDRegValue(kSimd128Precision);
1906 Vm = instr->VFPMRegValue(kSimd128Precision);
1907 Vn = instr->VFPNRegValue(kSimd128Precision);
1908 }
1909 int size = kBitsPerByte * (1 << instr->Bits(21, 20));
1910 switch (instr->Bits(11, 8)) {
1911 case 0x0: {
1912 if (instr->Bit(4) == 1) {
1913 // vqadd.s<size> Qd, Qm, Qn.
1914 out_buffer_pos_ +=
1915 SNPrintF(out_buffer_ + out_buffer_pos_,
1916 "vqadd.s%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1917 } else {
1918 Unknown(instr);
1919 }
1920 break;
1921 }
1922 case 0x1: {
1923 if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 &&
1924 instr->Bit(4) == 1) {
1925 if (Vm == Vn) {
1926 // vmov Qd, Qm
1927 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1928 "vmov q%d, q%d", Vd, Vm);
1929 } else {
1930 // vorr Qd, Qm, Qn.
1931 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1932 "vorr q%d, q%d, q%d", Vd, Vn, Vm);
1933 }
1934 } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
1935 instr->Bit(4) == 1) {
1936 // vand Qd, Qm, Qn.
1937 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1938 "vand q%d, q%d, q%d", Vd, Vn, Vm);
1939 } else {
1940 Unknown(instr);
1941 }
1942 break;
1943 }
1944 case 0x2: {
1945 if (instr->Bit(4) == 1) {
1946 // vqsub.s<size> Qd, Qm, Qn.
1947 out_buffer_pos_ +=
1948 SNPrintF(out_buffer_ + out_buffer_pos_,
1949 "vqsub.s%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1950 } else {
1951 Unknown(instr);
1952 }
1953 break;
1954 }
1955 case 0x3: {
1956 const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt";
1957 // vcge/vcgt.s<size> Qd, Qm, Qn.
1958 out_buffer_pos_ +=
1959 SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d",
1960 op, size, Vd, Vn, Vm);
1961 break;
1962 }
1963 case 0x6: {
1964 // vmin/vmax.s<size> Qd, Qm, Qn.
1965 const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax";
1966 out_buffer_pos_ +=
1967 SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d",
1968 op, size, Vd, Vn, Vm);
1969 break;
1970 }
1971 case 0x8: {
1972 const char* op = (instr->Bit(4) == 0) ? "vadd" : "vtst";
1973 // vadd/vtst.i<size> Qd, Qm, Qn.
1974 out_buffer_pos_ +=
1975 SNPrintF(out_buffer_ + out_buffer_pos_, "%s.i%d q%d, q%d, q%d",
1976 op, size, Vd, Vn, Vm);
1977 break;
1978 }
1979 case 0x9: {
1980 if (instr->Bit(6) == 1 && instr->Bit(4) == 1) {
1981 // vmul.i<size> Qd, Qm, Qn.
1982 out_buffer_pos_ +=
1983 SNPrintF(out_buffer_ + out_buffer_pos_,
1984 "vmul.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
1985 } else {
1986 Unknown(instr);
1987 }
1988 break;
1989 }
1990 case 0xA: {
1991 // vpmin/vpmax.s<size> Dd, Dm, Dn.
1992 const char* op = instr->Bit(4) == 1 ? "vpmin" : "vpmax";
1993 out_buffer_pos_ +=
1994 SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d d%d, d%d, d%d",
1995 op, size, Vd, Vn, Vm);
1996 break;
1997 }
1998 case 0xB: {
1999 // vpadd.i<size> Dd, Dm, Dn.
2000 out_buffer_pos_ +=
2001 SNPrintF(out_buffer_ + out_buffer_pos_, "vpadd.i%d d%d, d%d, d%d",
2002 size, Vd, Vn, Vm);
2003 break;
2004 }
2005 case 0xD: {
2006 if (instr->Bit(4) == 0) {
2007 const char* op = (instr->Bits(21, 20) == 0) ? "vadd" : "vsub";
2008 // vadd/vsub.f32 Qd, Qm, Qn.
2009 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2010 "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2011 } else {
2012 Unknown(instr);
2013 }
2014 break;
2015 }
2016 case 0xE: {
2017 if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) {
2018 // vceq.f32 Qd, Qm, Qn.
2019 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2020 "vceq.f32 q%d, q%d, q%d", Vd, Vn, Vm);
2021 } else {
2022 Unknown(instr);
2023 }
2024 break;
2025 }
2026 case 0xF: {
2027 if (instr->Bit(20) == 0 && instr->Bit(6) == 1) {
2028 if (instr->Bit(4) == 1) {
2029 // vrecps/vrsqrts.f32 Qd, Qm, Qn.
2030 const char* op = instr->Bit(21) == 0 ? "vrecps" : "vrsqrts";
2031 out_buffer_pos_ +=
2032 SNPrintF(out_buffer_ + out_buffer_pos_,
2033 "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2034 } else {
2035 // vmin/max.f32 Qd, Qm, Qn.
2036 const char* op = instr->Bit(21) == 1 ? "vmin" : "vmax";
2037 out_buffer_pos_ +=
2038 SNPrintF(out_buffer_ + out_buffer_pos_,
2039 "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2040 }
2041 } else {
2042 Unknown(instr);
2043 }
2044 break;
2045 }
2046 default:
2047 Unknown(instr);
2048 break;
2049 }
2050 break;
2051 }
2052 case 5:
2053 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
2054 (instr->Bit(4) == 1)) {
2055 // vmovl signed
2056 if ((instr->VdValue() & 1) != 0) Unknown(instr);
2057 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
2058 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
2059 int imm3 = instr->Bits(21, 19);
2060 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2061 "vmovl.s%d q%d, d%d", imm3 * 8, Vd, Vm);
2062 } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) {
2063 // vext.8 Qd, Qm, Qn, imm4
2064 int imm4 = instr->Bits(11, 8);
2065 int Vd = instr->VFPDRegValue(kSimd128Precision);
2066 int Vm = instr->VFPMRegValue(kSimd128Precision);
2067 int Vn = instr->VFPNRegValue(kSimd128Precision);
2068 out_buffer_pos_ +=
2069 SNPrintF(out_buffer_ + out_buffer_pos_, "vext.8 q%d, q%d, q%d, #%d",
2070 Vd, Vn, Vm, imm4);
2071 } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) {
2072 // vshl.i<size> Qd, Qm, shift
2073 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2074 int shift = instr->Bits(21, 16) - size;
2075 int Vd = instr->VFPDRegValue(kSimd128Precision);
2076 int Vm = instr->VFPMRegValue(kSimd128Precision);
2077 out_buffer_pos_ +=
2078 SNPrintF(out_buffer_ + out_buffer_pos_, "vshl.i%d q%d, q%d, #%d",
2079 size, Vd, Vm, shift);
2080 } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
2081 // vshr.s<size> Qd, Qm, shift
2082 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2083 int shift = 2 * size - instr->Bits(21, 16);
2084 int Vd = instr->VFPDRegValue(kSimd128Precision);
2085 int Vm = instr->VFPMRegValue(kSimd128Precision);
2086 out_buffer_pos_ +=
2087 SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.s%d q%d, q%d, #%d",
2088 size, Vd, Vm, shift);
2089 } else {
2090 Unknown(instr);
2091 }
2092 break;
2093 case 6: {
2094 int Vd, Vm, Vn;
2095 if (instr->Bit(6) == 0) {
2096 Vd = instr->VFPDRegValue(kDoublePrecision);
2097 Vm = instr->VFPMRegValue(kDoublePrecision);
2098 Vn = instr->VFPNRegValue(kDoublePrecision);
2099 } else {
2100 Vd = instr->VFPDRegValue(kSimd128Precision);
2101 Vm = instr->VFPMRegValue(kSimd128Precision);
2102 Vn = instr->VFPNRegValue(kSimd128Precision);
2103 }
2104 int size = kBitsPerByte * (1 << instr->Bits(21, 20));
2105 switch (instr->Bits(11, 8)) {
2106 case 0x0: {
2107 if (instr->Bit(4) == 1) {
2108 // vqadd.u<size> Qd, Qm, Qn.
2109 out_buffer_pos_ +=
2110 SNPrintF(out_buffer_ + out_buffer_pos_,
2111 "vqadd.u%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2112 } else {
2113 Unknown(instr);
2114 }
2115 break;
2116 }
2117 case 0x1: {
2118 if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) {
2119 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2120 "vbsl q%d, q%d, q%d", Vd, Vn, Vm);
2121 } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) {
2122 if (instr->Bit(6) == 0) {
2123 // veor Dd, Dn, Dm
2124 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2125 "veor d%d, d%d, d%d", Vd, Vn, Vm);
2126
2127 } else {
2128 // veor Qd, Qn, Qm
2129 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2130 "veor q%d, q%d, q%d", Vd, Vn, Vm);
2131 }
2132 } else {
2133 Unknown(instr);
2134 }
2135 break;
2136 }
2137 case 0x2: {
2138 if (instr->Bit(4) == 1) {
2139 // vqsub.u<size> Qd, Qm, Qn.
2140 out_buffer_pos_ +=
2141 SNPrintF(out_buffer_ + out_buffer_pos_,
2142 "vqsub.u%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2143 } else {
2144 Unknown(instr);
2145 }
2146 break;
2147 }
2148 case 0x3: {
2149 const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt";
2150 // vcge/vcgt.u<size> Qd, Qm, Qn.
2151 out_buffer_pos_ +=
2152 SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d",
2153 op, size, Vd, Vn, Vm);
2154 break;
2155 }
2156 case 0x6: {
2157 // vmin/vmax.u<size> Qd, Qm, Qn.
2158 const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax";
2159 out_buffer_pos_ +=
2160 SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d",
2161 op, size, Vd, Vn, Vm);
2162 break;
2163 }
2164 case 0x8: {
2165 if (instr->Bit(4) == 0) {
2166 out_buffer_pos_ +=
2167 SNPrintF(out_buffer_ + out_buffer_pos_,
2168 "vsub.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2169 } else {
2170 out_buffer_pos_ +=
2171 SNPrintF(out_buffer_ + out_buffer_pos_,
2172 "vceq.i%d q%d, q%d, q%d", size, Vd, Vn, Vm);
2173 }
2174 break;
2175 }
2176 case 0xA: {
2177 // vpmin/vpmax.u<size> Dd, Dm, Dn.
2178 const char* op = instr->Bit(4) == 1 ? "vpmin" : "vpmax";
2179 out_buffer_pos_ +=
2180 SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d d%d, d%d, d%d",
2181 op, size, Vd, Vn, Vm);
2182 break;
2183 }
2184 case 0xD: {
2185 if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
2186 instr->Bit(4) == 1) {
2187 // vmul.f32 Qd, Qm, Qn
2188 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2189 "vmul.f32 q%d, q%d, q%d", Vd, Vn, Vm);
2190 } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 0 &&
2191 instr->Bit(4) == 0) {
2192 // vpadd.f32 Dd, Dm, Dn.
2193 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2194 "vpadd.f32 d%d, d%d, d%d", Vd, Vn, Vm);
2195 } else {
2196 Unknown(instr);
2197 }
2198 break;
2199 }
2200 case 0xE: {
2201 if (instr->Bit(20) == 0 && instr->Bit(4) == 0) {
2202 const char* op = (instr->Bit(21) == 0) ? "vcge" : "vcgt";
2203 // vcge/vcgt.f32 Qd, Qm, Qn.
2204 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2205 "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
2206 } else {
2207 Unknown(instr);
2208 }
2209 break;
2210 }
2211 default:
2212 Unknown(instr);
2213 break;
2214 }
2215 break;
2216 }
2217 case 7:
2218 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
2219 (instr->Bit(4) == 1)) {
2220 // vmovl unsigned
2221 if ((instr->VdValue() & 1) != 0) Unknown(instr);
2222 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
2223 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
2224 int imm3 = instr->Bits(21, 19);
2225 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2226 "vmovl.u%d q%d, d%d", imm3 * 8, Vd, Vm);
2227 } else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) {
2228 if (instr->Bits(11, 7) == 0x18) {
2229 int Vm = instr->VFPMRegValue(kDoublePrecision);
2230 int imm4 = instr->Bits(19, 16);
2231 int size = 0, index = 0;
2232 if ((imm4 & 0x1) != 0) {
2233 size = 8;
2234 index = imm4 >> 1;
2235 } else if ((imm4 & 0x2) != 0) {
2236 size = 16;
2237 index = imm4 >> 2;
2238 } else {
2239 size = 32;
2240 index = imm4 >> 3;
2241 }
2242 if (instr->Bit(6) == 0) {
2243 int Vd = instr->VFPDRegValue(kDoublePrecision);
2244 out_buffer_pos_ +=
2245 SNPrintF(out_buffer_ + out_buffer_pos_, "vdup.%i d%d, d%d[%d]",
2246 size, Vd, Vm, index);
2247 } else {
2248 int Vd = instr->VFPDRegValue(kSimd128Precision);
2249 out_buffer_pos_ +=
2250 SNPrintF(out_buffer_ + out_buffer_pos_, "vdup.%i q%d, d%d[%d]",
2251 size, Vd, Vm, index);
2252 }
2253 } else if (instr->Bits(11, 10) == 0x2) {
2254 int Vd = instr->VFPDRegValue(kDoublePrecision);
2255 int Vn = instr->VFPNRegValue(kDoublePrecision);
2256 int Vm = instr->VFPMRegValue(kDoublePrecision);
2257 int len = instr->Bits(9, 8);
2258 NeonListOperand list(DwVfpRegister::from_code(Vn), len + 1);
2259 out_buffer_pos_ +=
2260 SNPrintF(out_buffer_ + out_buffer_pos_, "%s d%d, ",
2261 instr->Bit(6) == 0 ? "vtbl.8" : "vtbx.8", Vd);
2262 FormatNeonList(Vn, list.type());
2263 Print(", ");
2264 PrintDRegister(Vm);
2265 } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x2 &&
2266 instr->Bits(7, 6) != 0) {
2267 // vqmovn.<type><size> Dd, Qm.
2268 int Vd = instr->VFPDRegValue(kDoublePrecision);
2269 int Vm = instr->VFPMRegValue(kSimd128Precision);
2270 char type = instr->Bit(6) != 0 ? 'u' : 's';
2271 int size = 2 * kBitsPerByte * (1 << instr->Bits(19, 18));
2272 out_buffer_pos_ +=
2273 SNPrintF(out_buffer_ + out_buffer_pos_, "vqmovn.%c%i d%d, q%d",
2274 type, size, Vd, Vm);
2275 } else {
2276 int Vd, Vm;
2277 if (instr->Bit(6) == 0) {
2278 Vd = instr->VFPDRegValue(kDoublePrecision);
2279 Vm = instr->VFPMRegValue(kDoublePrecision);
2280 } else {
2281 Vd = instr->VFPDRegValue(kSimd128Precision);
2282 Vm = instr->VFPMRegValue(kSimd128Precision);
2283 }
2284 if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) {
2285 if (instr->Bit(6) == 0) {
2286 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2287 "vswp d%d, d%d", Vd, Vm);
2288 } else {
2289 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2290 "vswp q%d, q%d", Vd, Vm);
2291 }
2292 } else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) {
2293 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2294 "vmvn q%d, q%d", Vd, Vm);
2295 } else if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 &&
2296 instr->Bit(6) == 1) {
2297 const char* suffix = nullptr;
2298 int op = instr->Bits(8, 7);
2299 switch (op) {
2300 case 0:
2301 suffix = "f32.s32";
2302 break;
2303 case 1:
2304 suffix = "f32.u32";
2305 break;
2306 case 2:
2307 suffix = "s32.f32";
2308 break;
2309 case 3:
2310 suffix = "u32.f32";
2311 break;
2312 }
2313 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2314 "vcvt.%s q%d, q%d", suffix, Vd, Vm);
2315 } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x1) {
2316 int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2317 const char* op = instr->Bit(7) != 0 ? "vzip" : "vuzp";
2318 if (instr->Bit(6) == 0) {
2319 // vzip/vuzp.<size> Dd, Dm.
2320 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2321 "%s.%d d%d, d%d", op, size, Vd, Vm);
2322 } else {
2323 // vzip/vuzp.<size> Qd, Qm.
2324 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2325 "%s.%d q%d, q%d", op, size, Vd, Vm);
2326 }
2327 } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0 &&
2328 instr->Bit(6) == 1) {
2329 int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2330 int op = kBitsPerByte
2331 << (static_cast<int>(Neon64) - instr->Bits(8, 7));
2332 // vrev<op>.<size> Qd, Qm.
2333 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2334 "vrev%d.%d q%d, q%d", op, size, Vd, Vm);
2335 } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0x1) {
2336 int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2337 if (instr->Bit(6) == 0) {
2338 // vtrn.<size> Dd, Dm.
2339 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2340 "vtrn.%d d%d, d%d", size, Vd, Vm);
2341 } else {
2342 // vtrn.<size> Qd, Qm.
2343 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2344 "vtrn.%d q%d, q%d", size, Vd, Vm);
2345 }
2346 } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0 &&
2347 instr->Bit(6) == 1) {
2348 int size = kBitsPerByte * (1 << instr->Bits(19, 18));
2349 char type = instr->Bit(10) != 0 ? 'f' : 's';
2350 if (instr->Bits(9, 6) == 0xD) {
2351 // vabs<type>.<size> Qd, Qm.
2352 out_buffer_pos_ +=
2353 SNPrintF(out_buffer_ + out_buffer_pos_, "vabs.%c%d q%d, q%d",
2354 type, size, Vd, Vm);
2355 } else if (instr->Bits(9, 6) == 0xF) {
2356 // vneg<type>.<size> Qd, Qm.
2357 out_buffer_pos_ +=
2358 SNPrintF(out_buffer_ + out_buffer_pos_, "vneg.%c%d q%d, q%d",
2359 type, size, Vd, Vm);
2360 } else {
2361 Unknown(instr);
2362 }
2363 } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5 &&
2364 instr->Bit(6) == 1) {
2365 // vrecpe/vrsqrte.f32 Qd, Qm.
2366 const char* op = instr->Bit(7) == 0 ? "vrecpe" : "vrsqrte";
2367 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2368 "%s.f32 q%d, q%d", op, Vd, Vm);
2369 } else {
2370 Unknown(instr);
2371 }
2372 }
2373 } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1 &&
2374 instr->Bit(6) == 1) {
2375 // vshr.u<size> Qd, Qm, shift
2376 int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
2377 int shift = 2 * size - instr->Bits(21, 16);
2378 int Vd = instr->VFPDRegValue(kSimd128Precision);
2379 int Vm = instr->VFPMRegValue(kSimd128Precision);
2380 out_buffer_pos_ +=
2381 SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.u%d q%d, q%d, #%d",
2382 size, Vd, Vm, shift);
2383 } else if (instr->Bit(10) == 1 && instr->Bit(6) == 0 &&
2384 instr->Bit(4) == 1) {
2385 // vsli.<size> Dd, Dm, shift
2386 // vsri.<size> Dd, Dm, shift
2387 int imm7 = instr->Bits(21, 16);
2388 if (instr->Bit(7) != 0) imm7 += 64;
2389 int size = base::bits::RoundDownToPowerOfTwo32(imm7);
2390 int shift;
2391 char direction;
2392 if (instr->Bit(8) == 1) {
2393 shift = imm7 - size;
2394 direction = 'l'; // vsli
2395 } else {
2396 shift = 2 * size - imm7;
2397 direction = 'r'; // vsri
2398 }
2399 int Vd = instr->VFPDRegValue(kDoublePrecision);
2400 int Vm = instr->VFPMRegValue(kDoublePrecision);
2401 out_buffer_pos_ +=
2402 SNPrintF(out_buffer_ + out_buffer_pos_, "vs%ci.%d d%d, d%d, #%d",
2403 direction, size, Vd, Vm, shift);
2404 } else {
2405 Unknown(instr);
2406 }
2407 break;
2408 case 8:
2409 if (instr->Bits(21, 20) == 0) {
2410 // vst1
2411 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
2412 int Rn = instr->VnValue();
2413 int type = instr->Bits(11, 8);
2414 int size = instr->Bits(7, 6);
2415 int align = instr->Bits(5, 4);
2416 int Rm = instr->VmValue();
2417 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vst1.%d ",
2418 (1 << size) << 3);
2419 FormatNeonList(Vd, type);
2420 Print(", ");
2421 FormatNeonMemory(Rn, align, Rm);
2422 } else if (instr->Bits(21, 20) == 2) {
2423 // vld1
2424 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
2425 int Rn = instr->VnValue();
2426 int type = instr->Bits(11, 8);
2427 int size = instr->Bits(7, 6);
2428 int align = instr->Bits(5, 4);
2429 int Rm = instr->VmValue();
2430 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vld1.%d ",
2431 (1 << size) << 3);
2432 FormatNeonList(Vd, type);
2433 Print(", ");
2434 FormatNeonMemory(Rn, align, Rm);
2435 } else {
2436 Unknown(instr);
2437 }
2438 break;
2439 case 0xA:
2440 case 0xB:
2441 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xF)) {
2442 const char* rn_name = converter_.NameOfCPURegister(instr->Bits(19, 16));
2443 int offset = instr->Bits(11, 0);
2444 if (offset == 0) {
2445 out_buffer_pos_ +=
2446 SNPrintF(out_buffer_ + out_buffer_pos_, "pld [%s]", rn_name);
2447 } else if (instr->Bit(23) == 0) {
2448 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2449 "pld [%s, #-%d]", rn_name, offset);
2450 } else {
2451 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2452 "pld [%s, #+%d]", rn_name, offset);
2453 }
2454 } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) {
2455 int option = instr->Bits(3, 0);
2456 switch (instr->Bits(7, 4)) {
2457 case 4:
2458 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "dsb %s",
2459 barrier_option_names[option]);
2460 break;
2461 case 5:
2462 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "dmb %s",
2463 barrier_option_names[option]);
2464 break;
2465 case 6:
2466 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "isb %s",
2467 barrier_option_names[option]);
2468 break;
2469 default:
2470 Unknown(instr);
2471 }
2472 } else {
2473 Unknown(instr);
2474 }
2475 break;
2476 case 0x1D:
2477 if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 &&
2478 instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 &&
2479 instr->Bit(4) == 0x0) {
2480 // VRINTA, VRINTN, VRINTP, VRINTM (floating-point)
2481 bool dp_operation = (instr->SzValue() == 1);
2482 int rounding_mode = instr->Bits(17, 16);
2483 switch (rounding_mode) {
2484 case 0x0:
2485 if (dp_operation) {
2486 Format(instr, "vrinta.f64.f64 'Dd, 'Dm");
2487 } else {
2488 Format(instr, "vrinta.f32.f32 'Sd, 'Sm");
2489 }
2490 break;
2491 case 0x1:
2492 if (dp_operation) {
2493 Format(instr, "vrintn.f64.f64 'Dd, 'Dm");
2494 } else {
2495 Format(instr, "vrintn.f32.f32 'Sd, 'Sm");
2496 }
2497 break;
2498 case 0x2:
2499 if (dp_operation) {
2500 Format(instr, "vrintp.f64.f64 'Dd, 'Dm");
2501 } else {
2502 Format(instr, "vrintp.f32.f32 'Sd, 'Sm");
2503 }
2504 break;
2505 case 0x3:
2506 if (dp_operation) {
2507 Format(instr, "vrintm.f64.f64 'Dd, 'Dm");
2508 } else {
2509 Format(instr, "vrintm.f32.f32 'Sd, 'Sm");
2510 }
2511 break;
2512 default:
2513 UNREACHABLE(); // Case analysis is exhaustive.
2514 break;
2515 }
2516 } else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) &&
2517 (instr->Bit(4) == 0x0)) {
2518 // VMAXNM, VMINNM (floating-point)
2519 if (instr->SzValue() == 0x1) {
2520 if (instr->Bit(6) == 0x1) {
2521 Format(instr, "vminnm.f64 'Dd, 'Dn, 'Dm");
2522 } else {
2523 Format(instr, "vmaxnm.f64 'Dd, 'Dn, 'Dm");
2524 }
2525 } else {
2526 if (instr->Bit(6) == 0x1) {
2527 Format(instr, "vminnm.f32 'Sd, 'Sn, 'Sm");
2528 } else {
2529 Format(instr, "vmaxnm.f32 'Sd, 'Sn, 'Sm");
2530 }
2531 }
2532 } else {
2533 Unknown(instr);
2534 }
2535 break;
2536 case 0x1C:
2537 if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
2538 (instr->Bit(4) == 0)) {
2539 // VSEL* (floating-point)
2540 bool dp_operation = (instr->SzValue() == 1);
2541 switch (instr->Bits(21, 20)) {
2542 case 0x0:
2543 if (dp_operation) {
2544 Format(instr, "vseleq.f64 'Dd, 'Dn, 'Dm");
2545 } else {
2546 Format(instr, "vseleq.f32 'Sd, 'Sn, 'Sm");
2547 }
2548 break;
2549 case 0x1:
2550 if (dp_operation) {
2551 Format(instr, "vselvs.f64 'Dd, 'Dn, 'Dm");
2552 } else {
2553 Format(instr, "vselvs.f32 'Sd, 'Sn, 'Sm");
2554 }
2555 break;
2556 case 0x2:
2557 if (dp_operation) {
2558 Format(instr, "vselge.f64 'Dd, 'Dn, 'Dm");
2559 } else {
2560 Format(instr, "vselge.f32 'Sd, 'Sn, 'Sm");
2561 }
2562 break;
2563 case 0x3:
2564 if (dp_operation) {
2565 Format(instr, "vselgt.f64 'Dd, 'Dn, 'Dm");
2566 } else {
2567 Format(instr, "vselgt.f32 'Sd, 'Sn, 'Sm");
2568 }
2569 break;
2570 default:
2571 UNREACHABLE(); // Case analysis is exhaustive.
2572 break;
2573 }
2574 } else {
2575 Unknown(instr);
2576 }
2577 break;
2578 default:
2579 Unknown(instr);
2580 break;
2581 }
2582 }
2583
2584 #undef VERIFIY
2585
IsConstantPoolAt(byte * instr_ptr)2586 bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
2587 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2588 return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
2589 }
2590
2591
ConstantPoolSizeAt(byte * instr_ptr)2592 int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
2593 if (IsConstantPoolAt(instr_ptr)) {
2594 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2595 return DecodeConstantPoolLength(instruction_bits);
2596 } else {
2597 return -1;
2598 }
2599 }
2600
2601
2602 // Disassemble the instruction at *instr_ptr into the output buffer.
InstructionDecode(byte * instr_ptr)2603 int Decoder::InstructionDecode(byte* instr_ptr) {
2604 Instruction* instr = Instruction::At(reinterpret_cast<Address>(instr_ptr));
2605 // Print raw instruction bytes.
2606 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2607 "%08x ",
2608 instr->InstructionBits());
2609 if (instr->ConditionField() == kSpecialCondition) {
2610 DecodeSpecialCondition(instr);
2611 return kInstrSize;
2612 }
2613 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
2614 if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
2615 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
2616 "constant pool begin (length %d)",
2617 DecodeConstantPoolLength(instruction_bits));
2618 return kInstrSize;
2619 }
2620 switch (instr->TypeValue()) {
2621 case 0:
2622 case 1: {
2623 DecodeType01(instr);
2624 break;
2625 }
2626 case 2: {
2627 DecodeType2(instr);
2628 break;
2629 }
2630 case 3: {
2631 DecodeType3(instr);
2632 break;
2633 }
2634 case 4: {
2635 DecodeType4(instr);
2636 break;
2637 }
2638 case 5: {
2639 DecodeType5(instr);
2640 break;
2641 }
2642 case 6: {
2643 DecodeType6(instr);
2644 break;
2645 }
2646 case 7: {
2647 return DecodeType7(instr);
2648 }
2649 default: {
2650 // The type field is 3-bits in the ARM encoding.
2651 UNREACHABLE();
2652 break;
2653 }
2654 }
2655 return kInstrSize;
2656 }
2657
2658
2659 } // namespace internal
2660 } // namespace v8
2661
2662
2663 //------------------------------------------------------------------------------
2664
2665 namespace disasm {
2666
2667
NameOfAddress(byte * addr) const2668 const char* NameConverter::NameOfAddress(byte* addr) const {
2669 v8::internal::SNPrintF(tmp_buffer_, "%p", static_cast<void*>(addr));
2670 return tmp_buffer_.start();
2671 }
2672
2673
NameOfConstant(byte * addr) const2674 const char* NameConverter::NameOfConstant(byte* addr) const {
2675 return NameOfAddress(addr);
2676 }
2677
2678
NameOfCPURegister(int reg) const2679 const char* NameConverter::NameOfCPURegister(int reg) const {
2680 return v8::internal::GetRegConfig()->GetGeneralRegisterName(reg);
2681 }
2682
2683
NameOfByteCPURegister(int reg) const2684 const char* NameConverter::NameOfByteCPURegister(int reg) const {
2685 UNREACHABLE(); // ARM does not have the concept of a byte register
2686 return "nobytereg";
2687 }
2688
2689
NameOfXMMRegister(int reg) const2690 const char* NameConverter::NameOfXMMRegister(int reg) const {
2691 UNREACHABLE(); // ARM does not have any XMM registers
2692 return "noxmmreg";
2693 }
2694
2695
NameInCode(byte * addr) const2696 const char* NameConverter::NameInCode(byte* addr) const {
2697 // The default name converter is called for unknown code. So we will not try
2698 // to access any memory.
2699 return "";
2700 }
2701
2702
2703 //------------------------------------------------------------------------------
2704
InstructionDecode(v8::internal::Vector<char> buffer,byte * instruction)2705 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
2706 byte* instruction) {
2707 v8::internal::Decoder d(converter_, buffer);
2708 return d.InstructionDecode(instruction);
2709 }
2710
2711
ConstantPoolSizeAt(byte * instruction)2712 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
2713 return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
2714 }
2715
Disassemble(FILE * f,byte * begin,byte * end,UnimplementedOpcodeAction unimplemented_action)2716 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end,
2717 UnimplementedOpcodeAction unimplemented_action) {
2718 NameConverter converter;
2719 Disassembler d(converter, unimplemented_action);
2720 for (byte* pc = begin; pc < end;) {
2721 v8::internal::EmbeddedVector<char, 128> buffer;
2722 buffer[0] = '\0';
2723 byte* prev_pc = pc;
2724 pc += d.InstructionDecode(buffer, pc);
2725 v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc),
2726 *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
2727 }
2728 }
2729
2730 } // namespace disasm
2731
2732 #endif // V8_TARGET_ARCH_ARM
2733