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