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

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

Issue 651029: Forking disassembler and simulator for Thumb2 support; (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 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/constants-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 out_buffer_(out_buffer), 82 out_buffer_(out_buffer),
83 out_buffer_pos_(0) { 83 out_buffer_pos_(0) {
84 out_buffer_[out_buffer_pos_] = '\0'; 84 out_buffer_[out_buffer_pos_] = '\0';
85 } 85 }
86 86
87 ~Decoder() {} 87 ~Decoder() {}
88 88
89 // Writes one disassembled instruction into 'buffer' (0-terminated). 89 // Writes one disassembled instruction into 'buffer' (0-terminated).
90 // Returns the length of the disassembled machine instruction in bytes. 90 // Returns the length of the disassembled machine instruction in bytes.
91 int InstructionDecode(byte* instruction); 91 int InstructionDecode(byte* instruction);
92 int InstructionDecodeArm(byte* instruction);
93 int InstructionDecodeThumb2(const InstrThumb2& instr);
92 94
93 private: 95 private:
94 // Bottleneck functions to print into the out_buffer. 96 // Bottleneck functions to print into the out_buffer.
95 void PrintChar(const char ch); 97 void PrintChar(const char ch);
96 void Print(const char* str); 98 void Print(const char* str);
97 99
98 // Printing of common values. 100 // Printing of common values.
99 void PrintRegister(int reg); 101 void PrintRegister(int reg);
100 void PrintSRegister(int reg); 102 void PrintSRegister(int reg);
101 void PrintDRegister(int reg); 103 void PrintDRegister(int reg);
102 int FormatVFPRegister(Instr* instr, const char* format); 104 int FormatVFPRegister(Instr* instr, const char* format);
103 int FormatVFPinstruction(Instr* instr, const char* format); 105 int FormatVFPinstruction(Instr* instr, const char* format);
104 void PrintCondition(Instr* instr); 106 void PrintCondition(Instr* instr);
105 void PrintShiftRm(Instr* instr); 107 void PrintShiftRm(Instr* instr);
108 void PrintShiftRm(const InstrThumb2& instr);
106 void PrintShiftImm(Instr* instr); 109 void PrintShiftImm(Instr* instr);
110 void PrintShiftImm(const InstrThumb2& instr);
107 void PrintPU(Instr* instr); 111 void PrintPU(Instr* instr);
108 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi); 112 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
109 113
110 // Handle formatting of instructions and their options. 114 // Handle formatting of instructions and their options.
111 int FormatRegister(Instr* instr, const char* option); 115 int FormatRegister(Instr* instr, const char* option);
116 int FormatRegister(const InstrThumb2& instr, const char* option);
112 int FormatOption(Instr* instr, const char* option); 117 int FormatOption(Instr* instr, const char* option);
118 int FormatOption(const InstrThumb2& instr, const char* option);
113 void Format(Instr* instr, const char* format); 119 void Format(Instr* instr, const char* format);
120 void Format(const InstrThumb2& instr, const char* format);
114 void Unknown(Instr* instr); 121 void Unknown(Instr* instr);
122 void Unknown(const InstrThumb2& instr);
115 123
116 // Each of these functions decodes one particular instruction type, a 3-bit 124 // Each of these functions decodes one particular instruction type, a 3-bit
117 // field in the instruction encoding. 125 // field in the instruction encoding.
118 // Types 0 and 1 are combined as they are largely the same except for the way 126 // Types 0 and 1 are combined as they are largely the same except for the way
119 // they interpret the shifter operand. 127 // they interpret the shifter operand.
120 void DecodeType01(Instr* instr); 128 void DecodeType01(Instr* instr);
121 void DecodeType2(Instr* instr); 129 void DecodeType2(Instr* instr);
122 void DecodeType3(Instr* instr); 130 void DecodeType3(Instr* instr);
123 void DecodeType4(Instr* instr); 131 void DecodeType4(Instr* instr);
124 void DecodeType5(Instr* instr); 132 void DecodeType5(Instr* instr);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 shift_names[shift], shift_amount); 231 shift_names[shift], shift_amount);
224 } else { 232 } else {
225 // by register 233 // by register
226 int rs = instr->RsField(); 234 int rs = instr->RsField();
227 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 235 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
228 ", %s ", shift_names[shift]); 236 ", %s ", shift_names[shift]);
229 PrintRegister(rs); 237 PrintRegister(rs);
230 } 238 }
231 } 239 }
232 240
241 void Decoder::PrintShiftRm(const InstrThumb2& instr) {
242 int shift = instr.Type();
243 int shift_amount = instr.Imm();
244 int rm = instr.Rm();
245
246 PrintRegister(rm);
247
248 if (instr.Variant() != VARIANT_REGISTER_SHIFTED_REGISTER) {
249 if (shift == no_shift) {
250 // Special case for using rm only.
251 return;
252 }
253 if (shift == RRX) {
254 Print(", RRX");
255 return;
256 }
257 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
258 ", %s #%d",
259 shift_names[shift], shift_amount);
260 } else {
261 // TODO(haustein)
262 UNIMPLEMENTED();
263 }
264 }
265
266
233 267
234 // Print the immediate operand for the instruction. Generally used for data 268 // Print the immediate operand for the instruction. Generally used for data
235 // processing instructions. 269 // processing instructions.
236 void Decoder::PrintShiftImm(Instr* instr) { 270 void Decoder::PrintShiftImm(Instr* instr) {
237 int rotate = instr->RotateField() * 2; 271 int rotate = instr->RotateField() * 2;
238 int immed8 = instr->Immed8Field(); 272 int immed8 = instr->Immed8Field();
239 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); 273 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
240 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 274 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
241 "#%d", imm); 275 "#%d", imm);
242 } 276 }
243 277
278 void Decoder::PrintShiftImm(const InstrThumb2& instr) {
279 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
280 "#%d", instr.Imm());
281 }
282
244 283
245 // Print PU formatting to reduce complexity of FormatOption. 284 // Print PU formatting to reduce complexity of FormatOption.
246 void Decoder::PrintPU(Instr* instr) { 285 void Decoder::PrintPU(Instr* instr) {
247 switch (instr->PUField()) { 286 switch (instr->PUField()) {
248 case 0: { 287 case 0: {
249 Print("da"); 288 Print("da");
250 break; 289 break;
251 } 290 }
252 case 1: { 291 case 1: {
253 Print("ia"); 292 Print("ia");
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 reg++; 368 reg++;
330 rlist >>= 1; 369 rlist >>= 1;
331 } 370 }
332 Print("}"); 371 Print("}");
333 return 5; 372 return 5;
334 } 373 }
335 UNREACHABLE(); 374 UNREACHABLE();
336 return -1; 375 return -1;
337 } 376 }
338 377
378 int Decoder::FormatRegister(const InstrThumb2& instr, const char* format) {
379 ASSERT(format[0] == 'r');
380 if (format[1] == 'n') { // 'rn: Rn register
381 int reg = instr.Rn();
382 PrintRegister(reg);
383 return 2;
384 } else if (format[1] == 'd') { // 'rd: Rd register
385 int reg = instr.Rd();
386 PrintRegister(reg);
387 return 2;
388 } else if (format[1] == 's') { // 'rs: Rs register
389 int reg = instr.Rs();
390 PrintRegister(reg);
391 return 2;
392 } else if (format[1] == 'm') { // 'rm: Rm register
393 int reg = instr.Rm();
394 PrintRegister(reg);
395 return 2;
396 } else if (format[1] == 't') { // 'rt: Rt register
397 int reg = instr.Rt();
398 PrintRegister(reg);
399 return 2;
400 } else if (format[1] == 'l') {
401 // 'rlist: register list for load and store multiple instructions
402 ASSERT(STRING_STARTS_WITH(format, "rlist"));
403 // TODO(haustein)
404 UNIMPLEMENTED();
405 return 5;
406 }
407 UNREACHABLE();
408 return -1;
409 }
410
339 411
340 // Handle all VFP register based formatting in this function to reduce the 412 // Handle all VFP register based formatting in this function to reduce the
341 // complexity of FormatOption. 413 // complexity of FormatOption.
342 int Decoder::FormatVFPRegister(Instr* instr, const char* format) { 414 int Decoder::FormatVFPRegister(Instr* instr, const char* format) {
343 ASSERT((format[0] == 'S') || (format[0] == 'D')); 415 ASSERT((format[0] == 'S') || (format[0] == 'D'));
344 416
345 if (format[1] == 'n') { 417 if (format[1] == 'n') {
346 int reg = instr->VnField(); 418 int reg = instr->VnField();
347 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField())); 419 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField()));
348 if (format[0] == 'D') PrintDRegister(reg); 420 if (format[0] == 'D') PrintDRegister(reg);
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 } 611 }
540 default: { 612 default: {
541 UNREACHABLE(); 613 UNREACHABLE();
542 break; 614 break;
543 } 615 }
544 } 616 }
545 UNREACHABLE(); 617 UNREACHABLE();
546 return -1; 618 return -1;
547 } 619 }
548 620
621 int Decoder::FormatOption(const InstrThumb2& instr, const char* format) {
622 switch (format[0]) {
623 // TODO(haustein) Add code for a, b, c, h, l, m, o, p, see ARM
624 case 'r': {
625 return FormatRegister(instr, format);
626 }
627 case 's': {
628 if (format[1] == 'h') { // 'shift_op or 'shift_rm
629 if (format[6] == 'o') { // 'shift_op
630 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
631 if (instr.Type() == 0) {
632 PrintShiftRm(instr);
633 } else {
634 ASSERT(instr.Type() == 1);
635 PrintShiftImm(instr);
636 }
637 return 8;
638 } else { // 'shift_rm
639 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
640 PrintShiftRm(instr);
641 return 8;
642 }
643 // TODO(haustein) Add code for 'w', 'i', 's' here (see arm code)
644 }
645 // 's: S field of data processing instructions
646 if (instr.HasS()) {
647 Print("s");
648 }
649 return 1;
650 }
651 // TODO(haustein) Add code for 't', 'u', 'v', 'S', 'D', 'w' below,
652 // see arm code
653 default: {
654 UNIMPLEMENTED();
655 break;
656 }
657 }
658 UNREACHABLE();
659 return -1;
660 }
661
549 662
550 // Format takes a formatting string for a whole instruction and prints it into 663 // Format takes a formatting string for a whole instruction and prints it into
551 // the output buffer. All escaped options are handed to FormatOption to be 664 // the output buffer. All escaped options are handed to FormatOption to be
552 // parsed further. 665 // parsed further.
553 void Decoder::Format(Instr* instr, const char* format) { 666 void Decoder::Format(Instr* instr, const char* format) {
554 char cur = *format++; 667 char cur = *format++;
555 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 668 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
556 if (cur == '\'') { // Single quote is used as the formatting escape. 669 if (cur == '\'') { // Single quote is used as the formatting escape.
557 format += FormatOption(instr, format); 670 format += FormatOption(instr, format);
558 } else { 671 } else {
559 out_buffer_[out_buffer_pos_++] = cur; 672 out_buffer_[out_buffer_pos_++] = cur;
560 } 673 }
561 cur = *format++; 674 cur = *format++;
562 } 675 }
563 out_buffer_[out_buffer_pos_] = '\0'; 676 out_buffer_[out_buffer_pos_] = '\0';
564 } 677 }
565 678
566 679
680 void Decoder::Format(const InstrThumb2& instr, const char* format) {
681 char cur = *format++;
682 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
683 if (cur == '\'') { // Single quote is used as the formatting escape.
684 format += FormatOption(instr, format);
685 } else {
686 out_buffer_[out_buffer_pos_++] = cur;
687 }
688 cur = *format++;
689 }
690 out_buffer_[out_buffer_pos_] = '\0';
691 }
692
693
694
567 // For currently unimplemented decodings the disassembler calls Unknown(instr) 695 // For currently unimplemented decodings the disassembler calls Unknown(instr)
568 // which will just print "unknown" of the instruction bits. 696 // which will just print "unknown" of the instruction bits.
569 void Decoder::Unknown(Instr* instr) { 697 void Decoder::Unknown(Instr* instr) {
570 Format(instr, "unknown"); 698 Format(instr, "unknown");
571 } 699 }
572 700
573 701
574 void Decoder::DecodeType01(Instr* instr) { 702 void Decoder::DecodeType01(Instr* instr) {
575 int type = instr->TypeField(); 703 int type = instr->TypeField();
576 if ((type == 0) && instr->IsSpecialType0()) { 704 if ((type == 0) && instr->IsSpecialType0()) {
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 default: 1183 default:
1056 Unknown(instr); // Not used by V8. 1184 Unknown(instr); // Not used by V8.
1057 break; 1185 break;
1058 } 1186 }
1059 } 1187 }
1060 } 1188 }
1061 1189
1062 1190
1063 // Disassemble the instruction at *instr_ptr into the output buffer. 1191 // Disassemble the instruction at *instr_ptr into the output buffer.
1064 int Decoder::InstructionDecode(byte* instr_ptr) { 1192 int Decoder::InstructionDecode(byte* instr_ptr) {
1193 if (reinterpret_cast<int32_t>(instr_ptr) & 1) {
1194 InstrThumb2 instr(instr_ptr);
1195 return InstructionDecodeThumb2(instr);
1196 } else {
1197 return InstructionDecodeArm(instr_ptr);
1198 }
1199 }
1200
1201 int Decoder::InstructionDecodeArm(byte* instr_ptr) {
1065 Instr* instr = Instr::At(instr_ptr); 1202 Instr* instr = Instr::At(instr_ptr);
1066 // Print raw instruction bytes. 1203 // Print raw instruction bytes.
1067 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 1204 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
1068 "%08x ", 1205 "%08x ",
1069 instr->InstructionBits()); 1206 instr->InstructionBits());
1070 if (instr->ConditionField() == special_condition) { 1207 if (instr->ConditionField() == special_condition) {
1071 DecodeUnconditional(instr); 1208 DecodeUnconditional(instr);
1072 return Instr::kInstrSize; 1209 return Instr::kInstrSize;
1073 } 1210 }
1074 switch (instr->TypeField()) { 1211 switch (instr->TypeField()) {
(...skipping 29 matching lines...) Expand all
1104 default: { 1241 default: {
1105 // The type field is 3-bits in the ARM encoding. 1242 // The type field is 3-bits in the ARM encoding.
1106 UNREACHABLE(); 1243 UNREACHABLE();
1107 break; 1244 break;
1108 } 1245 }
1109 } 1246 }
1110 return Instr::kInstrSize; 1247 return Instr::kInstrSize;
1111 } 1248 }
1112 1249
1113 1250
1251 int Decoder::InstructionDecodeThumb2(const InstrThumb2& instr) {
1252 switch (instr.Op()) {
1253 case OP_ADD:
1254 Format(instr, "and's 'rd, 'rn, 'shift_op");
1255 break;
1256 case OP_AND:
1257 Format(instr, "and's 'rd, 'rn, 'shift_op");
1258 break;
1259 case OP_SUB:
1260 Format(instr, "sub's 'rd, 'rn, 'shift_op");
1261 break;
1262 default:
1263 UNIMPLEMENTED();
1264 break;
1265 }
1266 return instr.Size();
1267 }
1268
1269
1114 } } // namespace assembler::arm 1270 } } // namespace assembler::arm
1115 1271
1116 1272
1117 1273
1118 //------------------------------------------------------------------------------ 1274 //------------------------------------------------------------------------------
1119 1275
1120 namespace disasm { 1276 namespace disasm {
1121 1277
1122 namespace v8i = v8::internal; 1278 namespace v8i = v8::internal;
1123 1279
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1192 buffer[0] = '\0'; 1348 buffer[0] = '\0';
1193 byte* prev_pc = pc; 1349 byte* prev_pc = pc;
1194 pc += d.InstructionDecode(buffer, pc); 1350 pc += d.InstructionDecode(buffer, pc);
1195 fprintf(f, "%p %08x %s\n", 1351 fprintf(f, "%p %08x %s\n",
1196 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 1352 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1197 } 1353 }
1198 } 1354 }
1199 1355
1200 1356
1201 } // namespace disasm 1357 } // namespace disasm
OLDNEW
« no previous file with comments | « src/arm/constants-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698