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

Side by Side Diff: runtime/vm/disassembler_arm.cc

Issue 18684008: Begins implementation of ARM neon instructions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/disassembler.h" 5 #include "vm/disassembler.h"
6 6
7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
8 #if defined(TARGET_ARCH_ARM) 8 #if defined(TARGET_ARCH_ARM)
9 #include "platform/assert.h" 9 #include "platform/assert.h"
10 10
(...skipping 15 matching lines...) Expand all
26 void InstructionDecode(uword pc); 26 void InstructionDecode(uword pc);
27 27
28 private: 28 private:
29 // Bottleneck functions to print into the out_buffer. 29 // Bottleneck functions to print into the out_buffer.
30 void Print(const char* str); 30 void Print(const char* str);
31 31
32 // Printing of common values. 32 // Printing of common values.
33 void PrintRegister(int reg); 33 void PrintRegister(int reg);
34 void PrintSRegister(int reg); 34 void PrintSRegister(int reg);
35 void PrintDRegister(int reg); 35 void PrintDRegister(int reg);
36 void PrintQRegister(int reg);
36 void PrintCondition(Instr* instr); 37 void PrintCondition(Instr* instr);
37 void PrintShiftRm(Instr* instr); 38 void PrintShiftRm(Instr* instr);
38 void PrintShiftImm(Instr* instr); 39 void PrintShiftImm(Instr* instr);
39 void PrintPU(Instr* instr); 40 void PrintPU(Instr* instr);
40 41
41 // Handle formatting of instructions and their options. 42 // Handle formatting of instructions and their options.
42 int FormatRegister(Instr* instr, const char* option); 43 int FormatRegister(Instr* instr, const char* option);
43 int FormatSRegister(Instr* instr, const char* option); 44 int FormatSRegister(Instr* instr, const char* option);
44 int FormatDRegister(Instr* instr, const char* option); 45 int FormatDRegister(Instr* instr, const char* option);
46 int FormatQRegister(Instr* instr, const char* option);
45 int FormatOption(Instr* instr, const char* option); 47 int FormatOption(Instr* instr, const char* option);
46 void Format(Instr* instr, const char* format); 48 void Format(Instr* instr, const char* format);
47 void Unknown(Instr* instr); 49 void Unknown(Instr* instr);
48 50
49 // Each of these functions decodes one particular instruction type, a 3-bit 51 // Each of these functions decodes one particular instruction type, a 3-bit
50 // field in the instruction encoding. 52 // field in the instruction encoding.
51 // Types 0 and 1 are combined as they are largely the same except for the way 53 // Types 0 and 1 are combined as they are largely the same except for the way
52 // they interpret the shifter operand. 54 // they interpret the shifter operand.
53 void DecodeType01(Instr* instr); 55 void DecodeType01(Instr* instr);
54 void DecodeType2(Instr* instr); 56 void DecodeType2(Instr* instr);
55 void DecodeType3(Instr* instr); 57 void DecodeType3(Instr* instr);
56 void DecodeType4(Instr* instr); 58 void DecodeType4(Instr* instr);
57 void DecodeType5(Instr* instr); 59 void DecodeType5(Instr* instr);
58 void DecodeType6(Instr* instr); 60 void DecodeType6(Instr* instr);
59 void DecodeType7(Instr* instr); 61 void DecodeType7(Instr* instr);
62 void DecodeSIMDDataProcessing(Instr* instr);
60 63
61 // Convenience functions. 64 // Convenience functions.
62 char* get_buffer() const { return buffer_; } 65 char* get_buffer() const { return buffer_; }
63 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } 66 char* current_position_in_buffer() { return buffer_ + buffer_pos_; }
64 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } 67 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; }
65 68
66 char* buffer_; // Decode instructions into this buffer. 69 char* buffer_; // Decode instructions into this buffer.
67 size_t buffer_size_; // The size of the character buffer. 70 size_t buffer_size_; // The size of the character buffer.
68 size_t buffer_pos_; // Current character position in buffer. 71 size_t buffer_pos_; // Current character position in buffer.
69 72
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 133
131 void ARMDecoder::PrintDRegister(int reg) { 134 void ARMDecoder::PrintDRegister(int reg) {
132 ASSERT(0 <= reg); 135 ASSERT(0 <= reg);
133 ASSERT(reg < kNumberOfDRegisters); 136 ASSERT(reg < kNumberOfDRegisters);
134 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 137 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
135 remaining_size_in_buffer(), 138 remaining_size_in_buffer(),
136 "d%d", reg); 139 "d%d", reg);
137 } 140 }
138 141
139 142
143 void ARMDecoder::PrintQRegister(int reg) {
144 ASSERT(0 <= reg);
145 ASSERT(reg < kNumberOfQRegisters);
146 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
147 remaining_size_in_buffer(),
148 "q%d", reg);
149 }
150
151
140 // These shift names are defined in a way to match the native disassembler 152 // These shift names are defined in a way to match the native disassembler
141 // formatting. See for example the command "objdump -d <binary file>". 153 // formatting. See for example the command "objdump -d <binary file>".
142 static const char* shift_names[kMaxShift] = { 154 static const char* shift_names[kMaxShift] = {
143 "lsl", "lsr", "asr", "ror" 155 "lsl", "lsr", "asr", "ror"
144 }; 156 };
145 157
146 158
147 // Print the register shift operands for the instruction. Generally used for 159 // Print the register shift operands for the instruction. Generally used for
148 // data processing instructions. 160 // data processing instructions.
149 void ARMDecoder::PrintShiftRm(Instr* instr) { 161 void ARMDecoder::PrintShiftRm(Instr* instr) {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 } 356 }
345 } 357 }
346 Print("}"); 358 Print("}");
347 return 5; 359 return 5;
348 } 360 }
349 UNREACHABLE(); 361 UNREACHABLE();
350 return -1; 362 return -1;
351 } 363 }
352 364
353 365
366 int ARMDecoder::FormatQRegister(Instr* instr, const char* format) {
367 ASSERT(format[0] == 'q');
368 if (format[1] == 'n') { // 'qn: Qn register
369 int reg = instr->QnField();
370 PrintQRegister(reg);
371 return 2;
372 } else if (format[1] == 'd') { // 'qd: Qd register
373 int reg = instr->QdField();
374 PrintQRegister(reg);
375 return 2;
376 } else if (format[1] == 'm') { // 'qm: Qm register
377 int reg = instr->QmField();
378 PrintQRegister(reg);
379 return 2;
380 }
381 UNREACHABLE();
382 return -1;
383 }
384
385
354 // FormatOption takes a formatting string and interprets it based on 386 // FormatOption takes a formatting string and interprets it based on
355 // the current instructions. The format string points to the first 387 // the current instructions. The format string points to the first
356 // character of the option string (the option escape has already been 388 // character of the option string (the option escape has already been
357 // consumed by the caller.) FormatOption returns the number of 389 // consumed by the caller.) FormatOption returns the number of
358 // characters that were consumed from the formatting string. 390 // characters that were consumed from the formatting string.
359 int ARMDecoder::FormatOption(Instr* instr, const char* format) { 391 int ARMDecoder::FormatOption(Instr* instr, const char* format) {
360 switch (format[0]) { 392 switch (format[0]) {
361 case 'a': { // 'a: accumulate multiplies 393 case 'a': { // 'a: accumulate multiplies
362 if (instr->Bit(21) == 0) { 394 if (instr->Bit(21) == 0) {
363 Print("ul"); 395 Print("ul");
(...skipping 20 matching lines...) Expand all
384 uword destination = reinterpret_cast<uword>(instr) + off; 416 uword destination = reinterpret_cast<uword>(instr) + off;
385 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 417 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
386 remaining_size_in_buffer(), 418 remaining_size_in_buffer(),
387 "%#"Px"", 419 "%#"Px"",
388 destination); 420 destination);
389 return 4; 421 return 4;
390 } else { 422 } else {
391 return FormatDRegister(instr, format); 423 return FormatDRegister(instr, format);
392 } 424 }
393 } 425 }
426 case 'q': {
427 return FormatQRegister(instr, format);
428 }
394 case 'i': { // 'imm12_4, imm4_12, immf, or immd 429 case 'i': { // 'imm12_4, imm4_12, immf, or immd
395 uint16_t immed16; 430 uint16_t immed16;
396 if (format[3] == 'f') { 431 if (format[3] == 'f') {
397 ASSERT(STRING_STARTS_WITH(format, "immf")); 432 ASSERT(STRING_STARTS_WITH(format, "immf"));
398 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 433 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
399 remaining_size_in_buffer(), 434 remaining_size_in_buffer(),
400 "%f", 435 "%f",
401 instr->ImmFloatField()); 436 instr->ImmFloatField());
402 return 4; 437 return 4;
403 } else if (format[3] == 'd') { 438 } else if (format[3] == 'd') {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 } 474 }
440 case 'o': { 475 case 'o': {
441 if (format[3] == '1') { 476 if (format[3] == '1') {
442 if (format[4] == '0') { 477 if (format[4] == '0') {
443 // 'off10: 10-bit offset for VFP load and store instructions 478 // 'off10: 10-bit offset for VFP load and store instructions
444 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 479 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
445 remaining_size_in_buffer(), 480 remaining_size_in_buffer(),
446 "%d", 481 "%d",
447 instr->Bits(0, 8) << 2); 482 instr->Bits(0, 8) << 2);
448 } else { 483 } else {
449 // 'off12: 12-bit offset for load and store instructions 484 // 'off12: 12-bit offset for load and store instructions.
450 ASSERT(STRING_STARTS_WITH(format, "off12")); 485 ASSERT(STRING_STARTS_WITH(format, "off12"));
451 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 486 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
452 remaining_size_in_buffer(), 487 remaining_size_in_buffer(),
453 "%d", 488 "%d",
454 instr->Offset12Field()); 489 instr->Offset12Field());
455 } 490 }
456 return 5; 491 return 5;
457 } 492 }
458 // 'off8: 8-bit offset for extra load and store instructions 493 // 'off8: 8-bit offset for extra load and store instructions.
459 ASSERT(STRING_STARTS_WITH(format, "off8")); 494 ASSERT(STRING_STARTS_WITH(format, "off8"));
460 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField(); 495 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
461 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 496 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
462 remaining_size_in_buffer(), 497 remaining_size_in_buffer(),
463 "%d", 498 "%d",
464 offs8); 499 offs8);
465 return 4; 500 return 4;
466 } 501 }
467 case 'p': { // 'pu: P and U bits for load and store instructions 502 case 'p': { // 'pu: P and U bits for load and store instructions.
468 ASSERT(STRING_STARTS_WITH(format, "pu")); 503 ASSERT(STRING_STARTS_WITH(format, "pu"));
469 PrintPU(instr); 504 PrintPU(instr);
470 return 2; 505 return 2;
471 } 506 }
472 case 'r': { 507 case 'r': {
473 return FormatRegister(instr, format); 508 return FormatRegister(instr, format);
474 } 509 }
475 case 's': { 510 case 's': {
476 if (format[1] == 'h') { // 'shift_op or 'shift_rm 511 if (format[1] == 'h') { // 'shift_op or 'shift_rm
477 if (format[6] == 'o') { // 'shift_op 512 if (format[6] == 'o') { // 'shift_op
(...skipping 10 matching lines...) Expand all
488 PrintShiftRm(instr); 523 PrintShiftRm(instr);
489 return 8; 524 return 8;
490 } 525 }
491 } else if (format[1] == 'v') { // 'svc 526 } else if (format[1] == 'v') { // 'svc
492 ASSERT(STRING_STARTS_WITH(format, "svc")); 527 ASSERT(STRING_STARTS_WITH(format, "svc"));
493 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 528 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
494 remaining_size_in_buffer(), 529 remaining_size_in_buffer(),
495 "0x%x", 530 "0x%x",
496 instr->SvcField()); 531 instr->SvcField());
497 return 3; 532 return 3;
533 } else if (format[1] == 'z') {
534 // 'sz: Size field of SIMD instruction.
535 int sz = 8 << (instr->Bits(20, 2));
536 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
537 remaining_size_in_buffer(),
538 "I%d",
539 sz);
540 return 2;
498 } else if (format[1] == ' ') { 541 } else if (format[1] == ' ') {
499 // 's: S field of data processing instructions 542 // 's: S field of data processing instructions.
500 if (instr->HasS()) { 543 if (instr->HasS()) {
501 Print("s"); 544 Print("s");
502 } 545 }
503 return 1; 546 return 1;
504 } else { 547 } else {
505 return FormatSRegister(instr, format); 548 return FormatSRegister(instr, format);
506 } 549 }
507 } 550 }
508 case 't': { // 'target: target of branch instructions 551 case 't': { // 'target: target of branch instructions.
509 ASSERT(STRING_STARTS_WITH(format, "target")); 552 ASSERT(STRING_STARTS_WITH(format, "target"));
510 int off = (instr->SImmed24Field() << 2) + 8; 553 int off = (instr->SImmed24Field() << 2) + 8;
511 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), 554 buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
512 remaining_size_in_buffer(), 555 remaining_size_in_buffer(),
513 "%+d", 556 "%+d",
514 off); 557 off);
515 return 6; 558 return 6;
516 } 559 }
517 case 'u': { // 'u: signed or unsigned multiplies 560 case 'u': { // 'u: signed or unsigned multiplies.
518 if (instr->Bit(22) == 0) { 561 if (instr->Bit(22) == 0) {
519 Print("u"); 562 Print("u");
520 } else { 563 } else {
521 Print("s"); 564 Print("s");
522 } 565 }
523 return 1; 566 return 1;
524 } 567 }
525 case 'w': { // 'w: W field of load and store instructions 568 case 'w': { // 'w: W field of load and store instructions.
526 if (instr->HasW()) { 569 if (instr->HasW()) {
527 Print("!"); 570 Print("!");
528 } 571 }
529 return 1; 572 return 1;
530 } 573 }
531 case 'x': { // 'x: type of extra load/store instructions 574 case 'x': { // 'x: type of extra load/store instructions.
532 if (!instr->HasSign()) { 575 if (!instr->HasSign()) {
533 Print("h"); 576 Print("h");
534 } else if (instr->HasL()) { 577 } else if (instr->HasL()) {
535 if (instr->HasH()) { 578 if (instr->HasH()) {
536 Print("sh"); 579 Print("sh");
537 } else { 580 } else {
538 Print("sb"); 581 Print("sb");
539 } 582 }
540 } else { 583 } else {
541 Print("d"); 584 Print("d");
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 } else { 1259 } else {
1217 Unknown(instr); 1260 Unknown(instr);
1218 } 1261 }
1219 } 1262 }
1220 } else { 1263 } else {
1221 Unknown(instr); 1264 Unknown(instr);
1222 } 1265 }
1223 } 1266 }
1224 1267
1225 1268
1269 void ARMDecoder::DecodeSIMDDataProcessing(Instr* instr) {
1270 ASSERT(instr->ConditionField() == kSpecialCondition);
1271 if (instr->Bit(6) == 1) {
1272 if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 0) &&
1273 (instr->Bit(24) == 0)) {
1274 Format(instr, "vadd.'sz 'qd, 'qn, 'qm");
1275 } else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 0) &&
1276 (instr->Bit(24) == 0)) {
1277 Format(instr, "vadd.F32 'qd, 'qn, 'qm");
1278 } else {
1279 Unknown(instr);
1280 }
1281 } else {
1282 Unknown(instr);
1283 }
1284 }
1285
1286
1226 void ARMDecoder::InstructionDecode(uword pc) { 1287 void ARMDecoder::InstructionDecode(uword pc) {
1227 Instr* instr = Instr::At(pc); 1288 Instr* instr = Instr::At(pc);
1228 1289
1229 if (instr->ConditionField() == kSpecialCondition) { 1290 if (instr->ConditionField() == kSpecialCondition) {
1230 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { 1291 if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
1231 Format(instr, "clrex"); 1292 Format(instr, "clrex");
1232 } else { 1293 } else {
1233 Unknown(instr); 1294 if (instr->IsSIMDDataProcessing()) {
1295 DecodeSIMDDataProcessing(instr);
1296 } else {
1297 Unknown(instr);
1298 }
1234 } 1299 }
1235 } else { 1300 } else {
1236 switch (instr->TypeField()) { 1301 switch (instr->TypeField()) {
1237 case 0: 1302 case 0:
1238 case 1: { 1303 case 1: {
1239 DecodeType01(instr); 1304 DecodeType01(instr);
1240 break; 1305 break;
1241 } 1306 }
1242 case 2: { 1307 case 2: {
1243 DecodeType2(instr); 1308 DecodeType2(instr);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 human_buffer, 1379 human_buffer,
1315 sizeof(human_buffer), 1380 sizeof(human_buffer),
1316 pc); 1381 pc);
1317 pc += instruction_length; 1382 pc += instruction_length;
1318 } 1383 }
1319 } 1384 }
1320 1385
1321 } // namespace dart 1386 } // namespace dart
1322 1387
1323 #endif // defined TARGET_ARCH_ARM 1388 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698