The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / disasm-arm.cc @ 40c0f755

History | View | Annotate | Download (24.4 KB)

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
    default:
265
      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
266
                                           "%d",
267
                                           swi);
268
      return;
269
  }
270
}
271

    
272

    
273
// Handle all register based formatting in this function to reduce the
274
// complexity of FormatOption.
275
int Decoder::FormatRegister(Instr* instr, const char* format) {
276
  ASSERT(format[0] == 'r');
277
  if (format[1] == 'n') {  // 'rn: Rn register
278
    int reg = instr->RnField();
279
    PrintRegister(reg);
280
    return 2;
281
  } else if (format[1] == 'd') {  // 'rd: Rd register
282
    int reg = instr->RdField();
283
    PrintRegister(reg);
284
    return 2;
285
  } else if (format[1] == 's') {  // 'rs: Rs register
286
    int reg = instr->RsField();
287
    PrintRegister(reg);
288
    return 2;
289
  } else if (format[1] == 'm') {  // 'rm: Rm register
290
    int reg = instr->RmField();
291
    PrintRegister(reg);
292
    return 2;
293
  } else if (format[1] == 'l') {
294
    // 'rlist: register list for load and store multiple instructions
295
    ASSERT(STRING_STARTS_WITH(format, "rlist"));
296
    int rlist = instr->RlistField();
297
    int reg = 0;
298
    Print("{");
299
    // Print register list in ascending order, by scanning the bit mask.
300
    while (rlist != 0) {
301
      if ((rlist & 1) != 0) {
302
        PrintRegister(reg);
303
        if ((rlist >> 1) != 0) {
304
          Print(", ");
305
        }
306
      }
307
      reg++;
308
      rlist >>= 1;
309
    }
310
    Print("}");
311
    return 5;
312
  }
313
  UNREACHABLE();
314
  return -1;
315
}
316

    
317

    
318
// FormatOption takes a formatting string and interprets it based on
319
// the current instructions. The format string points to the first
320
// character of the option string (the option escape has already been
321
// consumed by the caller.)  FormatOption returns the number of
322
// characters that were consumed from the formatting string.
323
int Decoder::FormatOption(Instr* instr, const char* format) {
324
  switch (format[0]) {
325
    case 'a': {  // 'a: accumulate multiplies
326
      if (instr->Bit(21) == 0) {
327
        Print("ul");
328
      } else {
329
        Print("la");
330
      }
331
      return 1;
332
    }
333
    case 'b': {  // 'b: byte loads or stores
334
      if (instr->HasB()) {
335
        Print("b");
336
      }
337
      return 1;
338
    }
339
    case 'c': {  // 'cond: conditional execution
340
      ASSERT(STRING_STARTS_WITH(format, "cond"));
341
      PrintCondition(instr);
342
      return 4;
343
    }
344
    case 'h': {  // 'h: halfword operation for extra loads and stores
345
      if (instr->HasH()) {
346
        Print("h");
347
      } else {
348
        Print("b");
349
      }
350
      return 1;
351
    }
352
    case 'l': {  // 'l: branch and link
353
      if (instr->HasLink()) {
354
        Print("l");
355
      }
356
      return 1;
357
    }
358
    case 'm': {
359
      if (format[1] == 'e') {  // 'memop: load/store instructions
360
        ASSERT(STRING_STARTS_WITH(format, "memop"));
361
        if (instr->HasL()) {
362
          Print("ldr");
363
        } else {
364
          Print("str");
365
        }
366
        return 5;
367
      }
368
      // 'msg: for simulator break instructions
369
      ASSERT(STRING_STARTS_WITH(format, "msg"));
370
      byte* str =
371
          reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
372
      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
373
                                           "%s", converter_.NameInCode(str));
374
      return 3;
375
    }
376
    case 'o': {
377
      if (format[3] == '1') {
378
        // 'off12: 12-bit offset for load and store instructions
379
        ASSERT(STRING_STARTS_WITH(format, "off12"));
380
        out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
381
                                             "%d", instr->Offset12Field());
382
        return 5;
383
      }
384
      // 'off8: 8-bit offset for extra load and store instructions
385
      ASSERT(STRING_STARTS_WITH(format, "off8"));
386
      int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
387
      out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
388
                                           "%d", offs8);
389
      return 4;
390
    }
391
    case 'p': {  // 'pu: P and U bits for load and store instructions
392
      ASSERT(STRING_STARTS_WITH(format, "pu"));
393
      PrintPU(instr);
394
      return 2;
395
    }
396
    case 'r': {
397
      return FormatRegister(instr, format);
398
    }
399
    case 's': {
400
      if (format[1] == 'h') {  // 'shift_op or 'shift_rm
401
        if (format[6] == 'o') {  // 'shift_op
402
          ASSERT(STRING_STARTS_WITH(format, "shift_op"));
403
          if (instr->TypeField() == 0) {
404
            PrintShiftRm(instr);
405
          } else {
406
            ASSERT(instr->TypeField() == 1);
407
            PrintShiftImm(instr);
408
          }
409
          return 8;
410
        } else {  // 'shift_rm
411
          ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
412
          PrintShiftRm(instr);
413
          return 8;
414
        }
415
      } else if (format[1] == 'w') {  // 'swi
416
        ASSERT(STRING_STARTS_WITH(format, "swi"));
417
        PrintSoftwareInterrupt(instr->SwiField());
418
        return 3;
419
      } else if (format[1] == 'i') {  // 'sign: signed extra loads and stores
420
        ASSERT(STRING_STARTS_WITH(format, "sign"));
421
        if (instr->HasSign()) {
422
          Print("s");
423
        }
424
        return 4;
425
      }
426
      // 's: S field of data processing instructions
427
      if (instr->HasS()) {
428
        Print("s");
429
      }
430
      return 1;
431
    }
432
    case 't': {  // 'target: target of branch instructions
433
      ASSERT(STRING_STARTS_WITH(format, "target"));
434
      int off = (instr->SImmed24Field() << 2) + 8;
435
      out_buffer_pos_ += v8i::OS::SNPrintF(
436
          out_buffer_ + out_buffer_pos_,
437
          "%+d -> %s",
438
          off,
439
          converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
440
      return 6;
441
    }
442
    case 'u': {  // 'u: signed or unsigned multiplies
443
      if (instr->Bit(22) == 0) {
444
        Print("u");
445
      } else {
446
        Print("s");
447
      }
448
      return 1;
449
    }
450
    case 'w': {  // 'w: W field of load and store instructions
451
      if (instr->HasW()) {
452
        Print("!");
453
      }
454
      return 1;
455
    }
456
    default: {
457
      UNREACHABLE();
458
      break;
459
    }
460
  }
461
  UNREACHABLE();
462
  return -1;
463
}
464

    
465

    
466
// Format takes a formatting string for a whole instruction and prints it into
467
// the output buffer. All escaped options are handed to FormatOption to be
468
// parsed further.
469
void Decoder::Format(Instr* instr, const char* format) {
470
  char cur = *format++;
471
  while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
472
    if (cur == '\'') {  // Single quote is used as the formatting escape.
473
      format += FormatOption(instr, format);
474
    } else {
475
      out_buffer_[out_buffer_pos_++] = cur;
476
    }
477
    cur = *format++;
478
  }
479
  out_buffer_[out_buffer_pos_]  = '\0';
480
}
481

    
482

    
483
// For currently unimplemented decodings the disassembler calls Unknown(instr)
484
// which will just print "unknown" of the instruction bits.
485
void Decoder::Unknown(Instr* instr) {
486
  Format(instr, "unknown");
487
}
488

    
489

    
490
void Decoder::DecodeType01(Instr* instr) {
491
  int type = instr->TypeField();
492
  if ((type == 0) && instr->IsSpecialType0()) {
493
    // multiply instruction or extra loads and stores
494
    if (instr->Bits(7, 4) == 9) {
495
      if (instr->Bit(24) == 0) {
496
        // multiply instructions
497
        if (instr->Bit(23) == 0) {
498
          if (instr->Bit(21) == 0) {
499
            Format(instr, "mul'cond's 'rd, 'rm, 'rs");
500
          } else {
501
            Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn");
502
          }
503
        } else {
504
          Format(instr, "'um'al'cond's 'rn, 'rd, 'rs, 'rm");
505
        }
506
      } else {
507
        Unknown(instr);  // not used by V8
508
      }
509
    } else {
510
      // extra load/store instructions
511
      switch (instr->PUField()) {
512
        case 0: {
513
          if (instr->Bit(22) == 0) {
514
            Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
515
          } else {
516
            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
517
          }
518
          break;
519
        }
520
        case 1: {
521
          if (instr->Bit(22) == 0) {
522
            Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
523
          } else {
524
            Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
525
          }
526
          break;
527
        }
528
        case 2: {
529
          if (instr->Bit(22) == 0) {
530
            Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
531
          } else {
532
            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
533
          }
534
          break;
535
        }
536
        case 3: {
537
          if (instr->Bit(22) == 0) {
538
            Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
539
          } else {
540
            Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
541
          }
542
          break;
543
        }
544
        default: {
545
          // The PU field is a 2-bit field.
546
          UNREACHABLE();
547
          break;
548
        }
549
      }
550
      return;
551
    }
552
  } else {
553
    switch (instr->OpcodeField()) {
554
      case AND: {
555
        Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
556
        break;
557
      }
558
      case EOR: {
559
        Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
560
        break;
561
      }
562
      case SUB: {
563
        Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
564
        break;
565
      }
566
      case RSB: {
567
        Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
568
        break;
569
      }
570
      case ADD: {
571
        Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
572
        break;
573
      }
574
      case ADC: {
575
        Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
576
        break;
577
      }
578
      case SBC: {
579
        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
580
        break;
581
      }
582
      case RSC: {
583
        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
584
        break;
585
      }
586
      case TST: {
587
        if (instr->HasS()) {
588
          Format(instr, "tst'cond 'rn, 'shift_op");
589
        } else {
590
          Unknown(instr);  // not used by V8
591
        }
592
        break;
593
      }
594
      case TEQ: {
595
        if (instr->HasS()) {
596
          Format(instr, "teq'cond 'rn, 'shift_op");
597
        } else {
598
          Unknown(instr);  // not used by V8
599
        }
600
        break;
601
      }
602
      case CMP: {
603
        if (instr->HasS()) {
604
          Format(instr, "cmp'cond 'rn, 'shift_op");
605
        } else {
606
          Unknown(instr);  // not used by V8
607
        }
608
        break;
609
      }
610
      case CMN: {
611
        if (instr->HasS()) {
612
          Format(instr, "cmn'cond 'rn, 'shift_op");
613
        } else {
614
          Unknown(instr);  // not used by V8
615
        }
616
        break;
617
      }
618
      case ORR: {
619
        Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
620
        break;
621
      }
622
      case MOV: {
623
        Format(instr, "mov'cond's 'rd, 'shift_op");
624
        break;
625
      }
626
      case BIC: {
627
        Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
628
        break;
629
      }
630
      case MVN: {
631
        Format(instr, "mvn'cond's 'rd, 'shift_op");
632
        break;
633
      }
634
      default: {
635
        // The Opcode field is a 4-bit field.
636
        UNREACHABLE();
637
        break;
638
      }
639
    }
640
  }
641
}
642

    
643

    
644
void Decoder::DecodeType2(Instr* instr) {
645
  switch (instr->PUField()) {
646
    case 0: {
647
      if (instr->HasW()) {
648
        Unknown(instr);  // not used in V8
649
      }
650
      Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
651
      break;
652
    }
653
    case 1: {
654
      if (instr->HasW()) {
655
        Unknown(instr);  // not used in V8
656
      }
657
      Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
658
      break;
659
    }
660
    case 2: {
661
      Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
662
      break;
663
    }
664
    case 3: {
665
      Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
666
      break;
667
    }
668
    default: {
669
      // The PU field is a 2-bit field.
670
      UNREACHABLE();
671
      break;
672
    }
673
  }
674
}
675

    
676

    
677
void Decoder::DecodeType3(Instr* instr) {
678
  switch (instr->PUField()) {
679
    case 0: {
680
      ASSERT(!instr->HasW());
681
      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
682
      break;
683
    }
684
    case 1: {
685
      ASSERT(!instr->HasW());
686
      Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
687
      break;
688
    }
689
    case 2: {
690
      Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
691
      break;
692
    }
693
    case 3: {
694
      Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
695
      break;
696
    }
697
    default: {
698
      // The PU field is a 2-bit field.
699
      UNREACHABLE();
700
      break;
701
    }
702
  }
703
}
704

    
705

    
706
void Decoder::DecodeType4(Instr* instr) {
707
  ASSERT(instr->Bit(22) == 0);  // Privileged mode currently not supported.
708
  if (instr->HasL()) {
709
    Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
710
  } else {
711
    Format(instr, "stm'cond'pu 'rn'w, 'rlist");
712
  }
713
}
714

    
715

    
716
void Decoder::DecodeType5(Instr* instr) {
717
  Format(instr, "b'l'cond 'target");
718
}
719

    
720

    
721
void Decoder::DecodeType6(Instr* instr) {
722
  // Coprocessor instructions currently not supported.
723
  Unknown(instr);
724
}
725

    
726

    
727
void Decoder::DecodeType7(Instr* instr) {
728
  if (instr->Bit(24) == 1) {
729
    Format(instr, "swi'cond 'swi");
730
  } else {
731
    // Coprocessor instructions currently not supported.
732
    Unknown(instr);
733
  }
734
}
735

    
736

    
737
// Disassemble the instruction at *instr_ptr into the output buffer.
738
int Decoder::InstructionDecode(byte* instr_ptr) {
739
  Instr* instr = Instr::At(instr_ptr);
740
  // Print raw instruction bytes.
741
  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
742
                                       "%08x       ",
743
                                       instr->InstructionBits());
744
  if (instr->ConditionField() == special_condition) {
745
    Format(instr, "break 'msg");
746
    return Instr::kInstrSize;
747
  }
748
  switch (instr->TypeField()) {
749
    case 0:
750
    case 1: {
751
      DecodeType01(instr);
752
      break;
753
    }
754
    case 2: {
755
      DecodeType2(instr);
756
      break;
757
    }
758
    case 3: {
759
      DecodeType3(instr);
760
      break;
761
    }
762
    case 4: {
763
      DecodeType4(instr);
764
      break;
765
    }
766
    case 5: {
767
      DecodeType5(instr);
768
      break;
769
    }
770
    case 6: {
771
      DecodeType6(instr);
772
      break;
773
    }
774
    case 7: {
775
      DecodeType7(instr);
776
      break;
777
    }
778
    default: {
779
      // The type field is 3-bits in the ARM encoding.
780
      UNREACHABLE();
781
      break;
782
    }
783
  }
784
  return Instr::kInstrSize;
785
}
786

    
787

    
788
} }  // namespace assembler::arm
789

    
790

    
791

    
792
//------------------------------------------------------------------------------
793

    
794
namespace disasm {
795

    
796
namespace v8i = v8::internal;
797

    
798

    
799
static const int kMaxRegisters = 16;
800

    
801
// These register names are defined in a way to match the native disassembler
802
// formatting. See for example the command "objdump -d <binary file>".
803
static const char* reg_names[kMaxRegisters] = {
804
  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
805
  "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
806
};
807

    
808

    
809
const char* NameConverter::NameOfAddress(byte* addr) const {
810
  static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
811
  v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
812
  return tmp_buffer.start();
813
}
814

    
815

    
816
const char* NameConverter::NameOfConstant(byte* addr) const {
817
  return NameOfAddress(addr);
818
}
819

    
820

    
821
const char* NameConverter::NameOfCPURegister(int reg) const {
822
  const char* result;
823
  if ((0 <= reg) && (reg < kMaxRegisters)) {
824
    result = reg_names[reg];
825
  } else {
826
    result = "noreg";
827
  }
828
  return result;
829
}
830

    
831

    
832
const char* NameConverter::NameOfByteCPURegister(int reg) const {
833
  UNREACHABLE();  // ARM does not have the concept of a byte register
834
  return "nobytereg";
835
}
836

    
837

    
838
const char* NameConverter::NameOfXMMRegister(int reg) const {
839
  UNREACHABLE();  // ARM does not have any XMM registers
840
  return "noxmmreg";
841
}
842

    
843

    
844
const char* NameConverter::NameInCode(byte* addr) const {
845
  // The default name converter is called for unknown code. So we will not try
846
  // to access any memory.
847
  return "";
848
}
849

    
850

    
851
//------------------------------------------------------------------------------
852

    
853
Disassembler::Disassembler(const NameConverter& converter)
854
    : converter_(converter) {}
855

    
856

    
857
Disassembler::~Disassembler() {}
858

    
859

    
860
int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
861
                                    byte* instruction) {
862
  assembler::arm::Decoder d(converter_, buffer);
863
  return d.InstructionDecode(instruction);
864
}
865

    
866

    
867
int Disassembler::ConstantPoolSizeAt(byte* instruction) {
868
  int instruction_bits = *(reinterpret_cast<int*>(instruction));
869
  if ((instruction_bits & 0xfff00000) == 0x03000000) {
870
    return instruction_bits & 0x0000ffff;
871
  } else {
872
    return -1;
873
  }
874
}
875

    
876

    
877
void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
878
  NameConverter converter;
879
  Disassembler d(converter);
880
  for (byte* pc = begin; pc < end;) {
881
    v8::internal::EmbeddedVector<char, 128> buffer;
882
    buffer[0] = '\0';
883
    byte* prev_pc = pc;
884
    pc += d.InstructionDecode(buffer, pc);
885
    fprintf(f, "%p    %08x      %s\n",
886
            prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
887
  }
888
}
889

    
890

    
891
}  // namespace disasm