Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(666)

Side by Side Diff: src/disasm-arm.cc

Issue 92068: Move backend specific files to separate directories. (Closed)
Patch Set: Added CPPPATH flag and made all includes use same base path. Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/debug-ia32.cc ('k') | src/disasm-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2007-2008 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 "disasm.h"
61 #include "macro-assembler.h"
62 #include "platform.h"
63
64
65 namespace assembler { namespace arm {
66
67 namespace v8i = v8::internal;
68
69
70 //------------------------------------------------------------------------------
71
72 // Decoder decodes and disassembles instructions into an output buffer.
73 // It uses the converter to convert register names and call destinations into
74 // more informative description.
75 class Decoder {
76 public:
77 Decoder(const disasm::NameConverter& converter,
78 v8::internal::Vector<char> out_buffer)
79 : converter_(converter),
80 out_buffer_(out_buffer),
81 out_buffer_pos_(0) {
82 out_buffer_[out_buffer_pos_] = '\0';
83 }
84
85 ~Decoder() {}
86
87 // Writes one disassembled instruction into 'buffer' (0-terminated).
88 // Returns the length of the disassembled machine instruction in bytes.
89 int InstructionDecode(byte* instruction);
90
91 private:
92 // Bottleneck functions to print into the out_buffer.
93 void PrintChar(const char ch);
94 void Print(const char* str);
95
96 // Printing of common values.
97 void PrintRegister(int reg);
98 void PrintCondition(Instr* instr);
99 void PrintShiftRm(Instr* instr);
100 void PrintShiftImm(Instr* instr);
101 void PrintPU(Instr* instr);
102 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
103
104 // Handle formatting of instructions and their options.
105 int FormatRegister(Instr* instr, const char* option);
106 int FormatOption(Instr* instr, const char* option);
107 void Format(Instr* instr, const char* format);
108 void Unknown(Instr* instr);
109
110 // Each of these functions decodes one particular instruction type, a 3-bit
111 // field in the instruction encoding.
112 // Types 0 and 1 are combined as they are largely the same except for the way
113 // they interpret the shifter operand.
114 void DecodeType01(Instr* instr);
115 void DecodeType2(Instr* instr);
116 void DecodeType3(Instr* instr);
117 void DecodeType4(Instr* instr);
118 void DecodeType5(Instr* instr);
119 void DecodeType6(Instr* instr);
120 void DecodeType7(Instr* instr);
121
122 const disasm::NameConverter& converter_;
123 v8::internal::Vector<char> out_buffer_;
124 int out_buffer_pos_;
125
126 DISALLOW_COPY_AND_ASSIGN(Decoder);
127 };
128
129
130 // Support for assertions in the Decoder formatting functions.
131 #define STRING_STARTS_WITH(string, compare_string) \
132 (strncmp(string, compare_string, strlen(compare_string)) == 0)
133
134
135 // Append the ch to the output buffer.
136 void Decoder::PrintChar(const char ch) {
137 out_buffer_[out_buffer_pos_++] = ch;
138 }
139
140
141 // Append the str to the output buffer.
142 void Decoder::Print(const char* str) {
143 char cur = *str++;
144 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
145 PrintChar(cur);
146 cur = *str++;
147 }
148 out_buffer_[out_buffer_pos_] = 0;
149 }
150
151
152 // These condition names are defined in a way to match the native disassembler
153 // formatting. See for example the command "objdump -d <binary file>".
154 static const char* cond_names[max_condition] = {
155 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
156 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
157 };
158
159
160 // Print the condition guarding the instruction.
161 void Decoder::PrintCondition(Instr* instr) {
162 Print(cond_names[instr->ConditionField()]);
163 }
164
165
166 // Print the register name according to the active name converter.
167 void Decoder::PrintRegister(int reg) {
168 Print(converter_.NameOfCPURegister(reg));
169 }
170
171
172 // These shift names are defined in a way to match the native disassembler
173 // formatting. See for example the command "objdump -d <binary file>".
174 static const char* shift_names[max_shift] = {
175 "lsl", "lsr", "asr", "ror"
176 };
177
178
179 // Print the register shift operands for the instruction. Generally used for
180 // data processing instructions.
181 void Decoder::PrintShiftRm(Instr* instr) {
182 Shift shift = instr->ShiftField();
183 int shift_amount = instr->ShiftAmountField();
184 int rm = instr->RmField();
185
186 PrintRegister(rm);
187
188 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
189 // Special case for using rm only.
190 return;
191 }
192 if (instr->RegShiftField() == 0) {
193 // by immediate
194 if ((shift == ROR) && (shift_amount == 0)) {
195 Print(", RRX");
196 return;
197 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
198 shift_amount = 32;
199 }
200 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
201 ", %s #%d",
202 shift_names[shift], shift_amount);
203 } else {
204 // by register
205 int rs = instr->RsField();
206 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
207 ", %s ", shift_names[shift]);
208 PrintRegister(rs);
209 }
210 }
211
212
213 // Print the immediate operand for the instruction. Generally used for data
214 // processing instructions.
215 void Decoder::PrintShiftImm(Instr* instr) {
216 int rotate = instr->RotateField() * 2;
217 int immed8 = instr->Immed8Field();
218 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
219 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
220 "#%d", imm);
221 }
222
223
224 // Print PU formatting to reduce complexity of FormatOption.
225 void Decoder::PrintPU(Instr* instr) {
226 switch (instr->PUField()) {
227 case 0: {
228 Print("da");
229 break;
230 }
231 case 1: {
232 Print("ia");
233 break;
234 }
235 case 2: {
236 Print("db");
237 break;
238 }
239 case 3: {
240 Print("ib");
241 break;
242 }
243 default: {
244 UNREACHABLE();
245 break;
246 }
247 }
248 }
249
250
251 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
252 // the FormatOption method.
253 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
254 switch (swi) {
255 case call_rt_r5:
256 Print("call_rt_r5");
257 return;
258 case call_rt_r2:
259 Print("call_rt_r2");
260 return;
261 case break_point:
262 Print("break_point");
263 return;
264 case simulator_fp_add:
265 Print("simulator_fp_add");
266 return;
267 case simulator_fp_mul:
268 Print("simulator_fp_mul");
269 return;
270 case simulator_fp_sub:
271 Print("simulator_fp_sub");
272 return;
273 default:
274 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
275 "%d",
276 swi);
277 return;
278 }
279 }
280
281
282 // Handle all register based formatting in this function to reduce the
283 // complexity of FormatOption.
284 int Decoder::FormatRegister(Instr* instr, const char* format) {
285 ASSERT(format[0] == 'r');
286 if (format[1] == 'n') { // 'rn: Rn register
287 int reg = instr->RnField();
288 PrintRegister(reg);
289 return 2;
290 } else if (format[1] == 'd') { // 'rd: Rd register
291 int reg = instr->RdField();
292 PrintRegister(reg);
293 return 2;
294 } else if (format[1] == 's') { // 'rs: Rs register
295 int reg = instr->RsField();
296 PrintRegister(reg);
297 return 2;
298 } else if (format[1] == 'm') { // 'rm: Rm register
299 int reg = instr->RmField();
300 PrintRegister(reg);
301 return 2;
302 } else if (format[1] == 'l') {
303 // 'rlist: register list for load and store multiple instructions
304 ASSERT(STRING_STARTS_WITH(format, "rlist"));
305 int rlist = instr->RlistField();
306 int reg = 0;
307 Print("{");
308 // Print register list in ascending order, by scanning the bit mask.
309 while (rlist != 0) {
310 if ((rlist & 1) != 0) {
311 PrintRegister(reg);
312 if ((rlist >> 1) != 0) {
313 Print(", ");
314 }
315 }
316 reg++;
317 rlist >>= 1;
318 }
319 Print("}");
320 return 5;
321 }
322 UNREACHABLE();
323 return -1;
324 }
325
326
327 // FormatOption takes a formatting string and interprets it based on
328 // the current instructions. The format string points to the first
329 // character of the option string (the option escape has already been
330 // consumed by the caller.) FormatOption returns the number of
331 // characters that were consumed from the formatting string.
332 int Decoder::FormatOption(Instr* instr, const char* format) {
333 switch (format[0]) {
334 case 'a': { // 'a: accumulate multiplies
335 if (instr->Bit(21) == 0) {
336 Print("ul");
337 } else {
338 Print("la");
339 }
340 return 1;
341 }
342 case 'b': { // 'b: byte loads or stores
343 if (instr->HasB()) {
344 Print("b");
345 }
346 return 1;
347 }
348 case 'c': { // 'cond: conditional execution
349 ASSERT(STRING_STARTS_WITH(format, "cond"));
350 PrintCondition(instr);
351 return 4;
352 }
353 case 'h': { // 'h: halfword operation for extra loads and stores
354 if (instr->HasH()) {
355 Print("h");
356 } else {
357 Print("b");
358 }
359 return 1;
360 }
361 case 'l': { // 'l: branch and link
362 if (instr->HasLink()) {
363 Print("l");
364 }
365 return 1;
366 }
367 case 'm': {
368 if (format[1] == 'e') { // 'memop: load/store instructions
369 ASSERT(STRING_STARTS_WITH(format, "memop"));
370 if (instr->HasL()) {
371 Print("ldr");
372 } else {
373 Print("str");
374 }
375 return 5;
376 }
377 // 'msg: for simulator break instructions
378 ASSERT(STRING_STARTS_WITH(format, "msg"));
379 byte* str =
380 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
381 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
382 "%s", converter_.NameInCode(str));
383 return 3;
384 }
385 case 'o': {
386 if (format[3] == '1') {
387 // 'off12: 12-bit offset for load and store instructions
388 ASSERT(STRING_STARTS_WITH(format, "off12"));
389 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
390 "%d", instr->Offset12Field());
391 return 5;
392 }
393 // 'off8: 8-bit offset for extra load and store instructions
394 ASSERT(STRING_STARTS_WITH(format, "off8"));
395 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
396 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
397 "%d", offs8);
398 return 4;
399 }
400 case 'p': { // 'pu: P and U bits for load and store instructions
401 ASSERT(STRING_STARTS_WITH(format, "pu"));
402 PrintPU(instr);
403 return 2;
404 }
405 case 'r': {
406 return FormatRegister(instr, format);
407 }
408 case 's': {
409 if (format[1] == 'h') { // 'shift_op or 'shift_rm
410 if (format[6] == 'o') { // 'shift_op
411 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
412 if (instr->TypeField() == 0) {
413 PrintShiftRm(instr);
414 } else {
415 ASSERT(instr->TypeField() == 1);
416 PrintShiftImm(instr);
417 }
418 return 8;
419 } else { // 'shift_rm
420 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
421 PrintShiftRm(instr);
422 return 8;
423 }
424 } else if (format[1] == 'w') { // 'swi
425 ASSERT(STRING_STARTS_WITH(format, "swi"));
426 PrintSoftwareInterrupt(instr->SwiField());
427 return 3;
428 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
429 ASSERT(STRING_STARTS_WITH(format, "sign"));
430 if (instr->HasSign()) {
431 Print("s");
432 }
433 return 4;
434 }
435 // 's: S field of data processing instructions
436 if (instr->HasS()) {
437 Print("s");
438 }
439 return 1;
440 }
441 case 't': { // 'target: target of branch instructions
442 ASSERT(STRING_STARTS_WITH(format, "target"));
443 int off = (instr->SImmed24Field() << 2) + 8;
444 out_buffer_pos_ += v8i::OS::SNPrintF(
445 out_buffer_ + out_buffer_pos_,
446 "%+d -> %s",
447 off,
448 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
449 return 6;
450 }
451 case 'u': { // 'u: signed or unsigned multiplies
452 if (instr->Bit(22) == 0) {
453 Print("u");
454 } else {
455 Print("s");
456 }
457 return 1;
458 }
459 case 'w': { // 'w: W field of load and store instructions
460 if (instr->HasW()) {
461 Print("!");
462 }
463 return 1;
464 }
465 default: {
466 UNREACHABLE();
467 break;
468 }
469 }
470 UNREACHABLE();
471 return -1;
472 }
473
474
475 // Format takes a formatting string for a whole instruction and prints it into
476 // the output buffer. All escaped options are handed to FormatOption to be
477 // parsed further.
478 void Decoder::Format(Instr* instr, const char* format) {
479 char cur = *format++;
480 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
481 if (cur == '\'') { // Single quote is used as the formatting escape.
482 format += FormatOption(instr, format);
483 } else {
484 out_buffer_[out_buffer_pos_++] = cur;
485 }
486 cur = *format++;
487 }
488 out_buffer_[out_buffer_pos_] = '\0';
489 }
490
491
492 // For currently unimplemented decodings the disassembler calls Unknown(instr)
493 // which will just print "unknown" of the instruction bits.
494 void Decoder::Unknown(Instr* instr) {
495 Format(instr, "unknown");
496 }
497
498
499 void Decoder::DecodeType01(Instr* instr) {
500 int type = instr->TypeField();
501 if ((type == 0) && instr->IsSpecialType0()) {
502 // multiply instruction or extra loads and stores
503 if (instr->Bits(7, 4) == 9) {
504 if (instr->Bit(24) == 0) {
505 // multiply instructions
506 if (instr->Bit(23) == 0) {
507 if (instr->Bit(21) == 0) {
508 Format(instr, "mul'cond's 'rd, 'rm, 'rs");
509 } else {
510 Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn");
511 }
512 } else {
513 Format(instr, "'um'al'cond's 'rn, 'rd, 'rs, 'rm");
514 }
515 } else {
516 Unknown(instr); // not used by V8
517 }
518 } else {
519 // extra load/store instructions
520 switch (instr->PUField()) {
521 case 0: {
522 if (instr->Bit(22) == 0) {
523 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
524 } else {
525 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
526 }
527 break;
528 }
529 case 1: {
530 if (instr->Bit(22) == 0) {
531 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
532 } else {
533 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
534 }
535 break;
536 }
537 case 2: {
538 if (instr->Bit(22) == 0) {
539 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
540 } else {
541 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
542 }
543 break;
544 }
545 case 3: {
546 if (instr->Bit(22) == 0) {
547 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
548 } else {
549 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
550 }
551 break;
552 }
553 default: {
554 // The PU field is a 2-bit field.
555 UNREACHABLE();
556 break;
557 }
558 }
559 return;
560 }
561 } else {
562 switch (instr->OpcodeField()) {
563 case AND: {
564 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
565 break;
566 }
567 case EOR: {
568 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
569 break;
570 }
571 case SUB: {
572 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
573 break;
574 }
575 case RSB: {
576 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
577 break;
578 }
579 case ADD: {
580 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
581 break;
582 }
583 case ADC: {
584 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
585 break;
586 }
587 case SBC: {
588 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
589 break;
590 }
591 case RSC: {
592 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
593 break;
594 }
595 case TST: {
596 if (instr->HasS()) {
597 Format(instr, "tst'cond 'rn, 'shift_op");
598 } else {
599 Unknown(instr); // not used by V8
600 }
601 break;
602 }
603 case TEQ: {
604 if (instr->HasS()) {
605 Format(instr, "teq'cond 'rn, 'shift_op");
606 } else {
607 Unknown(instr); // not used by V8
608 }
609 break;
610 }
611 case CMP: {
612 if (instr->HasS()) {
613 Format(instr, "cmp'cond 'rn, 'shift_op");
614 } else {
615 Unknown(instr); // not used by V8
616 }
617 break;
618 }
619 case CMN: {
620 if (instr->HasS()) {
621 Format(instr, "cmn'cond 'rn, 'shift_op");
622 } else {
623 Unknown(instr); // not used by V8
624 }
625 break;
626 }
627 case ORR: {
628 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
629 break;
630 }
631 case MOV: {
632 Format(instr, "mov'cond's 'rd, 'shift_op");
633 break;
634 }
635 case BIC: {
636 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
637 break;
638 }
639 case MVN: {
640 Format(instr, "mvn'cond's 'rd, 'shift_op");
641 break;
642 }
643 default: {
644 // The Opcode field is a 4-bit field.
645 UNREACHABLE();
646 break;
647 }
648 }
649 }
650 }
651
652
653 void Decoder::DecodeType2(Instr* instr) {
654 switch (instr->PUField()) {
655 case 0: {
656 if (instr->HasW()) {
657 Unknown(instr); // not used in V8
658 }
659 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
660 break;
661 }
662 case 1: {
663 if (instr->HasW()) {
664 Unknown(instr); // not used in V8
665 }
666 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
667 break;
668 }
669 case 2: {
670 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
671 break;
672 }
673 case 3: {
674 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
675 break;
676 }
677 default: {
678 // The PU field is a 2-bit field.
679 UNREACHABLE();
680 break;
681 }
682 }
683 }
684
685
686 void Decoder::DecodeType3(Instr* instr) {
687 switch (instr->PUField()) {
688 case 0: {
689 ASSERT(!instr->HasW());
690 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
691 break;
692 }
693 case 1: {
694 ASSERT(!instr->HasW());
695 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
696 break;
697 }
698 case 2: {
699 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
700 break;
701 }
702 case 3: {
703 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
704 break;
705 }
706 default: {
707 // The PU field is a 2-bit field.
708 UNREACHABLE();
709 break;
710 }
711 }
712 }
713
714
715 void Decoder::DecodeType4(Instr* instr) {
716 ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported.
717 if (instr->HasL()) {
718 Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
719 } else {
720 Format(instr, "stm'cond'pu 'rn'w, 'rlist");
721 }
722 }
723
724
725 void Decoder::DecodeType5(Instr* instr) {
726 Format(instr, "b'l'cond 'target");
727 }
728
729
730 void Decoder::DecodeType6(Instr* instr) {
731 // Coprocessor instructions currently not supported.
732 Unknown(instr);
733 }
734
735
736 void Decoder::DecodeType7(Instr* instr) {
737 if (instr->Bit(24) == 1) {
738 Format(instr, "swi'cond 'swi");
739 } else {
740 // Coprocessor instructions currently not supported.
741 Unknown(instr);
742 }
743 }
744
745
746 // Disassemble the instruction at *instr_ptr into the output buffer.
747 int Decoder::InstructionDecode(byte* instr_ptr) {
748 Instr* instr = Instr::At(instr_ptr);
749 // Print raw instruction bytes.
750 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
751 "%08x ",
752 instr->InstructionBits());
753 if (instr->ConditionField() == special_condition) {
754 Format(instr, "break 'msg");
755 return Instr::kInstrSize;
756 }
757 switch (instr->TypeField()) {
758 case 0:
759 case 1: {
760 DecodeType01(instr);
761 break;
762 }
763 case 2: {
764 DecodeType2(instr);
765 break;
766 }
767 case 3: {
768 DecodeType3(instr);
769 break;
770 }
771 case 4: {
772 DecodeType4(instr);
773 break;
774 }
775 case 5: {
776 DecodeType5(instr);
777 break;
778 }
779 case 6: {
780 DecodeType6(instr);
781 break;
782 }
783 case 7: {
784 DecodeType7(instr);
785 break;
786 }
787 default: {
788 // The type field is 3-bits in the ARM encoding.
789 UNREACHABLE();
790 break;
791 }
792 }
793 return Instr::kInstrSize;
794 }
795
796
797 } } // namespace assembler::arm
798
799
800
801 //------------------------------------------------------------------------------
802
803 namespace disasm {
804
805 namespace v8i = v8::internal;
806
807
808 static const int kMaxRegisters = 16;
809
810 // These register names are defined in a way to match the native disassembler
811 // formatting. See for example the command "objdump -d <binary file>".
812 static const char* reg_names[kMaxRegisters] = {
813 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
814 "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
815 };
816
817
818 const char* NameConverter::NameOfAddress(byte* addr) const {
819 static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
820 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
821 return tmp_buffer.start();
822 }
823
824
825 const char* NameConverter::NameOfConstant(byte* addr) const {
826 return NameOfAddress(addr);
827 }
828
829
830 const char* NameConverter::NameOfCPURegister(int reg) const {
831 const char* result;
832 if ((0 <= reg) && (reg < kMaxRegisters)) {
833 result = reg_names[reg];
834 } else {
835 result = "noreg";
836 }
837 return result;
838 }
839
840
841 const char* NameConverter::NameOfByteCPURegister(int reg) const {
842 UNREACHABLE(); // ARM does not have the concept of a byte register
843 return "nobytereg";
844 }
845
846
847 const char* NameConverter::NameOfXMMRegister(int reg) const {
848 UNREACHABLE(); // ARM does not have any XMM registers
849 return "noxmmreg";
850 }
851
852
853 const char* NameConverter::NameInCode(byte* addr) const {
854 // The default name converter is called for unknown code. So we will not try
855 // to access any memory.
856 return "";
857 }
858
859
860 //------------------------------------------------------------------------------
861
862 Disassembler::Disassembler(const NameConverter& converter)
863 : converter_(converter) {}
864
865
866 Disassembler::~Disassembler() {}
867
868
869 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
870 byte* instruction) {
871 assembler::arm::Decoder d(converter_, buffer);
872 return d.InstructionDecode(instruction);
873 }
874
875
876 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
877 int instruction_bits = *(reinterpret_cast<int*>(instruction));
878 if ((instruction_bits & 0xfff00000) == 0x03000000) {
879 return instruction_bits & 0x0000ffff;
880 } else {
881 return -1;
882 }
883 }
884
885
886 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
887 NameConverter converter;
888 Disassembler d(converter);
889 for (byte* pc = begin; pc < end;) {
890 v8::internal::EmbeddedVector<char, 128> buffer;
891 buffer[0] = '\0';
892 byte* prev_pc = pc;
893 pc += d.InstructionDecode(buffer, pc);
894 fprintf(f, "%p %08x %s\n",
895 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
896 }
897 }
898
899
900 } // namespace disasm
OLDNEW
« no previous file with comments | « src/debug-ia32.cc ('k') | src/disasm-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698