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

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

Issue 601028: Forking disassembler and simulator for Thumb2 support;... Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/arm/debug-thumb2.cc ('k') | src/arm/instr-thumb2.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 2010 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 "instr-thumb2.h"
64 #include "platform.h"
65
66
67 namespace assembler {
68 namespace arm {
69
70 namespace v8i = v8::internal;
71
72
73 //------------------------------------------------------------------------------
74
75 // Decoder decodes and disassembles instructions into an output buffer.
76 // It uses the converter to convert register names and call destinations into
77 // more informative description.
78 class Decoder {
79 public:
80 Decoder(const disasm::NameConverter& converter,
81 v8::internal::Vector<char> out_buffer)
82 : converter_(converter),
83 out_buffer_(out_buffer),
84 out_buffer_pos_(0) {
85 out_buffer_[out_buffer_pos_] = '\0';
86 }
87
88 ~Decoder() {}
89
90 // Writes one disassembled instruction into 'buffer' (0-terminated).
91 // Returns the length of the disassembled machine instruction in bytes.
92 int InstructionDecode(byte* instruction);
93 int InstructionDecodeArm(byte* instruction);
94 int InstructionDecodeThumb2(const InstrThumb2& instr);
95
96 private:
97 // Bottleneck functions to print into the out_buffer.
98 void PrintChar(const char ch);
99 void Print(const char* str);
100
101 // Printing of common values.
102 void PrintRegister(int reg);
103 void PrintSRegister(int reg);
104 void PrintDRegister(int reg);
105 int FormatVFPRegister(Instr* instr, const char* format);
106 int FormatVFPinstruction(Instr* instr, const char* format);
107 void PrintCondition(Instr* instr);
108 void PrintShiftRm(Instr* instr);
109 void PrintShiftRm(const InstrThumb2& instr);
110 void PrintShiftImm(Instr* instr);
111 void PrintShiftImm(const InstrThumb2& instr);
112 void PrintPU(Instr* instr);
113 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
114
115 // Handle formatting of instructions and their options.
116 int FormatRegister(Instr* instr, const char* option);
117 int FormatRegister(const InstrThumb2& instr, const char* option);
118 int FormatOption(Instr* instr, const char* option);
119 int FormatOption(const InstrThumb2& instr, const char* option);
120 void Format(Instr* instr, const char* format);
121 void Format(const InstrThumb2& instr, const char* format);
122 void Unknown(Instr* instr);
123 void Unknown(const InstrThumb2& instr);
124
125 // Each of these functions decodes one particular instruction type, a 3-bit
126 // field in the instruction encoding.
127 // Types 0 and 1 are combined as they are largely the same except for the way
128 // they interpret the shifter operand.
129 void DecodeType01(Instr* instr);
130 void DecodeType2(Instr* instr);
131 void DecodeType3(Instr* instr);
132 void DecodeType4(Instr* instr);
133 void DecodeType5(Instr* instr);
134 void DecodeType6(Instr* instr);
135 void DecodeType7(Instr* instr);
136 void DecodeUnconditional(Instr* instr);
137 // For VFP support.
138 void DecodeTypeVFP(Instr* instr);
139 void DecodeType6CoprocessorIns(Instr* instr);
140
141
142 const disasm::NameConverter& converter_;
143 v8::internal::Vector<char> out_buffer_;
144 int out_buffer_pos_;
145
146 DISALLOW_COPY_AND_ASSIGN(Decoder);
147 };
148
149
150 // Support for assertions in the Decoder formatting functions.
151 #define STRING_STARTS_WITH(string, compare_string) \
152 (strncmp(string, compare_string, strlen(compare_string)) == 0)
153
154
155 // Append the ch to the output buffer.
156 void Decoder::PrintChar(const char ch) {
157 out_buffer_[out_buffer_pos_++] = ch;
158 }
159
160
161 // Append the str to the output buffer.
162 void Decoder::Print(const char* str) {
163 char cur = *str++;
164 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
165 PrintChar(cur);
166 cur = *str++;
167 }
168 out_buffer_[out_buffer_pos_] = 0;
169 }
170
171
172 // These condition 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* cond_names[max_condition] = {
175 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
176 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
177 };
178
179
180 // Print the condition guarding the instruction.
181 void Decoder::PrintCondition(Instr* instr) {
182 Print(cond_names[instr->ConditionField()]);
183 }
184
185
186 // Print the register name according to the active name converter.
187 void Decoder::PrintRegister(int reg) {
188 Print(converter_.NameOfCPURegister(reg));
189 }
190
191 // Print the VFP S register name according to the active name converter.
192 void Decoder::PrintSRegister(int reg) {
193 Print(assembler::arm::VFPRegisters::Name(reg));
194 }
195
196 // Print the VFP D register name according to the active name converter.
197 void Decoder::PrintDRegister(int reg) {
198 Print(assembler::arm::VFPRegisters::Name(reg + 32));
199 }
200
201
202 // These shift names are defined in a way to match the native disassembler
203 // formatting. See for example the command "objdump -d <binary file>".
204 static const char* shift_names[max_shift] = {
205 "lsl", "lsr", "asr", "ror"
206 };
207
208
209 // Print the register shift operands for the instruction. Generally used for
210 // data processing instructions.
211 void Decoder::PrintShiftRm(Instr* instr) {
212 Shift shift = instr->ShiftField();
213 int shift_amount = instr->ShiftAmountField();
214 int rm = instr->RmField();
215
216 PrintRegister(rm);
217
218 if ((instr->RegShiftField() == 0) && (shift == LSL) && (shift_amount == 0)) {
219 // Special case for using rm only.
220 return;
221 }
222 if (instr->RegShiftField() == 0) {
223 // by immediate
224 if ((shift == ROR) && (shift_amount == 0)) {
225 Print(", RRX");
226 return;
227 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
228 shift_amount = 32;
229 }
230 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
231 ", %s #%d",
232 shift_names[shift], shift_amount);
233 } else {
234 // by register
235 int rs = instr->RsField();
236 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
237 ", %s ", shift_names[shift]);
238 PrintRegister(rs);
239 }
240 }
241
242 void Decoder::PrintShiftRm(const InstrThumb2& instr) {
243 int shift = instr.Type();
244 int shift_amount = instr.Imm();
245 int rm = instr.Rm();
246
247 PrintRegister(rm);
248
249 if (instr.Variant() != VARIANT_REGISTER_SHIFTED_REGISTER) {
250 if (shift == no_shift) {
251 // Special case for using rm only.
252 return;
253 }
254 if (shift == RRX) {
255 Print(", RRX");
256 return;
257 }
258 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
259 ", %s #%d",
260 shift_names[shift], shift_amount);
261 } else {
262 UNIMPLEMENTED();
263 // // by register
264 // int rs = instr->Rs();
265 // out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
266 // ", %s ", shift_names[shift]);
267 // PrintRegister(rs);
268 }
269 }
270
271
272
273 // Print the immediate operand for the instruction. Generally used for data
274 // processing instructions.
275 void Decoder::PrintShiftImm(Instr* instr) {
276 int rotate = instr->RotateField() * 2;
277 int immed8 = instr->Immed8Field();
278 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
279 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
280 "#%d", imm);
281 }
282
283 void Decoder::PrintShiftImm(const InstrThumb2& instr) {
284 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
285 "#%d", instr.Imm());
286 }
287
288
289 // Print PU formatting to reduce complexity of FormatOption.
290 void Decoder::PrintPU(Instr* instr) {
291 switch (instr->PUField()) {
292 case 0: {
293 Print("da");
294 break;
295 }
296 case 1: {
297 Print("ia");
298 break;
299 }
300 case 2: {
301 Print("db");
302 break;
303 }
304 case 3: {
305 Print("ib");
306 break;
307 }
308 default: {
309 UNREACHABLE();
310 break;
311 }
312 }
313 }
314
315
316 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
317 // the FormatOption method.
318 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
319 switch (swi) {
320 case call_rt_redirected:
321 Print("call_rt_redirected");
322 return;
323 case break_point:
324 Print("break_point");
325 return;
326 default:
327 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
328 "%d",
329 swi);
330 return;
331 }
332 }
333
334
335 // Handle all register based formatting in this function to reduce the
336 // complexity of FormatOption.
337 int Decoder::FormatRegister(Instr* instr, const char* format) {
338 ASSERT(format[0] == 'r');
339 if (format[1] == 'n') { // 'rn: Rn register
340 int reg = instr->RnField();
341 PrintRegister(reg);
342 return 2;
343 } else if (format[1] == 'd') { // 'rd: Rd register
344 int reg = instr->RdField();
345 PrintRegister(reg);
346 return 2;
347 } else if (format[1] == 's') { // 'rs: Rs register
348 int reg = instr->RsField();
349 PrintRegister(reg);
350 return 2;
351 } else if (format[1] == 'm') { // 'rm: Rm register
352 int reg = instr->RmField();
353 PrintRegister(reg);
354 return 2;
355 } else if (format[1] == 't') { // 'rt: Rt register
356 int reg = instr->RtField();
357 PrintRegister(reg);
358 return 2;
359 } else if (format[1] == 'l') {
360 // 'rlist: register list for load and store multiple instructions
361 ASSERT(STRING_STARTS_WITH(format, "rlist"));
362 int rlist = instr->RlistField();
363 int reg = 0;
364 Print("{");
365 // Print register list in ascending order, by scanning the bit mask.
366 while (rlist != 0) {
367 if ((rlist & 1) != 0) {
368 PrintRegister(reg);
369 if ((rlist >> 1) != 0) {
370 Print(", ");
371 }
372 }
373 reg++;
374 rlist >>= 1;
375 }
376 Print("}");
377 return 5;
378 }
379 UNREACHABLE();
380 return -1;
381 }
382
383 int Decoder::FormatRegister(const InstrThumb2& instr, const char* format) {
384 ASSERT(format[0] == 'r');
385 if (format[1] == 'n') { // 'rn: Rn register
386 int reg = instr.Rn();
387 PrintRegister(reg);
388 return 2;
389 } else if (format[1] == 'd') { // 'rd: Rd register
390 int reg = instr.Rd();
391 PrintRegister(reg);
392 return 2;
393 } else if (format[1] == 's') { // 'rs: Rs register
394 int reg = instr.Rs();
395 PrintRegister(reg);
396 return 2;
397 } else if (format[1] == 'm') { // 'rm: Rm register
398 int reg = instr.Rm();
399 PrintRegister(reg);
400 return 2;
401 } else if (format[1] == 't') { // 'rt: Rt register
402 int reg = instr.Rt();
403 PrintRegister(reg);
404 return 2;
405 } else if (format[1] == 'l') {
406 // 'rlist: register list for load and store multiple instructions
407 ASSERT(STRING_STARTS_WITH(format, "rlist"));
408 UNIMPLEMENTED();
409 // int rlist = instr->RlistField();
410 // int reg = 0;
411 // Print("{");
412 // // Print register list in ascending order, by scanning the bit mask.
413 // while (rlist != 0) {
414 // if ((rlist & 1) != 0) {
415 // PrintRegister(reg);
416 // if ((rlist >> 1) != 0) {
417 // Print(", ");
418 // }
419 // }
420 // reg++;
421 // rlist >>= 1;
422 // }
423 // Print("}");
424 return 5;
425 }
426 UNREACHABLE();
427 return -1;
428 }
429
430
431 // Handle all VFP register based formatting in this function to reduce the
432 // complexity of FormatOption.
433 int Decoder::FormatVFPRegister(Instr* instr, const char* format) {
434 ASSERT((format[0] == 'S') || (format[0] == 'D'));
435
436 if (format[1] == 'n') {
437 int reg = instr->VnField();
438 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField()));
439 if (format[0] == 'D') PrintDRegister(reg);
440 return 2;
441 } else if (format[1] == 'm') {
442 int reg = instr->VmField();
443 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->MField()));
444 if (format[0] == 'D') PrintDRegister(reg);
445 return 2;
446 } else if (format[1] == 'd') {
447 int reg = instr->VdField();
448 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->DField()));
449 if (format[0] == 'D') PrintDRegister(reg);
450 return 2;
451 }
452
453 UNREACHABLE();
454 return -1;
455 }
456
457
458 int Decoder::FormatVFPinstruction(Instr* instr, const char* format) {
459 Print(format);
460 return 0;
461 }
462
463
464 // FormatOption takes a formatting string and interprets it based on
465 // the current instructions. The format string points to the first
466 // character of the option string (the option escape has already been
467 // consumed by the caller.) FormatOption returns the number of
468 // characters that were consumed from the formatting string.
469 int Decoder::FormatOption(Instr* instr, const char* format) {
470 switch (format[0]) {
471 case 'a': { // 'a: accumulate multiplies
472 if (instr->Bit(21) == 0) {
473 Print("ul");
474 } else {
475 Print("la");
476 }
477 return 1;
478 }
479 case 'b': { // 'b: byte loads or stores
480 if (instr->HasB()) {
481 Print("b");
482 }
483 return 1;
484 }
485 case 'c': { // 'cond: conditional execution
486 ASSERT(STRING_STARTS_WITH(format, "cond"));
487 PrintCondition(instr);
488 return 4;
489 }
490 case 'h': { // 'h: halfword operation for extra loads and stores
491 if (instr->HasH()) {
492 Print("h");
493 } else {
494 Print("b");
495 }
496 return 1;
497 }
498 case 'l': { // 'l: branch and link
499 if (instr->HasLink()) {
500 Print("l");
501 }
502 return 1;
503 }
504 case 'm': {
505 if (format[1] == 'e') { // 'memop: load/store instructions
506 ASSERT(STRING_STARTS_WITH(format, "memop"));
507 if (instr->HasL()) {
508 Print("ldr");
509 } else {
510 Print("str");
511 }
512 return 5;
513 }
514 // 'msg: for simulator break instructions
515 ASSERT(STRING_STARTS_WITH(format, "msg"));
516 byte* str =
517 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
518 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
519 "%s", converter_.NameInCode(str));
520 return 3;
521 }
522 case 'o': {
523 if ((format[3] == '1') && (format[4] == '2')) {
524 // 'off12: 12-bit offset for load and store instructions
525 ASSERT(STRING_STARTS_WITH(format, "off12"));
526 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
527 "%d", instr->Offset12Field());
528 return 5;
529 } else if ((format[3] == '1') && (format[4] == '6')) {
530 ASSERT(STRING_STARTS_WITH(format, "off16to20"));
531 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
532 "%d", instr->Bits(20, 16) +1);
533 return 9;
534 } else if (format[3] == '7') {
535 ASSERT(STRING_STARTS_WITH(format, "off7to11"));
536 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
537 "%d", instr->ShiftAmountField());
538 return 8;
539 }
540 // 'off8: 8-bit offset for extra load and store instructions
541 ASSERT(STRING_STARTS_WITH(format, "off8"));
542 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
543 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
544 "%d", offs8);
545 return 4;
546 }
547 case 'p': { // 'pu: P and U bits for load and store instructions
548 ASSERT(STRING_STARTS_WITH(format, "pu"));
549 PrintPU(instr);
550 return 2;
551 }
552 case 'r': {
553 return FormatRegister(instr, format);
554 }
555 case 's': {
556 if (format[1] == 'h') { // 'shift_op or 'shift_rm
557 if (format[6] == 'o') { // 'shift_op
558 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
559 if (instr->TypeField() == 0) {
560 PrintShiftRm(instr);
561 } else {
562 ASSERT(instr->TypeField() == 1);
563 PrintShiftImm(instr);
564 }
565 return 8;
566 } else { // 'shift_rm
567 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
568 PrintShiftRm(instr);
569 return 8;
570 }
571 } else if (format[1] == 'w') { // 'swi
572 ASSERT(STRING_STARTS_WITH(format, "swi"));
573 PrintSoftwareInterrupt(instr->SwiField());
574 return 3;
575 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
576 ASSERT(STRING_STARTS_WITH(format, "sign"));
577 if (instr->HasSign()) {
578 Print("s");
579 }
580 return 4;
581 }
582 // 's: S field of data processing instructions
583 if (instr->HasS()) {
584 Print("s");
585 }
586 return 1;
587 }
588 case 't': { // 'target: target of branch instructions
589 ASSERT(STRING_STARTS_WITH(format, "target"));
590 int off = (instr->SImmed24Field() << 2) + 8;
591 out_buffer_pos_ += v8i::OS::SNPrintF(
592 out_buffer_ + out_buffer_pos_,
593 "%+d -> %s",
594 off,
595 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
596 return 6;
597 }
598 case 'u': { // 'u: signed or unsigned multiplies
599 // The manual gets the meaning of bit 22 backwards in the multiply
600 // instruction overview on page A3.16.2. The instructions that
601 // exist in u and s variants are the following:
602 // smull A4.1.87
603 // umull A4.1.129
604 // umlal A4.1.128
605 // smlal A4.1.76
606 // For these 0 means u and 1 means s. As can be seen on their individual
607 // pages. The other 18 mul instructions have the bit set or unset in
608 // arbitrary ways that are unrelated to the signedness of the instruction.
609 // None of these 18 instructions exist in both a 'u' and an 's' variant.
610
611 if (instr->Bit(22) == 0) {
612 Print("u");
613 } else {
614 Print("s");
615 }
616 return 1;
617 }
618 case 'v': {
619 return FormatVFPinstruction(instr, format);
620 }
621 case 'S':
622 case 'D': {
623 return FormatVFPRegister(instr, format);
624 }
625 case 'w': { // 'w: W field of load and store instructions
626 if (instr->HasW()) {
627 Print("!");
628 }
629 return 1;
630 }
631 default: {
632 UNREACHABLE();
633 break;
634 }
635 }
636 UNREACHABLE();
637 return -1;
638 }
639
640 int Decoder::FormatOption(const InstrThumb2& instr, const char* format) {
641 switch (format[0]) {
642 // TODO(haustein) Re-enable code below
643 // case 'a': { // 'a: accumulate multiplies
644 // if (instr->Bit(21) == 0) {
645 // Print("ul");
646 // } else {
647 // Print("la");
648 // }
649 // return 1;
650 // }
651 // case 'b': { // 'b: byte loads or stores
652 // if (instr->HasB()) {
653 // Print("b");
654 // }
655 // return 1;
656 // }
657 // case 'c': { // 'cond: conditional execution
658 // ASSERT(STRING_STARTS_WITH(format, "cond"));
659 // PrintCondition(instr);
660 // return 4;
661 // }
662 // case 'h': { // 'h: halfword operation for extra loads and stores
663 // if (instr->HasH()) {
664 // Print("h");
665 // } else {
666 // Print("b");
667 // }
668 // return 1;
669 // }
670 // case 'l': { // 'l: branch and link
671 // if (instr->HasLink()) {
672 // Print("l");
673 // }
674 // return 1;
675 // }
676 // case 'm': {
677 // if (format[1] == 'e') { // 'memop: load/store instructions
678 // ASSERT(STRING_STARTS_WITH(format, "memop"));
679 // if (instr->HasL()) {
680 // Print("ldr");
681 // } else {
682 // Print("str");
683 // }
684 // return 5;
685 // }
686 // // 'msg: for simulator break instructions
687 // ASSERT(STRING_STARTS_WITH(format, "msg"));
688 // byte* str =
689 // reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
690 // out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
691 // "%s", converter_.NameInCode(str));
692 // return 3;
693 // }
694 // case 'o': {
695 // if ((format[3] == '1') && (format[4] == '2')) {
696 // // 'off12: 12-bit offset for load and store instructions
697 // ASSERT(STRING_STARTS_WITH(format, "off12"));
698 // out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
699 // "%d", instr->Offset12Field());
700 // return 5;
701 // } else if ((format[3] == '1') && (format[4] == '6')) {
702 // ASSERT(STRING_STARTS_WITH(format, "off16to20"));
703 // out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
704 // "%d", instr->Bits(20, 16) +1);
705 // return 9;
706 // } else if (format[3] == '7') {
707 // ASSERT(STRING_STARTS_WITH(format, "off7to11"));
708 // out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
709 // "%d", instr->ShiftAmountField());
710 // return 8;
711 // }
712 // // 'off8: 8-bit offset for extra load and store instructions
713 // ASSERT(STRING_STARTS_WITH(format, "off8"));
714 // int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
715 // out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
716 // "%d", offs8);
717 // return 4;
718 // }
719 // case 'p': { // 'pu: P and U bits for load and store instructions
720 // ASSERT(STRING_STARTS_WITH(format, "pu"));
721 // PrintPU(instr);
722 // return 2;
723 // }
724 case 'r': {
725 return FormatRegister(instr, format);
726 }
727 case 's': {
728 if (format[1] == 'h') { // 'shift_op or 'shift_rm
729 if (format[6] == 'o') { // 'shift_op
730 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
731 if (instr.Type() == 0) {
732 PrintShiftRm(instr);
733 } else {
734 ASSERT(instr.Type() == 1);
735 PrintShiftImm(instr);
736 }
737 return 8;
738 } else { // 'shift_rm
739 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
740 PrintShiftRm(instr);
741 return 8;
742 }
743 // TODO(haustein) Re-enable code below
744 // } else if (format[1] == 'w') { // 'swi
745 // ASSERT(STRING_STARTS_WITH(format, "swi"));
746 // PrintSoftwareInterrupt(instr->SwiField());
747 // return 3;
748 // } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
749 // ASSERT(STRING_STARTS_WITH(format, "sign"));
750 // if (instr->HasSign()) {
751 // Print("s");
752 // return 4;
753 }
754 // 's: S field of data processing instructions
755 if (instr.HasS()) {
756 Print("s");
757 }
758 return 1;
759 }
760 // TODO(haustein) Re-enable code for 't', 'u', 'v', 'S', 'D', 'w' below.
761 // case 't': { // 'target: target of branch instructions
762 // ASSERT(STRING_STARTS_WITH(format, "target"));
763 // int off = (instr->SImmed24Field() << 2) + 8;
764 // out_buffer_pos_ += v8i::OS::SNPrintF(
765 // out_buffer_ + out_buffer_pos_,
766 // "%+d -> %s",
767 // off,
768 // converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
769 // return 6;
770 // }
771 // case 'u': { // 'u: signed or unsigned multiplies
772 // // The manual gets the meaning of bit 22 backwards in the multiply
773 // // instruction overview on page A3.16.2. The instructions that
774 // // exist in u and s variants are the following:
775 // // smull A4.1.87
776 // // umull A4.1.129
777 // // umlal A4.1.128
778 // // smlal A4.1.76
779 // // For these 0 means u and 1 means s. As can be seen on their individual
780 // // pages. The other 18 mul instructions have the bit set or unset in
781 // // arbitrary ways that are unrelated to the signedness of the instruction.
782 // // None of these 18 instructions exist in both a 'u' and an 's' variant.
783 //
784 // if (instr->Bit(22) == 0) {
785 // Print("u");
786 // } else {
787 // Print("s");
788 // }
789 // return 1;
790 // }
791 // case 'v': {
792 // return FormatVFPinstruction(instr, format);
793 // }
794 // case 'S':
795 // case 'D': {
796 // return FormatVFPRegister(instr, format);
797 // }
798 // case 'w': { // 'w: W field of load and store instructions
799 // if (instr->HasW()) {
800 // Print("!");
801 // }
802 // return 1;
803 // }
804 default: {
805 UNIMPLEMENTED();
806 break;
807 }
808 }
809 UNREACHABLE();
810 return -1;
811 }
812
813
814 // Format takes a formatting string for a whole instruction and prints it into
815 // the output buffer. All escaped options are handed to FormatOption to be
816 // parsed further.
817 void Decoder::Format(Instr* instr, const char* format) {
818 char cur = *format++;
819 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
820 if (cur == '\'') { // Single quote is used as the formatting escape.
821 format += FormatOption(instr, format);
822 } else {
823 out_buffer_[out_buffer_pos_++] = cur;
824 }
825 cur = *format++;
826 }
827 out_buffer_[out_buffer_pos_] = '\0';
828 }
829
830
831 void Decoder::Format(const InstrThumb2& instr, const char* format) {
832 char cur = *format++;
833 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
834 if (cur == '\'') { // Single quote is used as the formatting escape.
835 format += FormatOption(instr, format);
836 } else {
837 out_buffer_[out_buffer_pos_++] = cur;
838 }
839 cur = *format++;
840 }
841 out_buffer_[out_buffer_pos_] = '\0';
842 }
843
844
845
846 // For currently unimplemented decodings the disassembler calls Unknown(instr)
847 // which will just print "unknown" of the instruction bits.
848 void Decoder::Unknown(Instr* instr) {
849 Format(instr, "unknown");
850 }
851
852
853 void Decoder::DecodeType01(Instr* instr) {
854 int type = instr->TypeField();
855 if ((type == 0) && instr->IsSpecialType0()) {
856 // multiply instruction or extra loads and stores
857 if (instr->Bits(7, 4) == 9) {
858 if (instr->Bit(24) == 0) {
859 // multiply instructions
860 if (instr->Bit(23) == 0) {
861 if (instr->Bit(21) == 0) {
862 // The MUL instruction description (A 4.1.33) refers to Rd as being
863 // the destination for the operation, but it confusingly uses the
864 // Rn field to encode it.
865 Format(instr, "mul'cond's 'rn, 'rm, 'rs");
866 } else {
867 // The MLA instruction description (A 4.1.28) refers to the order
868 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
869 // Rn field to encode the Rd register and the Rd field to encode
870 // the Rn register.
871 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
872 }
873 } else {
874 // The signed/long multiply instructions use the terms RdHi and RdLo
875 // when referring to the target registers. They are mapped to the Rn
876 // and Rd fields as follows:
877 // RdLo == Rd field
878 // RdHi == Rn field
879 // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
880 Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
881 }
882 } else {
883 Unknown(instr); // not used by V8
884 }
885 } else {
886 // extra load/store instructions
887 switch (instr->PUField()) {
888 case 0: {
889 if (instr->Bit(22) == 0) {
890 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
891 } else {
892 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
893 }
894 break;
895 }
896 case 1: {
897 if (instr->Bit(22) == 0) {
898 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
899 } else {
900 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
901 }
902 break;
903 }
904 case 2: {
905 if (instr->Bit(22) == 0) {
906 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
907 } else {
908 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
909 }
910 break;
911 }
912 case 3: {
913 if (instr->Bit(22) == 0) {
914 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
915 } else {
916 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
917 }
918 break;
919 }
920 default: {
921 // The PU field is a 2-bit field.
922 UNREACHABLE();
923 break;
924 }
925 }
926 return;
927 }
928 } else {
929 switch (instr->OpcodeField()) {
930 case AND: {
931 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
932 break;
933 }
934 case EOR: {
935 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
936 break;
937 }
938 case SUB: {
939 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
940 break;
941 }
942 case RSB: {
943 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
944 break;
945 }
946 case ADD: {
947 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
948 break;
949 }
950 case ADC: {
951 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
952 break;
953 }
954 case SBC: {
955 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
956 break;
957 }
958 case RSC: {
959 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
960 break;
961 }
962 case TST: {
963 if (instr->HasS()) {
964 Format(instr, "tst'cond 'rn, 'shift_op");
965 } else {
966 Unknown(instr); // not used by V8
967 }
968 break;
969 }
970 case TEQ: {
971 if (instr->HasS()) {
972 Format(instr, "teq'cond 'rn, 'shift_op");
973 } else {
974 switch (instr->Bits(7, 4)) {
975 case BX:
976 Format(instr, "bx'cond 'rm");
977 break;
978 case BLX:
979 Format(instr, "blx'cond 'rm");
980 break;
981 default:
982 Unknown(instr); // not used by V8
983 break;
984 }
985 }
986 break;
987 }
988 case CMP: {
989 if (instr->HasS()) {
990 Format(instr, "cmp'cond 'rn, 'shift_op");
991 } else {
992 Unknown(instr); // not used by V8
993 }
994 break;
995 }
996 case CMN: {
997 if (instr->HasS()) {
998 Format(instr, "cmn'cond 'rn, 'shift_op");
999 } else {
1000 switch (instr->Bits(7, 4)) {
1001 case CLZ:
1002 Format(instr, "clz'cond 'rd, 'rm");
1003 break;
1004 default:
1005 Unknown(instr); // not used by V8
1006 break;
1007 }
1008 }
1009 break;
1010 }
1011 case ORR: {
1012 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
1013 break;
1014 }
1015 case MOV: {
1016 Format(instr, "mov'cond's 'rd, 'shift_op");
1017 break;
1018 }
1019 case BIC: {
1020 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
1021 break;
1022 }
1023 case MVN: {
1024 Format(instr, "mvn'cond's 'rd, 'shift_op");
1025 break;
1026 }
1027 default: {
1028 // The Opcode field is a 4-bit field.
1029 UNREACHABLE();
1030 break;
1031 }
1032 }
1033 }
1034 }
1035
1036
1037 void Decoder::DecodeType2(Instr* instr) {
1038 switch (instr->PUField()) {
1039 case 0: {
1040 if (instr->HasW()) {
1041 Unknown(instr); // not used in V8
1042 }
1043 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
1044 break;
1045 }
1046 case 1: {
1047 if (instr->HasW()) {
1048 Unknown(instr); // not used in V8
1049 }
1050 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
1051 break;
1052 }
1053 case 2: {
1054 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
1055 break;
1056 }
1057 case 3: {
1058 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
1059 break;
1060 }
1061 default: {
1062 // The PU field is a 2-bit field.
1063 UNREACHABLE();
1064 break;
1065 }
1066 }
1067 }
1068
1069
1070 void Decoder::DecodeType3(Instr* instr) {
1071 switch (instr->PUField()) {
1072 case 0: {
1073 ASSERT(!instr->HasW());
1074 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
1075 break;
1076 }
1077 case 1: {
1078 ASSERT(!instr->HasW());
1079 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
1080 break;
1081 }
1082 case 2: {
1083 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1084 break;
1085 }
1086 case 3: {
1087 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1088 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1089 uint32_t lsbit = static_cast<uint32_t>(instr->ShiftAmountField());
1090 uint32_t msbit = widthminus1 + lsbit;
1091 if (msbit <= 31) {
1092 Format(instr, "ubfx'cond 'rd, 'rm, #'off7to11, #'off16to20");
1093 } else {
1094 UNREACHABLE();
1095 }
1096 } else {
1097 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1098 }
1099 break;
1100 }
1101 default: {
1102 // The PU field is a 2-bit field.
1103 UNREACHABLE();
1104 break;
1105 }
1106 }
1107 }
1108
1109
1110 void Decoder::DecodeType4(Instr* instr) {
1111 ASSERT(instr->Bit(22) == 0); // Privileged mode currently not supported.
1112 if (instr->HasL()) {
1113 Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1114 } else {
1115 Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1116 }
1117 }
1118
1119
1120 void Decoder::DecodeType5(Instr* instr) {
1121 Format(instr, "b'l'cond 'target");
1122 }
1123
1124
1125 void Decoder::DecodeType6(Instr* instr) {
1126 DecodeType6CoprocessorIns(instr);
1127 }
1128
1129
1130 void Decoder::DecodeType7(Instr* instr) {
1131 if (instr->Bit(24) == 1) {
1132 Format(instr, "swi'cond 'swi");
1133 } else {
1134 DecodeTypeVFP(instr);
1135 }
1136 }
1137
1138 void Decoder::DecodeUnconditional(Instr* instr) {
1139 if (instr->Bits(7, 4) == 0xB && instr->Bits(27, 25) == 0 && instr->HasL()) {
1140 Format(instr, "'memop'h'pu 'rd, ");
1141 bool immediate = instr->HasB();
1142 switch (instr->PUField()) {
1143 case 0: {
1144 // Post index, negative.
1145 if (instr->HasW()) {
1146 Unknown(instr);
1147 break;
1148 }
1149 if (immediate) {
1150 Format(instr, "['rn], #-'imm12");
1151 } else {
1152 Format(instr, "['rn], -'rm");
1153 }
1154 break;
1155 }
1156 case 1: {
1157 // Post index, positive.
1158 if (instr->HasW()) {
1159 Unknown(instr);
1160 break;
1161 }
1162 if (immediate) {
1163 Format(instr, "['rn], #+'imm12");
1164 } else {
1165 Format(instr, "['rn], +'rm");
1166 }
1167 break;
1168 }
1169 case 2: {
1170 // Pre index or offset, negative.
1171 if (immediate) {
1172 Format(instr, "['rn, #-'imm12]'w");
1173 } else {
1174 Format(instr, "['rn, -'rm]'w");
1175 }
1176 break;
1177 }
1178 case 3: {
1179 // Pre index or offset, positive.
1180 if (immediate) {
1181 Format(instr, "['rn, #+'imm12]'w");
1182 } else {
1183 Format(instr, "['rn, +'rm]'w");
1184 }
1185 break;
1186 }
1187 default: {
1188 // The PU field is a 2-bit field.
1189 UNREACHABLE();
1190 break;
1191 }
1192 }
1193 return;
1194 }
1195 Format(instr, "break 'msg");
1196 }
1197
1198
1199 // void Decoder::DecodeTypeVFP(Instr* instr)
1200 // vmov: Sn = Rt
1201 // vmov: Rt = Sn
1202 // vcvt: Dd = Sm
1203 // vcvt: Sd = Dm
1204 // Dd = vadd(Dn, Dm)
1205 // Dd = vsub(Dn, Dm)
1206 // Dd = vmul(Dn, Dm)
1207 // Dd = vdiv(Dn, Dm)
1208 // vcmp(Dd, Dm)
1209 // VMRS
1210 void Decoder::DecodeTypeVFP(Instr* instr) {
1211 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
1212
1213 if (instr->Bit(23) == 1) {
1214 if ((instr->Bits(21, 19) == 0x7) &&
1215 (instr->Bits(18, 16) == 0x5) &&
1216 (instr->Bits(11, 9) == 0x5) &&
1217 (instr->Bit(8) == 1) &&
1218 (instr->Bit(6) == 1) &&
1219 (instr->Bit(4) == 0)) {
1220 Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm");
1221 } else if ((instr->Bits(21, 19) == 0x7) &&
1222 (instr->Bits(18, 16) == 0x0) &&
1223 (instr->Bits(11, 9) == 0x5) &&
1224 (instr->Bit(8) == 1) &&
1225 (instr->Bit(7) == 1) &&
1226 (instr->Bit(6) == 1) &&
1227 (instr->Bit(4) == 0)) {
1228 Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm");
1229 } else if ((instr->Bit(21) == 0x0) &&
1230 (instr->Bit(20) == 0x0) &&
1231 (instr->Bits(11, 9) == 0x5) &&
1232 (instr->Bit(8) == 1) &&
1233 (instr->Bit(6) == 0) &&
1234 (instr->Bit(4) == 0)) {
1235 Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm");
1236 } else if ((instr->Bits(21, 20) == 0x3) &&
1237 (instr->Bits(19, 16) == 0x4) &&
1238 (instr->Bits(11, 9) == 0x5) &&
1239 (instr->Bit(8) == 0x1) &&
1240 (instr->Bit(6) == 0x1) &&
1241 (instr->Bit(4) == 0x0)) {
1242 Format(instr, "vcmp.f64'cond 'Dd, 'Dm");
1243 } else if ((instr->Bits(23, 20) == 0xF) &&
1244 (instr->Bits(19, 16) == 0x1) &&
1245 (instr->Bits(11, 8) == 0xA) &&
1246 (instr->Bits(7, 5) == 0x0) &&
1247 (instr->Bit(4) == 0x1) &&
1248 (instr->Bits(3, 0) == 0x0)) {
1249 if (instr->Bits(15, 12) == 0xF)
1250 Format(instr, "vmrs'cond APSR, FPSCR");
1251 else
1252 Unknown(instr); // Not used by V8.
1253 } else {
1254 Unknown(instr); // Not used by V8.
1255 }
1256 } else if (instr->Bit(21) == 1) {
1257 if ((instr->Bit(20) == 0x1) &&
1258 (instr->Bits(11, 9) == 0x5) &&
1259 (instr->Bit(8) == 0x1) &&
1260 (instr->Bit(6) == 0) &&
1261 (instr->Bit(4) == 0)) {
1262 Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm");
1263 } else if ((instr->Bit(20) == 0x1) &&
1264 (instr->Bits(11, 9) == 0x5) &&
1265 (instr->Bit(8) == 0x1) &&
1266 (instr->Bit(6) == 1) &&
1267 (instr->Bit(4) == 0)) {
1268 Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm");
1269 } else if ((instr->Bit(20) == 0x0) &&
1270 (instr->Bits(11, 9) == 0x5) &&
1271 (instr->Bit(8) == 0x1) &&
1272 (instr->Bit(6) == 0) &&
1273 (instr->Bit(4) == 0)) {
1274 Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm");
1275 } else {
1276 Unknown(instr); // Not used by V8.
1277 }
1278 } else {
1279 if ((instr->Bit(20) == 0x0) &&
1280 (instr->Bits(11, 8) == 0xA) &&
1281 (instr->Bits(6, 5) == 0x0) &&
1282 (instr->Bit(4) == 1) &&
1283 (instr->Bits(3, 0) == 0x0)) {
1284 Format(instr, "vmov'cond 'Sn, 'rt");
1285 } else if ((instr->Bit(20) == 0x1) &&
1286 (instr->Bits(11, 8) == 0xA) &&
1287 (instr->Bits(6, 5) == 0x0) &&
1288 (instr->Bit(4) == 1) &&
1289 (instr->Bits(3, 0) == 0x0)) {
1290 Format(instr, "vmov'cond 'rt, 'Sn");
1291 } else {
1292 Unknown(instr); // Not used by V8.
1293 }
1294 }
1295 }
1296
1297
1298 // Decode Type 6 coprocessor instructions.
1299 // Dm = vmov(Rt, Rt2)
1300 // <Rt, Rt2> = vmov(Dm)
1301 // Ddst = MEM(Rbase + 4*offset).
1302 // MEM(Rbase + 4*offset) = Dsrc.
1303 void Decoder::DecodeType6CoprocessorIns(Instr* instr) {
1304 ASSERT((instr->TypeField() == 6));
1305
1306 if (instr->CoprocessorField() != 0xB) {
1307 Unknown(instr); // Not used by V8.
1308 } else {
1309 switch (instr->OpcodeField()) {
1310 case 0x2:
1311 // Load and store double to two GP registers
1312 if (instr->Bits(7, 4) != 0x1) {
1313 Unknown(instr); // Not used by V8.
1314 } else if (instr->HasL()) {
1315 Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1316 } else {
1317 Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1318 }
1319 break;
1320 case 0x8:
1321 if (instr->HasL()) {
1322 Format(instr, "vldr'cond 'Dd, ['rn - 4*'off8]");
1323 } else {
1324 Format(instr, "vstr'cond 'Dd, ['rn - 4*'off8]");
1325 }
1326 break;
1327 case 0xC:
1328 if (instr->HasL()) {
1329 Format(instr, "vldr'cond 'Dd, ['rn + 4*'off8]");
1330 } else {
1331 Format(instr, "vstr'cond 'Dd, ['rn + 4*'off8]");
1332 }
1333 break;
1334 default:
1335 Unknown(instr); // Not used by V8.
1336 break;
1337 }
1338 }
1339 }
1340
1341
1342 // Disassemble the instruction at *instr_ptr into the output buffer.
1343 int Decoder::InstructionDecode(byte* instr_ptr) {
1344 if (reinterpret_cast<int32_t>(instr_ptr) & 1) {
1345 InstrThumb2 instr(instr_ptr);
1346 return InstructionDecodeThumb2(instr);
1347 } else {
1348 return InstructionDecodeArm(instr_ptr);
1349 }
1350 }
1351
1352 int Decoder::InstructionDecodeArm(byte* instr_ptr) {
1353 Instr* instr = Instr::At(instr_ptr);
1354 // Print raw instruction bytes.
1355 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
1356 "%08x ",
1357 instr->InstructionBits());
1358 if (instr->ConditionField() == special_condition) {
1359 DecodeUnconditional(instr);
1360 return Instr::kInstrSize;
1361 }
1362 switch (instr->TypeField()) {
1363 case 0:
1364 case 1: {
1365 DecodeType01(instr);
1366 break;
1367 }
1368 case 2: {
1369 DecodeType2(instr);
1370 break;
1371 }
1372 case 3: {
1373 DecodeType3(instr);
1374 break;
1375 }
1376 case 4: {
1377 DecodeType4(instr);
1378 break;
1379 }
1380 case 5: {
1381 DecodeType5(instr);
1382 break;
1383 }
1384 case 6: {
1385 DecodeType6(instr);
1386 break;
1387 }
1388 case 7: {
1389 DecodeType7(instr);
1390 break;
1391 }
1392 default: {
1393 // The type field is 3-bits in the ARM encoding.
1394 UNREACHABLE();
1395 break;
1396 }
1397 }
1398 return Instr::kInstrSize;
1399 }
1400
1401
1402 int Decoder::InstructionDecodeThumb2(const InstrThumb2& instr) {
1403 switch (instr.Op()) {
1404 case OP_ADD:
1405 Format(instr, "and's 'rd, 'rn, 'shift_op");
1406 break;
1407 case OP_AND:
1408 Format(instr, "and's 'rd, 'rn, 'shift_op");
1409 break;
1410 case OP_SUB:
1411 Format(instr, "sub's 'rd, 'rn, 'shift_op");
1412 break;
1413 default:
1414 UNIMPLEMENTED();
1415 break;
1416 }
1417 return instr.Size();
1418 }
1419
1420
1421 } } // namespace assembler::arm
1422
1423
1424
1425 //------------------------------------------------------------------------------
1426
1427 namespace disasm {
1428
1429 namespace v8i = v8::internal;
1430
1431
1432 const char* NameConverter::NameOfAddress(byte* addr) const {
1433 static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
1434 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
1435 return tmp_buffer.start();
1436 }
1437
1438
1439 const char* NameConverter::NameOfConstant(byte* addr) const {
1440 return NameOfAddress(addr);
1441 }
1442
1443
1444 const char* NameConverter::NameOfCPURegister(int reg) const {
1445 return assembler::arm::Registers::Name(reg);
1446 }
1447
1448
1449 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1450 UNREACHABLE(); // ARM does not have the concept of a byte register
1451 return "nobytereg";
1452 }
1453
1454
1455 const char* NameConverter::NameOfXMMRegister(int reg) const {
1456 UNREACHABLE(); // ARM does not have any XMM registers
1457 return "noxmmreg";
1458 }
1459
1460
1461 const char* NameConverter::NameInCode(byte* addr) const {
1462 // The default name converter is called for unknown code. So we will not try
1463 // to access any memory.
1464 return "";
1465 }
1466
1467
1468 //------------------------------------------------------------------------------
1469
1470 Disassembler::Disassembler(const NameConverter& converter)
1471 : converter_(converter) {}
1472
1473
1474 Disassembler::~Disassembler() {}
1475
1476
1477 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1478 byte* instruction) {
1479 assembler::arm::Decoder d(converter_, buffer);
1480 return d.InstructionDecode(instruction);
1481 }
1482
1483
1484 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1485 int instruction_bits = *(reinterpret_cast<int*>(instruction));
1486 if ((instruction_bits & 0xfff00000) == 0x03000000) {
1487 return instruction_bits & 0x0000ffff;
1488 } else {
1489 return -1;
1490 }
1491 }
1492
1493
1494 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1495 NameConverter converter;
1496 Disassembler d(converter);
1497 for (byte* pc = begin; pc < end;) {
1498 v8::internal::EmbeddedVector<char, 128> buffer;
1499 buffer[0] = '\0';
1500 byte* prev_pc = pc;
1501 pc += d.InstructionDecode(buffer, pc);
1502 fprintf(f, "%p %08x %s\n",
1503 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1504 }
1505 }
1506
1507
1508 } // namespace disasm
OLDNEW
« no previous file with comments | « src/arm/debug-thumb2.cc ('k') | src/arm/instr-thumb2.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698