| Index: runtime/vm/disassembler_mips.cc
|
| ===================================================================
|
| --- runtime/vm/disassembler_mips.cc (revision 19885)
|
| +++ runtime/vm/disassembler_mips.cc (working copy)
|
| @@ -22,7 +22,8 @@
|
| ~MIPSDecoder() {}
|
|
|
| // Writes one disassembled instruction into 'buffer' (0-terminated).
|
| - void InstructionDecode(Instr* instr);
|
| + // Returns true if the instruction was successfully decoded, false otherwise.
|
| + bool InstructionDecode(Instr* instr);
|
|
|
| private:
|
| // Bottleneck functions to print into the out_buffer.
|
| @@ -34,10 +35,10 @@
|
| int FormatRegister(Instr* instr, const char* format);
|
| int FormatOption(Instr* instr, const char* format);
|
| void Format(Instr* instr, const char* format);
|
| + void Unknown(Instr* instr);
|
|
|
| - void DecodeSpecial(Instr* instr);
|
| - void DecodeSpecial2(Instr* instr);
|
| - void DecodeSpecial3(Instr* instr);
|
| + bool DecodeSpecial(Instr* instr);
|
| + bool DecodeSpecial2(Instr* instr);
|
|
|
| // Convenience functions.
|
| char* get_buffer() const { return buffer_; }
|
| @@ -114,10 +115,25 @@
|
| // characters that were consumed from the formatting string.
|
| int MIPSDecoder::FormatOption(Instr* instr, const char* format) {
|
| switch (format[0]) {
|
| + case 'c': {
|
| + ASSERT(STRING_STARTS_WITH(format, "code"));
|
| + buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
| + remaining_size_in_buffer(),
|
| + "%d", instr->BreakCodeField());
|
| + return 4;
|
| + }
|
| case 'h': {
|
| ASSERT(STRING_STARTS_WITH(format, "hint"));
|
| - if (instr->SaField() != 0) {
|
| - UNIMPLEMENTED();
|
| + if (instr->SaField() == 0x10) {
|
| + // The high bit of the SA field is the only one that means something for
|
| + // JALR and JR. TODO(zra): Fill in the other cases for PREF if needed.
|
| + buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
| + remaining_size_in_buffer(),
|
| + ".hb");
|
| + } else if (instr->SaField() != 0) {
|
| + buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
| + remaining_size_in_buffer(),
|
| + ".unknown");
|
| }
|
| return 4;
|
| }
|
| @@ -176,7 +192,16 @@
|
| }
|
|
|
|
|
| -void MIPSDecoder::DecodeSpecial(Instr* instr) {
|
| +// For currently unimplemented decodings the disassembler calls Unknown(instr)
|
| +// which will just print "unknown" of the instruction bits.
|
| +void MIPSDecoder::Unknown(Instr* instr) {
|
| + Format(instr, "unknown");
|
| +}
|
| +
|
| +
|
| +bool MIPSDecoder::DecodeSpecial(Instr* instr) {
|
| + bool decoded = true;
|
| +
|
| ASSERT(instr->OpcodeField() == SPECIAL);
|
| switch (instr->FunctionField()) {
|
| case ADDU: {
|
| @@ -187,6 +212,10 @@
|
| Format(instr, "and 'rd, 'rs, 'rt");
|
| break;
|
| }
|
| + case BREAK: {
|
| + Format(instr, "break 'code");
|
| + break;
|
| + }
|
| case DIV: {
|
| Format(instr, "div 'rs, 'rt");
|
| break;
|
| @@ -214,21 +243,23 @@
|
| break;
|
| }
|
| case JR: {
|
| - ASSERT(instr->RtField() == R0);
|
| - ASSERT(instr->RdField() == R0);
|
| Format(instr, "jr'hint 'rs");
|
| break;
|
| }
|
| default: {
|
| - OS::PrintErr("DecodeSpecial: 0x%x\n", instr->InstructionBits());
|
| - UNREACHABLE();
|
| + Unknown(instr);
|
| + decoded = false;
|
| break;
|
| }
|
| }
|
| +
|
| + return decoded;
|
| }
|
|
|
|
|
| -void MIPSDecoder::DecodeSpecial2(Instr* instr) {
|
| +bool MIPSDecoder::DecodeSpecial2(Instr* instr) {
|
| + bool decoded = true;
|
| +
|
| ASSERT(instr->OpcodeField() == SPECIAL2);
|
| switch (instr->FunctionField()) {
|
| case CLO: {
|
| @@ -240,40 +271,28 @@
|
| break;
|
| }
|
| default: {
|
| - OS::PrintErr("DecodeSpecial2: 0x%x\n", instr->InstructionBits());
|
| - UNREACHABLE();
|
| + Unknown(instr);
|
| + decoded = false;
|
| break;
|
| }
|
| }
|
| +
|
| + return decoded;
|
| }
|
|
|
|
|
| -void MIPSDecoder::DecodeSpecial3(Instr* instr) {
|
| - ASSERT(instr->OpcodeField() == SPECIAL3);
|
| - switch (instr->FunctionField()) {
|
| - default: {
|
| - OS::PrintErr("DecodeSpecial3: 0x%x\n", instr->InstructionBits());
|
| - UNREACHABLE();
|
| - break;
|
| - }
|
| - }
|
| -}
|
| +bool MIPSDecoder::InstructionDecode(Instr* instr) {
|
| + bool decoded = true;
|
|
|
| -
|
| -void MIPSDecoder::InstructionDecode(Instr* instr) {
|
| switch (instr->OpcodeField()) {
|
| case SPECIAL: {
|
| - DecodeSpecial(instr);
|
| + decoded = DecodeSpecial(instr);
|
| break;
|
| }
|
| case SPECIAL2: {
|
| - DecodeSpecial2(instr);
|
| + decoded = DecodeSpecial2(instr);
|
| break;
|
| }
|
| - case SPECIAL3: {
|
| - DecodeSpecial3(instr);
|
| - break;
|
| - }
|
| case ADDIU: {
|
| Format(instr, "addiu 'rt, 'rs, 'imms");
|
| break;
|
| @@ -319,11 +338,13 @@
|
| break;
|
| }
|
| default: {
|
| - OS::PrintErr("Undecoded instruction: 0x%x\n", instr->InstructionBits());
|
| - UNREACHABLE();
|
| + Unknown(instr);
|
| + decoded = false;
|
| break;
|
| }
|
| }
|
| +
|
| + return decoded;
|
| }
|
|
|
|
|
| @@ -332,17 +353,21 @@
|
| uword pc) {
|
| MIPSDecoder decoder(human_buffer, human_size);
|
| Instr* instr = Instr::At(pc);
|
| - decoder.InstructionDecode(instr);
|
| - OS::SNPrint(hex_buffer, hex_size, "%08x", instr->InstructionBits());
|
| - return Instr::kInstrSize;
|
| + if (decoder.InstructionDecode(instr)) {
|
| + OS::SNPrint(hex_buffer, hex_size, "%08x", instr->InstructionBits());
|
| + return Instr::kInstrSize;
|
| + } else {
|
| + return -Instr::kInstrSize;
|
| + }
|
| }
|
|
|
|
|
| -void Disassembler::Disassemble(uword start,
|
| +bool Disassembler::Disassemble(uword start,
|
| uword end,
|
| DisassemblyFormatter* formatter,
|
| const Code::Comments& comments) {
|
| ASSERT(formatter != NULL);
|
| + bool success = true;
|
| char hex_buffer[kHexadecimalBufferSize]; // Instruction in hexadecimal form.
|
| char human_buffer[kUserReadableBufferSize]; // Human-readable instruction.
|
| uword pc = start;
|
| @@ -361,13 +386,21 @@
|
| human_buffer,
|
| sizeof(human_buffer),
|
| pc);
|
| - formatter->ConsumeInstruction(hex_buffer,
|
| - sizeof(hex_buffer),
|
| - human_buffer,
|
| - sizeof(human_buffer),
|
| - pc);
|
| - pc += instruction_length;
|
| + if (instruction_length > 0) {
|
| + formatter->ConsumeInstruction(hex_buffer,
|
| + sizeof(hex_buffer),
|
| + human_buffer,
|
| + sizeof(human_buffer),
|
| + pc);
|
| + pc += instruction_length;
|
| + } else {
|
| + ASSERT(instruction_length < 0);
|
| + success = false;
|
| + pc += (-instruction_length);
|
| + }
|
| }
|
| +
|
| + return success;
|
| }
|
|
|
| } // namespace dart
|
|
|