blob: 64314837d6271a5d45533d52f7ca7660a091ab7a [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2007-2009 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28// A Disassembler object is used to disassemble a block of code instruction by
29// instruction. The default implementation of the NameConverter object can be
30// overriden to modify register names or to do symbol lookup on addresses.
31//
32// The example below will disassemble a block of code and print it to stdout.
33//
34// NameConverter converter;
35// Disassembler d(converter);
36// for (byte* pc = begin; pc < end;) {
37// char buffer[128];
38// buffer[0] = '\0';
39// byte* prev_pc = pc;
40// pc += d.InstructionDecode(buffer, sizeof buffer, pc);
41// printf("%p %08x %s\n",
42// prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
43// }
44//
45// The Disassembler class also has a convenience method to disassemble a block
46// of code into a FILE*, meaning that the above functionality could also be
47// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
48
49
50#include <assert.h>
51#include <stdio.h>
52#include <stdarg.h>
53#include <string.h>
54#ifndef WIN32
55#include <stdint.h>
56#endif
57
58#include "v8.h"
59
60#include "constants-arm.h"
61#include "disasm.h"
62#include "macro-assembler.h"
63#include "platform.h"
64
65
66namespace assembler {
67namespace arm {
68
69namespace v8i = v8::internal;
70
71
72//------------------------------------------------------------------------------
73
74// Decoder decodes and disassembles instructions into an output buffer.
75// It uses the converter to convert register names and call destinations into
76// more informative description.
77class Decoder {
78 public:
79 Decoder(const disasm::NameConverter& converter,
80 v8::internal::Vector<char> out_buffer)
81 : converter_(converter),
82 out_buffer_(out_buffer),
83 out_buffer_pos_(0) {
84 out_buffer_[out_buffer_pos_] = '\0';
85 }
86
87 ~Decoder() {}
88
89 // Writes one disassembled instruction into 'buffer' (0-terminated).
90 // Returns the length of the disassembled machine instruction in bytes.
91 int InstructionDecode(byte* instruction);
92
93 private:
94 // Bottleneck functions to print into the out_buffer.
95 void PrintChar(const char ch);
96 void Print(const char* str);
97
98 // Printing of common values.
99 void PrintRegister(int reg);
100 void PrintCondition(Instr* instr);
101 void PrintShiftRm(Instr* instr);
102 void PrintShiftImm(Instr* instr);
103 void PrintPU(Instr* instr);
104 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
105
106 // Handle formatting of instructions and their options.
107 int FormatRegister(Instr* instr, const char* option);
108 int FormatOption(Instr* instr, const char* option);
109 void Format(Instr* instr, const char* format);
110 void Unknown(Instr* instr);
111
112 // Each of these functions decodes one particular instruction type, a 3-bit
113 // field in the instruction encoding.
114 // Types 0 and 1 are combined as they are largely the same except for the way
115 // they interpret the shifter operand.
116 void DecodeType01(Instr* instr);
117 void DecodeType2(Instr* instr);
118 void DecodeType3(Instr* instr);
119 void DecodeType4(Instr* instr);
120 void DecodeType5(Instr* instr);
121 void DecodeType6(Instr* instr);
122 void DecodeType7(Instr* instr);
123 void DecodeUnconditional(Instr* instr);
124
125 const disasm::NameConverter& converter_;
126 v8::internal::Vector<char> out_buffer_;
127 int out_buffer_pos_;
128
129 DISALLOW_COPY_AND_ASSIGN(Decoder);
130};
131
132
133// Support for assertions in the Decoder formatting functions.
134#define STRING_STARTS_WITH(string, compare_string) \
135 (strncmp(string, compare_string, strlen(compare_string)) == 0)
136
137
138// Append the ch to the output buffer.
139void Decoder::PrintChar(const char ch) {
140 out_buffer_[out_buffer_pos_++] = ch;
141}
142
143
144// Append the str to the output buffer.
145void Decoder::Print(const char* str) {
146 char cur = *str++;
147 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
148 PrintChar(cur);
149 cur = *str++;
150 }
151 out_buffer_[out_buffer_pos_] = 0;
152}
153
154
155// These condition names are defined in a way to match the native disassembler
156// formatting. See for example the command "objdump -d <binary file>".
157static const char* cond_names[max_condition] = {
158 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
159 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
160};
161
162
163// Print the condition guarding the instruction.
164void Decoder::PrintCondition(Instr* instr) {
165 Print(cond_names[instr->ConditionField()]);
166}
167
168
169// Print the register name according to the active name converter.
170void Decoder::PrintRegister(int reg) {
171 Print(converter_.NameOfCPURegister(reg));
172}
173
174
175// These shift names are defined in a way to match the native disassembler
176// formatting. See for example the command "objdump -d <binary file>".
177static const char* shift_names[max_shift] = {
178 "lsl", "lsr", "asr", "ror"
179};
180
181
182// Print the register shift operands for the instruction. Generally used for
183// data processing instructions.
184void Decoder::PrintShiftRm(Instr* instr) {
185 Shift shift = instr->ShiftField();
186 int shift_amount = instr->ShiftAmountField();
187 int rm = instr->RmField();
188
189 PrintRegister(rm);
190
191 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
192 // Special case for using rm only.
193 return;
194 }
195 if (instr->RegShiftField() == 0) {
196 // by immediate
197 if ((shift == ROR) && (shift_amount == 0)) {
198 Print(", RRX");
199 return;
200 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
201 shift_amount = 32;
202 }
203 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
204 ", %s #%d",
205 shift_names[shift], shift_amount);
206 } else {
207 // by register
208 int rs = instr->RsField();
209 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
210 ", %s ", shift_names[shift]);
211 PrintRegister(rs);
212 }
213}
214
215
216// Print the immediate operand for the instruction. Generally used for data
217// processing instructions.
218void Decoder::PrintShiftImm(Instr* instr) {
219 int rotate = instr->RotateField() * 2;
220 int immed8 = instr->Immed8Field();
221 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
222 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
223 "#%d", imm);
224}
225
226
227// Print PU formatting to reduce complexity of FormatOption.
228void Decoder::PrintPU(Instr* instr) {
229 switch (instr->PUField()) {
230 case 0: {
231 Print("da");
232 break;
233 }
234 case 1: {
235 Print("ia");
236 break;
237 }
238 case 2: {
239 Print("db");
240 break;
241 }
242 case 3: {
243 Print("ib");
244 break;
245 }
246 default: {
247 UNREACHABLE();
248 break;
249 }
250 }
251}
252
253
254// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
255// the FormatOption method.
256void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
257 switch (swi) {
258 case call_rt_redirected:
259 Print("call_rt_redirected");
260 return;
261 case break_point:
262 Print("break_point");
263 return;
264 default:
265 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
266 "%d",
267 swi);
268 return;
269 }
270}
271
272
273// Handle all register based formatting in this function to reduce the
274// complexity of FormatOption.
275int Decoder::FormatRegister(Instr* instr, const char* format) {
276 ASSERT(format[0] == 'r');
277 if (format[1] == 'n') { // 'rn: Rn register
278 int reg = instr->RnField();
279 PrintRegister(reg);
280 return 2;
281 } else if (format[1] == 'd') { // 'rd: Rd register
282 int reg = instr->RdField();
283 PrintRegister(reg);
284 return 2;
285 } else if (format[1] == 's') { // 'rs: Rs register
286 int reg = instr->RsField();
287 PrintRegister(reg);
288 return 2;
289 } else if (format[1] == 'm') { // 'rm: Rm register
290 int reg = instr->RmField();
291 PrintRegister(reg);
292 return 2;
293 } else if (format[1] == 'l') {
294 // 'rlist: register list for load and store multiple instructions
295 ASSERT(STRING_STARTS_WITH(format, "rlist"));
296 int rlist = instr->RlistField();
297 int reg = 0;
298 Print("{");
299 // Print register list in ascending order, by scanning the bit mask.
300 while (rlist != 0) {
301 if ((rlist & 1) != 0) {
302 PrintRegister(reg);
303 if ((rlist >> 1) != 0) {
304 Print(", ");
305 }
306 }
307 reg++;
308 rlist >>= 1;
309 }
310 Print("}");
311 return 5;
312 }
313 UNREACHABLE();
314 return -1;
315}
316
317
318// FormatOption takes a formatting string and interprets it based on
319// the current instructions. The format string points to the first
320// character of the option string (the option escape has already been
321// consumed by the caller.) FormatOption returns the number of
322// characters that were consumed from the formatting string.
323int Decoder::FormatOption(Instr* instr, const char* format) {
324 switch (format[0]) {
325 case 'a': { // 'a: accumulate multiplies
326 if (instr->Bit(21) == 0) {
327 Print("ul");
328 } else {
329 Print("la");
330 }
331 return 1;
332 }
333 case 'b': { // 'b: byte loads or stores
334 if (instr->HasB()) {
335 Print("b");
336 }
337 return 1;
338 }
339 case 'c': { // 'cond: conditional execution
340 ASSERT(STRING_STARTS_WITH(format, "cond"));
341 PrintCondition(instr);
342 return 4;
343 }
344 case 'h': { // 'h: halfword operation for extra loads and stores
345 if (instr->HasH()) {
346 Print("h");
347 } else {
348 Print("b");
349 }
350 return 1;
351 }
352 case 'l': { // 'l: branch and link
353 if (instr->HasLink()) {
354 Print("l");
355 }
356 return 1;
357 }
358 case 'm': {
359 if (format[1] == 'e') { // 'memop: load/store instructions
360 ASSERT(STRING_STARTS_WITH(format, "memop"));
361 if (instr->HasL()) {
362 Print("ldr");
363 } else {
364 Print("str");
365 }
366 return 5;
367 }
368 // 'msg: for simulator break instructions
369 ASSERT(STRING_STARTS_WITH(format, "msg"));
370 byte* str =
371 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
372 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
373 "%s", converter_.NameInCode(str));
374 return 3;
375 }
376 case 'o': {
377 if (format[3] == '1') {
378 // 'off12: 12-bit offset for load and store instructions
379 ASSERT(STRING_STARTS_WITH(format, "off12"));
380 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
381 "%d", instr->Offset12Field());
382 return 5;
383 }
384 // 'off8: 8-bit offset for extra load and store instructions
385 ASSERT(STRING_STARTS_WITH(format, "off8"));
386 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
387 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
388 "%d", offs8);
389 return 4;
390 }
391 case 'p': { // 'pu: P and U bits for load and store instructions
392 ASSERT(STRING_STARTS_WITH(format, "pu"));
393 PrintPU(instr);
394 return 2;
395 }
396 case 'r': {
397 return FormatRegister(instr, format);
398 }
399 case 's': {
400 if (format[1] == 'h') { // 'shift_op or 'shift_rm
401 if (format[6] == 'o') { // 'shift_op
402 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
403 if (instr->TypeField() == 0) {
404 PrintShiftRm(instr);
405 } else {
406 ASSERT(instr->TypeField() == 1);
407 PrintShiftImm(instr);
408 }
409 return 8;
410 } else { // 'shift_rm
411 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
412 PrintShiftRm(instr);
413 return 8;
414 }
415 } else if (format[1] == 'w') { // 'swi
416 ASSERT(STRING_STARTS_WITH(format, "swi"));
417 PrintSoftwareInterrupt(instr->SwiField());
418 return 3;
419 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
420 ASSERT(STRING_STARTS_WITH(format, "sign"));
421 if (instr->HasSign()) {
422 Print("s");
423 }
424 return 4;
425 }
426 // 's: S field of data processing instructions
427 if (instr->HasS()) {
428 Print("s");
429 }
430 return 1;
431 }
432 case 't': { // 'target: target of branch instructions
433 ASSERT(STRING_STARTS_WITH(format, "target"));
434 int off = (instr->SImmed24Field() << 2) + 8;
435 out_buffer_pos_ += v8i::OS::SNPrintF(
436 out_buffer_ + out_buffer_pos_,
437 "%+d -> %s",
438 off,
439 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
440 return 6;
441 }
442 case 'u': { // 'u: signed or unsigned multiplies
443 // The manual gets the meaning of bit 22 backwards in the multiply
444 // instruction overview on page A3.16.2. The instructions that
445 // exist in u and s variants are the following:
446 // smull A4.1.87
447 // umull A4.1.129
448 // umlal A4.1.128
449 // smlal A4.1.76
450 // For these 0 means u and 1 means s. As can be seen on their individual
451 // pages. The other 18 mul instructions have the bit set or unset in
452 // arbitrary ways that are unrelated to the signedness of the instruction.
453 // None of these 18 instructions exist in both a 'u' and an 's' variant.
454
455 if (instr->Bit(22) == 0) {
456 Print("u");
457 } else {
458 Print("s");
459 }
460 return 1;
461 }
462 case 'w': { // 'w: W field of load and store instructions
463 if (instr->HasW()) {
464 Print("!");
465 }
466 return 1;
467 }
468 default: {
469 UNREACHABLE();
470 break;
471 }
472 }
473 UNREACHABLE();
474 return -1;
475}
476
477
478// Format takes a formatting string for a whole instruction and prints it into
479// the output buffer. All escaped options are handed to FormatOption to be
480// parsed further.
481void Decoder::Format(Instr* instr, const char* format) {
482 char cur = *format++;
483 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
484 if (cur == '\'') { // Single quote is used as the formatting escape.
485 format += FormatOption(instr, format);
486 } else {
487 out_buffer_[out_buffer_pos_++] = cur;
488 }
489 cur = *format++;
490 }
491 out_buffer_[out_buffer_pos_] = '\0';
492}
493
494
495// For currently unimplemented decodings the disassembler calls Unknown(instr)
496// which will just print "unknown" of the instruction bits.
497void Decoder::Unknown(Instr* instr) {
498 Format(instr, "unknown");
499}
500
501
502void Decoder::DecodeType01(Instr* instr) {
503 int type = instr->TypeField();
504 if ((type == 0) && instr->IsSpecialType0()) {
505 // multiply instruction or extra loads and stores
506 if (instr->Bits(7, 4) == 9) {
507 if (instr->Bit(24) == 0) {
508 // multiply instructions
509 if (instr->Bit(23) == 0) {
510 if (instr->Bit(21) == 0) {
511 // The MUL instruction description (A 4.1.33) refers to Rd as being
512 // the destination for the operation, but it confusingly uses the
513 // Rn field to encode it.
514 Format(instr, "mul'cond's 'rn, 'rm, 'rs");
515 } else {
516 // The MLA instruction description (A 4.1.28) refers to the order
517 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
518 // Rn field to encode the Rd register and the Rd field to encode
519 // the Rn register.
520 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
521 }
522 } else {
523 // The signed/long multiply instructions use the terms RdHi and RdLo
524 // when referring to the target registers. They are mapped to the Rn
525 // and Rd fields as follows:
526 // RdLo == Rd field
527 // RdHi == Rn field
528 // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
529 Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
530 }
531 } else {
532 Unknown(instr); // not used by V8
533 }
534 } else {
535 // extra load/store instructions
536 switch (instr->PUField()) {
537 case 0: {
538 if (instr->Bit(22) == 0) {
539 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
540 } else {
541 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
542 }
543 break;
544 }
545 case 1: {
546 if (instr->Bit(22) == 0) {
547 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
548 } else {
549 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
550 }
551 break;
552 }
553 case 2: {
554 if (instr->Bit(22) == 0) {
555 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
556 } else {
557 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
558 }
559 break;
560 }
561 case 3: {
562 if (instr->Bit(22) == 0) {
563 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
564 } else {
565 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
566 }
567 break;
568 }
569 default: {
570 // The PU field is a 2-bit field.
571 UNREACHABLE();
572 break;
573 }
574 }
575 return;
576 }
577 } else {
578 switch (instr->OpcodeField()) {
579 case AND: {
580 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
581 break;
582 }
583 case EOR: {
584 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
585 break;
586 }
587 case SUB: {
588 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
589 break;
590 }
591 case RSB: {
592 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
593 break;
594 }
595 case ADD: {
596 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
597 break;
598 }
599 case ADC: {
600 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
601 break;
602 }
603 case SBC: {
604 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
605 break;
606 }
607 case RSC: {
608 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
609 break;
610 }
611 case TST: {
612 if (instr->HasS()) {
613 Format(instr, "tst'cond 'rn, 'shift_op");
614 } else {
615 Unknown(instr); // not used by V8
616 }
617 break;
618 }
619 case TEQ: {
620 if (instr->HasS()) {
621 Format(instr, "teq'cond 'rn, 'shift_op");
622 } else {
623 switch (instr->Bits(7, 4)) {
624 case BX:
625 Format(instr, "bx'cond 'rm");
626 break;
627 case BLX:
628 Format(instr, "blx'cond 'rm");
629 break;
630 default:
631 Unknown(instr); // not used by V8
632 break;
633 }
634 }
635 break;
636 }
637 case CMP: {
638 if (instr->HasS()) {
639 Format(instr, "cmp'cond 'rn, 'shift_op");
640 } else {
641 Unknown(instr); // not used by V8
642 }
643 break;
644 }
645 case CMN: {
646 if (instr->HasS()) {
647 Format(instr, "cmn'cond 'rn, 'shift_op");
648 } else {
649 switch (instr->Bits(7, 4)) {
650 case CLZ:
651 Format(instr, "clz'cond 'rd, 'rm");
652 break;
653 default:
654 Unknown(instr); // not used by V8
655 break;
656 }
657 }
658 break;
659 }
660 case ORR: {
661 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
662 break;
663 }
664 case MOV: {
665 Format(instr, "mov'cond's 'rd, 'shift_op");
666 break;
667 }
668 case BIC: {
669 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
670 break;
671 }
672 case MVN: {
673 Format(instr, "mvn'cond's 'rd, 'shift_op");
674 break;
675 }
676 default: {
677 // The Opcode field is a 4-bit field.
678 UNREACHABLE();
679 break;
680 }
681 }
682 }
683}
684
685
686void Decoder::DecodeType2(Instr* instr) {
687 switch (instr->PUField()) {
688 case 0: {
689 if (instr->HasW()) {
690 Unknown(instr); // not used in V8
691 }
692 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
693 break;
694 }
695 case 1: {
696 if (instr->HasW()) {
697 Unknown(instr); // not used in V8
698 }
699 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
700 break;
701 }
702 case 2: {
703 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
704 break;
705 }
706 case 3: {
707 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
708 break;
709 }
710 default: {
711 // The PU field is a 2-bit field.
712 UNREACHABLE();
713 break;
714 }
715 }
716}
717
718
719void Decoder::DecodeType3(Instr* instr) {
720 switch (instr->PUField()) {
721 case 0: {
722 ASSERT(!instr->HasW());
723 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
724 break;
725 }
726 case 1: {
727 ASSERT(!instr->HasW());
728 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
729 break;
730 }
731 case 2: {
732 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
733 break;
734 }
735 case 3: {
736 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
737 break;
738 }
739 default: {
740 // The PU field is a 2-bit field.
741 UNREACHABLE();
742 break;
743 }
744 }
745}
746
747
748void Decoder::DecodeType4(Instr* instr) {
749 ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported.
750 if (instr->HasL()) {
751 Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
752 } else {
753 Format(instr, "stm'cond'pu 'rn'w, 'rlist");
754 }
755}
756
757
758void Decoder::DecodeType5(Instr* instr) {
759 Format(instr, "b'l'cond 'target");
760}
761
762
763void Decoder::DecodeType6(Instr* instr) {
764 // Coprocessor instructions currently not supported.
765 Unknown(instr);
766}
767
768
769void Decoder::DecodeType7(Instr* instr) {
770 if (instr->Bit(24) == 1) {
771 Format(instr, "swi'cond 'swi");
772 } else {
773 // Coprocessor instructions currently not supported.
774 Unknown(instr);
775 }
776}
777
778
779void Decoder::DecodeUnconditional(Instr* instr) {
780 if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) {
781 Format(instr, "'memop'h'pu 'rd, ");
782 bool immediate = instr->HasB();
783 switch (instr->PUField()) {
784 case 0: {
785 // Post index, negative.
786 if (instr->HasW()) {
787 Unknown(instr);
788 break;
789 }
790 if (immediate) {
791 Format(instr, "['rn], #-'imm12");
792 } else {
793 Format(instr, "['rn], -'rm");
794 }
795 break;
796 }
797 case 1: {
798 // Post index, positive.
799 if (instr->HasW()) {
800 Unknown(instr);
801 break;
802 }
803 if (immediate) {
804 Format(instr, "['rn], #+'imm12");
805 } else {
806 Format(instr, "['rn], +'rm");
807 }
808 break;
809 }
810 case 2: {
811 // Pre index or offset, negative.
812 if (immediate) {
813 Format(instr, "['rn, #-'imm12]'w");
814 } else {
815 Format(instr, "['rn, -'rm]'w");
816 }
817 break;
818 }
819 case 3: {
820 // Pre index or offset, positive.
821 if (immediate) {
822 Format(instr, "['rn, #+'imm12]'w");
823 } else {
824 Format(instr, "['rn, +'rm]'w");
825 }
826 break;
827 }
828 default: {
829 // The PU field is a 2-bit field.
830 UNREACHABLE();
831 break;
832 }
833 }
834 return;
835 }
836 Format(instr, "break 'msg");
837}
838
839
840// Disassemble the instruction at *instr_ptr into the output buffer.
841int Decoder::InstructionDecode(byte* instr_ptr) {
842 Instr* instr = Instr::At(instr_ptr);
843 // Print raw instruction bytes.
844 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
845 "%08x ",
846 instr->InstructionBits());
847 if (instr->ConditionField() == special_condition) {
848 DecodeUnconditional(instr);
849 return Instr::kInstrSize;
850 }
851 switch (instr->TypeField()) {
852 case 0:
853 case 1: {
854 DecodeType01(instr);
855 break;
856 }
857 case 2: {
858 DecodeType2(instr);
859 break;
860 }
861 case 3: {
862 DecodeType3(instr);
863 break;
864 }
865 case 4: {
866 DecodeType4(instr);
867 break;
868 }
869 case 5: {
870 DecodeType5(instr);
871 break;
872 }
873 case 6: {
874 DecodeType6(instr);
875 break;
876 }
877 case 7: {
878 DecodeType7(instr);
879 break;
880 }
881 default: {
882 // The type field is 3-bits in the ARM encoding.
883 UNREACHABLE();
884 break;
885 }
886 }
887 return Instr::kInstrSize;
888}
889
890
891} } // namespace assembler::arm
892
893
894
895//------------------------------------------------------------------------------
896
897namespace disasm {
898
899namespace v8i = v8::internal;
900
901
902const char* NameConverter::NameOfAddress(byte* addr) const {
903 static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
904 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
905 return tmp_buffer.start();
906}
907
908
909const char* NameConverter::NameOfConstant(byte* addr) const {
910 return NameOfAddress(addr);
911}
912
913
914const char* NameConverter::NameOfCPURegister(int reg) const {
915 return assembler::arm::Registers::Name(reg);
916}
917
918
919const char* NameConverter::NameOfByteCPURegister(int reg) const {
920 UNREACHABLE(); // ARM does not have the concept of a byte register
921 return "nobytereg";
922}
923
924
925const char* NameConverter::NameOfXMMRegister(int reg) const {
926 UNREACHABLE(); // ARM does not have any XMM registers
927 return "noxmmreg";
928}
929
930
931const char* NameConverter::NameInCode(byte* addr) const {
932 // The default name converter is called for unknown code. So we will not try
933 // to access any memory.
934 return "";
935}
936
937
938//------------------------------------------------------------------------------
939
940Disassembler::Disassembler(const NameConverter& converter)
941 : converter_(converter) {}
942
943
944Disassembler::~Disassembler() {}
945
946
947int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
948 byte* instruction) {
949 assembler::arm::Decoder d(converter_, buffer);
950 return d.InstructionDecode(instruction);
951}
952
953
954int Disassembler::ConstantPoolSizeAt(byte* instruction) {
955 int instruction_bits = *(reinterpret_cast<int*>(instruction));
956 if ((instruction_bits & 0xfff00000) == 0x03000000) {
957 return instruction_bits & 0x0000ffff;
958 } else {
959 return -1;
960 }
961}
962
963
964void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
965 NameConverter converter;
966 Disassembler d(converter);
967 for (byte* pc = begin; pc < end;) {
968 v8::internal::EmbeddedVector<char, 128> buffer;
969 buffer[0] = '\0';
970 byte* prev_pc = pc;
971 pc += d.InstructionDecode(buffer, pc);
972 fprintf(f, "%p %08x %s\n",
973 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
974 }
975}
976
977
978} // namespace disasm