blob: 127c160863c50ed6f02a50450630125986e39a13 [file] [log] [blame]
Leon Clarked91b9f72010-01-27 17:25:45 +00001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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);
Steve Blockd0582a62009-12-15 09:54:21 +0000100 void PrintSRegister(int reg);
101 void PrintDRegister(int reg);
102 int FormatVFPRegister(Instr* instr, const char* format);
103 int FormatVFPinstruction(Instr* instr, const char* format);
Steve Blocka7e24c12009-10-30 11:49:00 +0000104 void PrintCondition(Instr* instr);
105 void PrintShiftRm(Instr* instr);
106 void PrintShiftImm(Instr* instr);
107 void PrintPU(Instr* instr);
108 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
109
110 // Handle formatting of instructions and their options.
111 int FormatRegister(Instr* instr, const char* option);
112 int FormatOption(Instr* instr, const char* option);
113 void Format(Instr* instr, const char* format);
114 void Unknown(Instr* instr);
115
116 // Each of these functions decodes one particular instruction type, a 3-bit
117 // field in the instruction encoding.
118 // Types 0 and 1 are combined as they are largely the same except for the way
119 // they interpret the shifter operand.
120 void DecodeType01(Instr* instr);
121 void DecodeType2(Instr* instr);
122 void DecodeType3(Instr* instr);
123 void DecodeType4(Instr* instr);
124 void DecodeType5(Instr* instr);
125 void DecodeType6(Instr* instr);
126 void DecodeType7(Instr* instr);
127 void DecodeUnconditional(Instr* instr);
Steve Blockd0582a62009-12-15 09:54:21 +0000128 // For VFP support.
129 void DecodeTypeVFP(Instr* instr);
130 void DecodeType6CoprocessorIns(Instr* instr);
131
Steve Blocka7e24c12009-10-30 11:49:00 +0000132
133 const disasm::NameConverter& converter_;
134 v8::internal::Vector<char> out_buffer_;
135 int out_buffer_pos_;
136
137 DISALLOW_COPY_AND_ASSIGN(Decoder);
138};
139
140
141// Support for assertions in the Decoder formatting functions.
142#define STRING_STARTS_WITH(string, compare_string) \
143 (strncmp(string, compare_string, strlen(compare_string)) == 0)
144
145
146// Append the ch to the output buffer.
147void Decoder::PrintChar(const char ch) {
148 out_buffer_[out_buffer_pos_++] = ch;
149}
150
151
152// Append the str to the output buffer.
153void Decoder::Print(const char* str) {
154 char cur = *str++;
155 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
156 PrintChar(cur);
157 cur = *str++;
158 }
159 out_buffer_[out_buffer_pos_] = 0;
160}
161
162
163// These condition names are defined in a way to match the native disassembler
164// formatting. See for example the command "objdump -d <binary file>".
165static const char* cond_names[max_condition] = {
166 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
167 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
168};
169
170
171// Print the condition guarding the instruction.
172void Decoder::PrintCondition(Instr* instr) {
173 Print(cond_names[instr->ConditionField()]);
174}
175
176
177// Print the register name according to the active name converter.
178void Decoder::PrintRegister(int reg) {
179 Print(converter_.NameOfCPURegister(reg));
180}
181
Steve Blockd0582a62009-12-15 09:54:21 +0000182// Print the VFP S register name according to the active name converter.
183void Decoder::PrintSRegister(int reg) {
184 Print(assembler::arm::VFPRegisters::Name(reg));
185}
186
187// Print the VFP D register name according to the active name converter.
188void Decoder::PrintDRegister(int reg) {
189 Print(assembler::arm::VFPRegisters::Name(reg + 32));
190}
191
Steve Blocka7e24c12009-10-30 11:49:00 +0000192
193// These shift names are defined in a way to match the native disassembler
194// formatting. See for example the command "objdump -d <binary file>".
195static const char* shift_names[max_shift] = {
196 "lsl", "lsr", "asr", "ror"
197};
198
199
200// Print the register shift operands for the instruction. Generally used for
201// data processing instructions.
202void Decoder::PrintShiftRm(Instr* instr) {
203 Shift shift = instr->ShiftField();
204 int shift_amount = instr->ShiftAmountField();
205 int rm = instr->RmField();
206
207 PrintRegister(rm);
208
209 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
210 // Special case for using rm only.
211 return;
212 }
213 if (instr->RegShiftField() == 0) {
214 // by immediate
215 if ((shift == ROR) && (shift_amount == 0)) {
216 Print(", RRX");
217 return;
218 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
219 shift_amount = 32;
220 }
221 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
222 ", %s #%d",
223 shift_names[shift], shift_amount);
224 } else {
225 // by register
226 int rs = instr->RsField();
227 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
228 ", %s ", shift_names[shift]);
229 PrintRegister(rs);
230 }
231}
232
233
234// Print the immediate operand for the instruction. Generally used for data
235// processing instructions.
236void Decoder::PrintShiftImm(Instr* instr) {
237 int rotate = instr->RotateField() * 2;
238 int immed8 = instr->Immed8Field();
239 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
240 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
241 "#%d", imm);
242}
243
244
245// Print PU formatting to reduce complexity of FormatOption.
246void Decoder::PrintPU(Instr* instr) {
247 switch (instr->PUField()) {
248 case 0: {
249 Print("da");
250 break;
251 }
252 case 1: {
253 Print("ia");
254 break;
255 }
256 case 2: {
257 Print("db");
258 break;
259 }
260 case 3: {
261 Print("ib");
262 break;
263 }
264 default: {
265 UNREACHABLE();
266 break;
267 }
268 }
269}
270
271
272// Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
273// the FormatOption method.
274void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
275 switch (swi) {
276 case call_rt_redirected:
277 Print("call_rt_redirected");
278 return;
279 case break_point:
280 Print("break_point");
281 return;
282 default:
283 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
284 "%d",
285 swi);
286 return;
287 }
288}
289
290
291// Handle all register based formatting in this function to reduce the
292// complexity of FormatOption.
293int Decoder::FormatRegister(Instr* instr, const char* format) {
294 ASSERT(format[0] == 'r');
295 if (format[1] == 'n') { // 'rn: Rn register
296 int reg = instr->RnField();
297 PrintRegister(reg);
298 return 2;
299 } else if (format[1] == 'd') { // 'rd: Rd register
300 int reg = instr->RdField();
301 PrintRegister(reg);
302 return 2;
303 } else if (format[1] == 's') { // 'rs: Rs register
304 int reg = instr->RsField();
305 PrintRegister(reg);
306 return 2;
307 } else if (format[1] == 'm') { // 'rm: Rm register
308 int reg = instr->RmField();
309 PrintRegister(reg);
310 return 2;
Steve Blockd0582a62009-12-15 09:54:21 +0000311 } else if (format[1] == 't') { // 'rt: Rt register
312 int reg = instr->RtField();
313 PrintRegister(reg);
314 return 2;
Steve Blocka7e24c12009-10-30 11:49:00 +0000315 } else if (format[1] == 'l') {
316 // 'rlist: register list for load and store multiple instructions
317 ASSERT(STRING_STARTS_WITH(format, "rlist"));
318 int rlist = instr->RlistField();
319 int reg = 0;
320 Print("{");
321 // Print register list in ascending order, by scanning the bit mask.
322 while (rlist != 0) {
323 if ((rlist & 1) != 0) {
324 PrintRegister(reg);
325 if ((rlist >> 1) != 0) {
326 Print(", ");
327 }
328 }
329 reg++;
330 rlist >>= 1;
331 }
332 Print("}");
333 return 5;
334 }
335 UNREACHABLE();
336 return -1;
337}
338
339
Steve Blockd0582a62009-12-15 09:54:21 +0000340// Handle all VFP register based formatting in this function to reduce the
341// complexity of FormatOption.
342int Decoder::FormatVFPRegister(Instr* instr, const char* format) {
343 ASSERT((format[0] == 'S') || (format[0] == 'D'));
344
345 if (format[1] == 'n') {
346 int reg = instr->VnField();
347 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField()));
348 if (format[0] == 'D') PrintDRegister(reg);
349 return 2;
350 } else if (format[1] == 'm') {
351 int reg = instr->VmField();
352 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->MField()));
353 if (format[0] == 'D') PrintDRegister(reg);
354 return 2;
355 } else if (format[1] == 'd') {
356 int reg = instr->VdField();
357 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->DField()));
358 if (format[0] == 'D') PrintDRegister(reg);
359 return 2;
360 }
361
362 UNREACHABLE();
363 return -1;
364}
365
366
367int Decoder::FormatVFPinstruction(Instr* instr, const char* format) {
368 Print(format);
369 return 0;
370}
371
372
Steve Blocka7e24c12009-10-30 11:49:00 +0000373// FormatOption takes a formatting string and interprets it based on
374// the current instructions. The format string points to the first
375// character of the option string (the option escape has already been
376// consumed by the caller.) FormatOption returns the number of
377// characters that were consumed from the formatting string.
378int Decoder::FormatOption(Instr* instr, const char* format) {
379 switch (format[0]) {
380 case 'a': { // 'a: accumulate multiplies
381 if (instr->Bit(21) == 0) {
382 Print("ul");
383 } else {
384 Print("la");
385 }
386 return 1;
387 }
388 case 'b': { // 'b: byte loads or stores
389 if (instr->HasB()) {
390 Print("b");
391 }
392 return 1;
393 }
394 case 'c': { // 'cond: conditional execution
395 ASSERT(STRING_STARTS_WITH(format, "cond"));
396 PrintCondition(instr);
397 return 4;
398 }
399 case 'h': { // 'h: halfword operation for extra loads and stores
400 if (instr->HasH()) {
401 Print("h");
402 } else {
403 Print("b");
404 }
405 return 1;
406 }
407 case 'l': { // 'l: branch and link
408 if (instr->HasLink()) {
409 Print("l");
410 }
411 return 1;
412 }
413 case 'm': {
414 if (format[1] == 'e') { // 'memop: load/store instructions
415 ASSERT(STRING_STARTS_WITH(format, "memop"));
416 if (instr->HasL()) {
417 Print("ldr");
418 } else {
419 Print("str");
420 }
421 return 5;
422 }
423 // 'msg: for simulator break instructions
424 ASSERT(STRING_STARTS_WITH(format, "msg"));
425 byte* str =
426 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
427 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
428 "%s", converter_.NameInCode(str));
429 return 3;
430 }
431 case 'o': {
Andrei Popescu31002712010-02-23 13:46:05 +0000432 if ((format[3] == '1') && (format[4] == '2')) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 // 'off12: 12-bit offset for load and store instructions
434 ASSERT(STRING_STARTS_WITH(format, "off12"));
435 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
436 "%d", instr->Offset12Field());
437 return 5;
Andrei Popescu31002712010-02-23 13:46:05 +0000438 } else if ((format[3] == '1') && (format[4] == '6')) {
439 ASSERT(STRING_STARTS_WITH(format, "off16to20"));
440 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
441 "%d", instr->Bits(20, 16) +1);
442 return 9;
443 } else if (format[3] == '7') {
444 ASSERT(STRING_STARTS_WITH(format, "off7to11"));
445 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
446 "%d", instr->ShiftAmountField());
447 return 8;
Steve Blocka7e24c12009-10-30 11:49:00 +0000448 }
449 // 'off8: 8-bit offset for extra load and store instructions
450 ASSERT(STRING_STARTS_WITH(format, "off8"));
451 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
452 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
453 "%d", offs8);
454 return 4;
455 }
456 case 'p': { // 'pu: P and U bits for load and store instructions
457 ASSERT(STRING_STARTS_WITH(format, "pu"));
458 PrintPU(instr);
459 return 2;
460 }
461 case 'r': {
462 return FormatRegister(instr, format);
463 }
464 case 's': {
465 if (format[1] == 'h') { // 'shift_op or 'shift_rm
466 if (format[6] == 'o') { // 'shift_op
467 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
468 if (instr->TypeField() == 0) {
469 PrintShiftRm(instr);
470 } else {
471 ASSERT(instr->TypeField() == 1);
472 PrintShiftImm(instr);
473 }
474 return 8;
475 } else { // 'shift_rm
476 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
477 PrintShiftRm(instr);
478 return 8;
479 }
480 } else if (format[1] == 'w') { // 'swi
481 ASSERT(STRING_STARTS_WITH(format, "swi"));
482 PrintSoftwareInterrupt(instr->SwiField());
483 return 3;
484 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
485 ASSERT(STRING_STARTS_WITH(format, "sign"));
486 if (instr->HasSign()) {
487 Print("s");
488 }
489 return 4;
490 }
491 // 's: S field of data processing instructions
492 if (instr->HasS()) {
493 Print("s");
494 }
495 return 1;
496 }
497 case 't': { // 'target: target of branch instructions
498 ASSERT(STRING_STARTS_WITH(format, "target"));
499 int off = (instr->SImmed24Field() << 2) + 8;
500 out_buffer_pos_ += v8i::OS::SNPrintF(
501 out_buffer_ + out_buffer_pos_,
502 "%+d -> %s",
503 off,
504 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
505 return 6;
506 }
507 case 'u': { // 'u: signed or unsigned multiplies
508 // The manual gets the meaning of bit 22 backwards in the multiply
509 // instruction overview on page A3.16.2. The instructions that
510 // exist in u and s variants are the following:
511 // smull A4.1.87
512 // umull A4.1.129
513 // umlal A4.1.128
514 // smlal A4.1.76
515 // For these 0 means u and 1 means s. As can be seen on their individual
516 // pages. The other 18 mul instructions have the bit set or unset in
517 // arbitrary ways that are unrelated to the signedness of the instruction.
518 // None of these 18 instructions exist in both a 'u' and an 's' variant.
519
520 if (instr->Bit(22) == 0) {
521 Print("u");
522 } else {
523 Print("s");
524 }
525 return 1;
526 }
Steve Blockd0582a62009-12-15 09:54:21 +0000527 case 'v': {
528 return FormatVFPinstruction(instr, format);
529 }
530 case 'S':
531 case 'D': {
532 return FormatVFPRegister(instr, format);
533 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000534 case 'w': { // 'w: W field of load and store instructions
535 if (instr->HasW()) {
536 Print("!");
537 }
538 return 1;
539 }
540 default: {
541 UNREACHABLE();
542 break;
543 }
544 }
545 UNREACHABLE();
546 return -1;
547}
548
549
550// Format takes a formatting string for a whole instruction and prints it into
551// the output buffer. All escaped options are handed to FormatOption to be
552// parsed further.
553void Decoder::Format(Instr* instr, const char* format) {
554 char cur = *format++;
555 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
556 if (cur == '\'') { // Single quote is used as the formatting escape.
557 format += FormatOption(instr, format);
558 } else {
559 out_buffer_[out_buffer_pos_++] = cur;
560 }
561 cur = *format++;
562 }
563 out_buffer_[out_buffer_pos_] = '\0';
564}
565
566
567// For currently unimplemented decodings the disassembler calls Unknown(instr)
568// which will just print "unknown" of the instruction bits.
569void Decoder::Unknown(Instr* instr) {
570 Format(instr, "unknown");
571}
572
573
574void Decoder::DecodeType01(Instr* instr) {
575 int type = instr->TypeField();
576 if ((type == 0) && instr->IsSpecialType0()) {
577 // multiply instruction or extra loads and stores
578 if (instr->Bits(7, 4) == 9) {
579 if (instr->Bit(24) == 0) {
580 // multiply instructions
581 if (instr->Bit(23) == 0) {
582 if (instr->Bit(21) == 0) {
583 // The MUL instruction description (A 4.1.33) refers to Rd as being
584 // the destination for the operation, but it confusingly uses the
585 // Rn field to encode it.
586 Format(instr, "mul'cond's 'rn, 'rm, 'rs");
587 } else {
588 // The MLA instruction description (A 4.1.28) refers to the order
589 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
590 // Rn field to encode the Rd register and the Rd field to encode
591 // the Rn register.
592 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
593 }
594 } else {
595 // The signed/long multiply instructions use the terms RdHi and RdLo
596 // when referring to the target registers. They are mapped to the Rn
597 // and Rd fields as follows:
598 // RdLo == Rd field
599 // RdHi == Rn field
600 // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
601 Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
602 }
603 } else {
604 Unknown(instr); // not used by V8
605 }
606 } else {
607 // extra load/store instructions
608 switch (instr->PUField()) {
609 case 0: {
610 if (instr->Bit(22) == 0) {
611 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
612 } else {
613 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
614 }
615 break;
616 }
617 case 1: {
618 if (instr->Bit(22) == 0) {
619 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
620 } else {
621 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
622 }
623 break;
624 }
625 case 2: {
626 if (instr->Bit(22) == 0) {
627 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
628 } else {
629 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
630 }
631 break;
632 }
633 case 3: {
634 if (instr->Bit(22) == 0) {
635 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
636 } else {
637 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
638 }
639 break;
640 }
641 default: {
642 // The PU field is a 2-bit field.
643 UNREACHABLE();
644 break;
645 }
646 }
647 return;
648 }
649 } else {
650 switch (instr->OpcodeField()) {
651 case AND: {
652 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
653 break;
654 }
655 case EOR: {
656 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
657 break;
658 }
659 case SUB: {
660 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
661 break;
662 }
663 case RSB: {
664 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
665 break;
666 }
667 case ADD: {
668 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
669 break;
670 }
671 case ADC: {
672 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
673 break;
674 }
675 case SBC: {
676 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
677 break;
678 }
679 case RSC: {
680 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
681 break;
682 }
683 case TST: {
684 if (instr->HasS()) {
685 Format(instr, "tst'cond 'rn, 'shift_op");
686 } else {
687 Unknown(instr); // not used by V8
688 }
689 break;
690 }
691 case TEQ: {
692 if (instr->HasS()) {
693 Format(instr, "teq'cond 'rn, 'shift_op");
694 } else {
695 switch (instr->Bits(7, 4)) {
696 case BX:
697 Format(instr, "bx'cond 'rm");
698 break;
699 case BLX:
700 Format(instr, "blx'cond 'rm");
701 break;
702 default:
703 Unknown(instr); // not used by V8
704 break;
705 }
706 }
707 break;
708 }
709 case CMP: {
710 if (instr->HasS()) {
711 Format(instr, "cmp'cond 'rn, 'shift_op");
712 } else {
713 Unknown(instr); // not used by V8
714 }
715 break;
716 }
717 case CMN: {
718 if (instr->HasS()) {
719 Format(instr, "cmn'cond 'rn, 'shift_op");
720 } else {
721 switch (instr->Bits(7, 4)) {
722 case CLZ:
723 Format(instr, "clz'cond 'rd, 'rm");
724 break;
725 default:
726 Unknown(instr); // not used by V8
727 break;
728 }
729 }
730 break;
731 }
732 case ORR: {
733 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
734 break;
735 }
736 case MOV: {
737 Format(instr, "mov'cond's 'rd, 'shift_op");
738 break;
739 }
740 case BIC: {
741 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
742 break;
743 }
744 case MVN: {
745 Format(instr, "mvn'cond's 'rd, 'shift_op");
746 break;
747 }
748 default: {
749 // The Opcode field is a 4-bit field.
750 UNREACHABLE();
751 break;
752 }
753 }
754 }
755}
756
757
758void Decoder::DecodeType2(Instr* instr) {
759 switch (instr->PUField()) {
760 case 0: {
761 if (instr->HasW()) {
762 Unknown(instr); // not used in V8
763 }
764 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
765 break;
766 }
767 case 1: {
768 if (instr->HasW()) {
769 Unknown(instr); // not used in V8
770 }
771 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
772 break;
773 }
774 case 2: {
775 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
776 break;
777 }
778 case 3: {
779 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
780 break;
781 }
782 default: {
783 // The PU field is a 2-bit field.
784 UNREACHABLE();
785 break;
786 }
787 }
788}
789
790
791void Decoder::DecodeType3(Instr* instr) {
792 switch (instr->PUField()) {
793 case 0: {
794 ASSERT(!instr->HasW());
795 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
796 break;
797 }
798 case 1: {
799 ASSERT(!instr->HasW());
800 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
801 break;
802 }
803 case 2: {
804 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
805 break;
806 }
807 case 3: {
Andrei Popescu31002712010-02-23 13:46:05 +0000808 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
809 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
810 uint32_t lsbit = static_cast<uint32_t>(instr->ShiftAmountField());
811 uint32_t msbit = widthminus1 + lsbit;
812 if (msbit <= 31) {
813 Format(instr, "ubfx'cond 'rd, 'rm, #'off7to11, #'off16to20");
814 } else {
815 UNREACHABLE();
816 }
817 } else {
818 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
819 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000820 break;
821 }
822 default: {
823 // The PU field is a 2-bit field.
824 UNREACHABLE();
825 break;
826 }
827 }
828}
829
830
831void Decoder::DecodeType4(Instr* instr) {
832 ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported.
833 if (instr->HasL()) {
834 Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
835 } else {
836 Format(instr, "stm'cond'pu 'rn'w, 'rlist");
837 }
838}
839
840
841void Decoder::DecodeType5(Instr* instr) {
842 Format(instr, "b'l'cond 'target");
843}
844
845
846void Decoder::DecodeType6(Instr* instr) {
Steve Blockd0582a62009-12-15 09:54:21 +0000847 DecodeType6CoprocessorIns(instr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000848}
849
850
851void Decoder::DecodeType7(Instr* instr) {
852 if (instr->Bit(24) == 1) {
853 Format(instr, "swi'cond 'swi");
854 } else {
Steve Blockd0582a62009-12-15 09:54:21 +0000855 DecodeTypeVFP(instr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 }
857}
858
Steve Blocka7e24c12009-10-30 11:49:00 +0000859void Decoder::DecodeUnconditional(Instr* instr) {
860 if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) {
861 Format(instr, "'memop'h'pu 'rd, ");
862 bool immediate = instr->HasB();
863 switch (instr->PUField()) {
864 case 0: {
865 // Post index, negative.
866 if (instr->HasW()) {
867 Unknown(instr);
868 break;
869 }
870 if (immediate) {
871 Format(instr, "['rn], #-'imm12");
872 } else {
873 Format(instr, "['rn], -'rm");
874 }
875 break;
876 }
877 case 1: {
878 // Post index, positive.
879 if (instr->HasW()) {
880 Unknown(instr);
881 break;
882 }
883 if (immediate) {
884 Format(instr, "['rn], #+'imm12");
885 } else {
886 Format(instr, "['rn], +'rm");
887 }
888 break;
889 }
890 case 2: {
891 // Pre index or offset, negative.
892 if (immediate) {
893 Format(instr, "['rn, #-'imm12]'w");
894 } else {
895 Format(instr, "['rn, -'rm]'w");
896 }
897 break;
898 }
899 case 3: {
900 // Pre index or offset, positive.
901 if (immediate) {
902 Format(instr, "['rn, #+'imm12]'w");
903 } else {
904 Format(instr, "['rn, +'rm]'w");
905 }
906 break;
907 }
908 default: {
909 // The PU field is a 2-bit field.
910 UNREACHABLE();
911 break;
912 }
913 }
914 return;
915 }
916 Format(instr, "break 'msg");
917}
918
919
Steve Blockd0582a62009-12-15 09:54:21 +0000920// void Decoder::DecodeTypeVFP(Instr* instr)
Leon Clarkee46be812010-01-19 14:06:41 +0000921// vmov: Sn = Rt
922// vmov: Rt = Sn
923// vcvt: Dd = Sm
924// vcvt: Sd = Dm
925// Dd = vadd(Dn, Dm)
926// Dd = vsub(Dn, Dm)
927// Dd = vmul(Dn, Dm)
928// Dd = vdiv(Dn, Dm)
Steve Blockd0582a62009-12-15 09:54:21 +0000929// vcmp(Dd, Dm)
930// VMRS
931void Decoder::DecodeTypeVFP(Instr* instr) {
932 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
933
934 if (instr->Bit(23) == 1) {
935 if ((instr->Bits(21, 19) == 0x7) &&
936 (instr->Bits(18, 16) == 0x5) &&
937 (instr->Bits(11, 9) == 0x5) &&
938 (instr->Bit(8) == 1) &&
939 (instr->Bit(6) == 1) &&
940 (instr->Bit(4) == 0)) {
941 Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
942 } else if ((instr->Bits(21, 19) == 0x7) &&
943 (instr->Bits(18, 16) == 0x0) &&
944 (instr->Bits(11, 9) == 0x5) &&
945 (instr->Bit(8) == 1) &&
946 (instr->Bit(7) == 1) &&
947 (instr->Bit(6) == 1) &&
948 (instr->Bit(4) == 0)) {
949 Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
950 } else if ((instr->Bit(21) == 0x0) &&
951 (instr->Bit(20) == 0x0) &&
952 (instr->Bits(11, 9) == 0x5) &&
953 (instr->Bit(8) == 1) &&
954 (instr->Bit(6) == 0) &&
955 (instr->Bit(4) == 0)) {
956 Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
957 } else if ((instr->Bits(21, 20) == 0x3) &&
958 (instr->Bits(19, 16) == 0x4) &&
959 (instr->Bits(11, 9) == 0x5) &&
960 (instr->Bit(8) == 0x1) &&
961 (instr->Bit(6) == 0x1) &&
962 (instr->Bit(4) == 0x0)) {
963 Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
964 } else if ((instr->Bits(23, 20) == 0xF) &&
965 (instr->Bits(19, 16) == 0x1) &&
966 (instr->Bits(11, 8) == 0xA) &&
967 (instr->Bits(7, 5) == 0x0) &&
968 (instr->Bit(4) == 0x1) &&
969 (instr->Bits(3, 0) == 0x0)) {
970 if (instr->Bits(15, 12) == 0xF)
971 Format(instr, "vmrs'cond APSR, FPSCR");
972 else
973 Unknown(instr); // Not used by V8.
974 } else {
975 Unknown(instr); // Not used by V8.
976 }
977 } else if (instr->Bit(21) == 1) {
978 if ((instr->Bit(20) == 0x1) &&
979 (instr->Bits(11, 9) == 0x5) &&
980 (instr->Bit(8) == 0x1) &&
981 (instr->Bit(6) == 0) &&
982 (instr->Bit(4) == 0)) {
983 Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
984 } else if ((instr->Bit(20) == 0x1) &&
985 (instr->Bits(11, 9) == 0x5) &&
986 (instr->Bit(8) == 0x1) &&
987 (instr->Bit(6) == 1) &&
988 (instr->Bit(4) == 0)) {
989 Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
990 } else if ((instr->Bit(20) == 0x0) &&
991 (instr->Bits(11, 9) == 0x5) &&
992 (instr->Bit(8) == 0x1) &&
993 (instr->Bit(6) == 0) &&
994 (instr->Bit(4) == 0)) {
995 Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
996 } else {
997 Unknown(instr); // Not used by V8.
998 }
999 } else {
1000 if ((instr->Bit(20) == 0x0) &&
1001 (instr->Bits(11, 8) == 0xA) &&
1002 (instr->Bits(6, 5) == 0x0) &&
1003 (instr->Bit(4) == 1) &&
1004 (instr->Bits(3, 0) == 0x0)) {
1005 Format(instr, "vmov'cond 'Sn, 'rt");
1006 } else if ((instr->Bit(20) == 0x1) &&
1007 (instr->Bits(11, 8) == 0xA) &&
1008 (instr->Bits(6, 5) == 0x0) &&
1009 (instr->Bit(4) == 1) &&
1010 (instr->Bits(3, 0) == 0x0)) {
1011 Format(instr, "vmov'cond 'rt, 'Sn");
1012 } else {
1013 Unknown(instr); // Not used by V8.
1014 }
1015 }
1016}
1017
1018
1019// Decode Type 6 coprocessor instructions.
Leon Clarkee46be812010-01-19 14:06:41 +00001020// Dm = vmov(Rt, Rt2)
1021// <Rt, Rt2> = vmov(Dm)
Leon Clarked91b9f72010-01-27 17:25:45 +00001022// Ddst = MEM(Rbase + 4*offset).
1023// MEM(Rbase + 4*offset) = Dsrc.
Steve Blockd0582a62009-12-15 09:54:21 +00001024void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
1025 ASSERT((instr->TypeField() == 6));
1026
Leon Clarked91b9f72010-01-27 17:25:45 +00001027 if (instr->CoprocessorField() != 0xB) {
Steve Blockd0582a62009-12-15 09:54:21 +00001028 Unknown(instr); // Not used by V8.
1029 } else {
Leon Clarked91b9f72010-01-27 17:25:45 +00001030 switch (instr->OpcodeField()) {
1031 case 0x2:
1032 // Load and store double to two GP registers
1033 if (instr->Bits(7, 4) != 0x1) {
1034 Unknown(instr); // Not used by V8.
1035 } else if (instr->HasL()) {
1036 Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1037 } else {
1038 Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1039 }
1040 break;
1041 case 0x8:
1042 if (instr->HasL()) {
1043 Format(instr, "vldr'cond 'Dd, ['rn - 4*'off8]");
1044 } else {
1045 Format(instr, "vstr'cond 'Dd, ['rn - 4*'off8]");
1046 }
1047 break;
1048 case 0xC:
1049 if (instr->HasL()) {
1050 Format(instr, "vldr'cond 'Dd, ['rn + 4*'off8]");
1051 } else {
1052 Format(instr, "vstr'cond 'Dd, ['rn + 4*'off8]");
1053 }
1054 break;
1055 default:
1056 Unknown(instr); // Not used by V8.
1057 break;
1058 }
Steve Blockd0582a62009-12-15 09:54:21 +00001059 }
1060}
1061
1062
Steve Blocka7e24c12009-10-30 11:49:00 +00001063// Disassemble the instruction at *instr_ptr into the output buffer.
1064int Decoder::InstructionDecode(byte* instr_ptr) {
1065 Instr* instr = Instr::At(instr_ptr);
1066 // Print raw instruction bytes.
1067 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
1068 "%08x ",
1069 instr->InstructionBits());
1070 if (instr->ConditionField() == special_condition) {
1071 DecodeUnconditional(instr);
1072 return Instr::kInstrSize;
1073 }
1074 switch (instr->TypeField()) {
1075 case 0:
1076 case 1: {
1077 DecodeType01(instr);
1078 break;
1079 }
1080 case 2: {
1081 DecodeType2(instr);
1082 break;
1083 }
1084 case 3: {
1085 DecodeType3(instr);
1086 break;
1087 }
1088 case 4: {
1089 DecodeType4(instr);
1090 break;
1091 }
1092 case 5: {
1093 DecodeType5(instr);
1094 break;
1095 }
1096 case 6: {
1097 DecodeType6(instr);
1098 break;
1099 }
1100 case 7: {
1101 DecodeType7(instr);
1102 break;
1103 }
1104 default: {
1105 // The type field is 3-bits in the ARM encoding.
1106 UNREACHABLE();
1107 break;
1108 }
1109 }
1110 return Instr::kInstrSize;
1111}
1112
1113
1114} } // namespace assembler::arm
1115
1116
1117
1118//------------------------------------------------------------------------------
1119
1120namespace disasm {
1121
1122namespace v8i = v8::internal;
1123
1124
1125const char* NameConverter::NameOfAddress(byte* addr) const {
1126 static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
1127 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
1128 return tmp_buffer.start();
1129}
1130
1131
1132const char* NameConverter::NameOfConstant(byte* addr) const {
1133 return NameOfAddress(addr);
1134}
1135
1136
1137const char* NameConverter::NameOfCPURegister(int reg) const {
1138 return assembler::arm::Registers::Name(reg);
1139}
1140
1141
1142const char* NameConverter::NameOfByteCPURegister(int reg) const {
1143 UNREACHABLE(); // ARM does not have the concept of a byte register
1144 return "nobytereg";
1145}
1146
1147
1148const char* NameConverter::NameOfXMMRegister(int reg) const {
1149 UNREACHABLE(); // ARM does not have any XMM registers
1150 return "noxmmreg";
1151}
1152
1153
1154const char* NameConverter::NameInCode(byte* addr) const {
1155 // The default name converter is called for unknown code. So we will not try
1156 // to access any memory.
1157 return "";
1158}
1159
1160
1161//------------------------------------------------------------------------------
1162
1163Disassembler::Disassembler(const NameConverter& converter)
1164 : converter_(converter) {}
1165
1166
1167Disassembler::~Disassembler() {}
1168
1169
1170int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1171 byte* instruction) {
1172 assembler::arm::Decoder d(converter_, buffer);
1173 return d.InstructionDecode(instruction);
1174}
1175
1176
1177int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1178 int instruction_bits = *(reinterpret_cast<int*>(instruction));
1179 if ((instruction_bits & 0xfff00000) == 0x03000000) {
1180 return instruction_bits & 0x0000ffff;
1181 } else {
1182 return -1;
1183 }
1184}
1185
1186
1187void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1188 NameConverter converter;
1189 Disassembler d(converter);
1190 for (byte* pc = begin; pc < end;) {
1191 v8::internal::EmbeddedVector<char, 128> buffer;
1192 buffer[0] = '\0';
1193 byte* prev_pc = pc;
1194 pc += d.InstructionDecode(buffer, pc);
1195 fprintf(f, "%p %08x %s\n",
1196 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1197 }
1198}
1199
1200
1201} // namespace disasm