Chromium Code Reviews| Index: runtime/vm/disassembler_arm.cc |
| =================================================================== |
| --- runtime/vm/disassembler_arm.cc (revision 19885) |
| +++ runtime/vm/disassembler_arm.cc (working copy) |
| @@ -22,7 +22,8 @@ |
| ~ARMDecoder() {} |
| // Writes one disassembled instruction into 'buffer' (0-terminated). |
| - void InstructionDecode(uword pc); |
| + // Returns true if the instruction was successfully decoded, false otherwise. |
| + bool InstructionDecode(uword pc); |
| private: |
| // Bottleneck functions to print into the out_buffer. |
| @@ -49,13 +50,13 @@ |
| // field in the instruction encoding. |
| // Types 0 and 1 are combined as they are largely the same except for the way |
| // they interpret the shifter operand. |
| - void DecodeType01(Instr* instr); |
| - void DecodeType2(Instr* instr); |
| - void DecodeType3(Instr* instr); |
| - void DecodeType4(Instr* instr); |
| - void DecodeType5(Instr* instr); |
| - void DecodeType6(Instr* instr); |
| - void DecodeType7(Instr* instr); |
| + bool DecodeType01(Instr* instr); |
| + bool DecodeType2(Instr* instr); |
| + bool DecodeType3(Instr* instr); |
| + bool DecodeType4(Instr* instr); |
| + bool DecodeType5(Instr* instr); |
| + bool DecodeType6(Instr* instr); |
| + bool DecodeType7(Instr* instr); |
| // Convenience functions. |
| char* get_buffer() const { return buffer_; } |
| @@ -575,7 +576,9 @@ |
| } |
| -void ARMDecoder::DecodeType01(Instr* instr) { |
| +bool ARMDecoder::DecodeType01(Instr* instr) { |
| + bool decoded = true; |
| + |
| if (!instr->IsDataProcessing()) { |
| // miscellaneous, multiply, sync primitives, extra loads and stores. |
| if (instr->IsMiscellaneous()) { |
| @@ -587,6 +590,7 @@ |
| Format(instr, "bx'cond 'rm"); |
| } else { |
| Unknown(instr); |
| + decoded = false; |
| } |
| break; |
| } |
| @@ -596,6 +600,7 @@ |
| } else { |
| // Could be inlined constant. |
| Unknown(instr); |
| + decoded = false; |
| } |
| break; |
| } |
| @@ -605,11 +610,13 @@ |
| } else { |
| // Format(instr, "smc'cond"); |
| Unknown(instr); // Not used. |
| + decoded = false; |
| } |
| break; |
| } |
| default: { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| break; |
| } |
| } |
| @@ -639,6 +646,7 @@ |
| } |
| default: { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| break; |
| } |
| } |
| @@ -655,6 +663,7 @@ |
| } |
| default: { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| break; |
| } |
| } |
| @@ -671,6 +680,7 @@ |
| Format(instr, "nop'cond"); |
| } else { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| } |
| break; |
| } |
| @@ -680,6 +690,7 @@ |
| } |
| default: { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| break; |
| } |
| } |
| @@ -764,6 +775,7 @@ |
| Format(instr, "tst'cond 'rn, 'shift_op"); |
| } else { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| } |
| break; |
| } |
| @@ -772,6 +784,7 @@ |
| Format(instr, "teq'cond 'rn, 'shift_op"); |
| } else { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| } |
| break; |
| } |
| @@ -780,6 +793,7 @@ |
| Format(instr, "cmp'cond 'rn, 'shift_op"); |
| } else { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| } |
| break; |
| } |
| @@ -788,6 +802,7 @@ |
| Format(instr, "cmn'cond 'rn, 'shift_op"); |
| } else { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| } |
| break; |
| } |
| @@ -814,14 +829,19 @@ |
| } |
| } |
| } |
| + |
| + return decoded; |
| } |
| -void ARMDecoder::DecodeType2(Instr* instr) { |
| +bool ARMDecoder::DecodeType2(Instr* instr) { |
| + bool decoded = true; |
| + |
| switch (instr->PUField()) { |
| case 0: { |
| if (instr->HasW()) { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| } else { |
| Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); |
| } |
| @@ -830,6 +850,7 @@ |
| case 1: { |
| if (instr->HasW()) { |
| Unknown(instr); // Not used. |
| + decoded = false; |
| } else { |
| Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); |
| } |
| @@ -849,22 +870,27 @@ |
| break; |
| } |
| } |
| + |
| + return decoded; |
| } |
| -void ARMDecoder::DecodeType3(Instr* instr) { |
| +bool ARMDecoder::DecodeType3(Instr* instr) { |
| + bool decoded = true; |
| + |
| if (instr->IsDivision()) { |
| if (instr->Bit(21)) { |
| Format(instr, "udiv'cond 'rd, 'rn, 'rm"); |
| } else { |
| Format(instr, "sdiv'cond 'rd, 'rn, 'rm"); |
| } |
| - return; |
| + return decoded; |
| } |
| switch (instr->PUField()) { |
| case 0: { |
| if (instr->HasW()) { |
| Unknown(instr); |
| + decoded = false; |
| } else { |
| Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); |
| } |
| @@ -873,6 +899,7 @@ |
| case 1: { |
| if (instr->HasW()) { |
| Unknown(instr); |
| + decoded = false; |
| } else { |
| Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); |
| } |
| @@ -892,26 +919,34 @@ |
| break; |
| } |
| } |
| + |
| + return decoded; |
| } |
| -void ARMDecoder::DecodeType4(Instr* instr) { |
| +bool ARMDecoder::DecodeType4(Instr* instr) { |
| + bool decoded = true; |
| if (instr->Bit(22) == 1) { |
| Unknown(instr); // Privileged mode currently not supported. |
| + decoded = false; |
| } else if (instr->HasL()) { |
| Format(instr, "ldm'cond'pu 'rn'w, 'rlist"); |
| } else { |
| Format(instr, "stm'cond'pu 'rn'w, 'rlist"); |
| } |
| + return decoded; |
| } |
| -void ARMDecoder::DecodeType5(Instr* instr) { |
| +bool ARMDecoder::DecodeType5(Instr* instr) { |
| Format(instr, "b'l'cond 'target ; 'dest"); |
| + return true; |
| } |
| -void ARMDecoder::DecodeType6(Instr* instr) { |
| +bool ARMDecoder::DecodeType6(Instr* instr) { |
| + bool decoded = true; |
| + |
| if (instr->IsVFPDoubleTransfer()) { |
| if (instr->Bit(8) == 0) { |
| if (instr->Bit(20) == 1) { |
| @@ -972,11 +1007,16 @@ |
| } |
| } else { |
| Unknown(instr); |
| + decoded = false; |
| } |
| + |
| + return decoded; |
| } |
| -void ARMDecoder::DecodeType7(Instr* instr) { |
| +bool ARMDecoder::DecodeType7(Instr* instr) { |
| + bool decoded = true; |
| + |
| if (instr->Bit(24) == 1) { |
| Format(instr, "svc'cond #'svc"); |
| if (instr->SvcField() == kStopMessageSvcCode) { |
| @@ -1010,6 +1050,7 @@ |
| case 1: // vnmla, vnmls, vnmul |
| default: { |
| Unknown(instr); |
| + decoded = false; |
| break; |
| } |
| case 2: { // vmul |
| @@ -1074,6 +1115,7 @@ |
| } |
| default: { |
| Unknown(instr); |
| + decoded = false; |
| break; |
| } |
| } |
| @@ -1099,6 +1141,7 @@ |
| } |
| default: { |
| Unknown(instr); |
| + decoded = false; |
| break; |
| } |
| } |
| @@ -1108,6 +1151,7 @@ |
| case 5: { // vcmp #0.0, vcmpe #0.0 |
| if (instr->Bit(7) == 1) { // vcmpe |
| Unknown(instr); |
| + decoded = false; |
| } else { |
| if (instr->Bit(8) == 0) { // vcmps |
| if (instr->Bit(16) == 0) { |
| @@ -1154,6 +1198,7 @@ |
| if (instr->Bit(7) == 0) { |
| // We only support round-to-zero mode |
| Unknown(instr); |
| + decoded = false; |
| break; |
| } |
| if (instr->Bit(8) == 0) { |
| @@ -1180,6 +1225,7 @@ |
| case 15: // vcvt between floating-point and fixed-point |
| default: { |
| Unknown(instr); |
| + decoded = false; |
| break; |
| } |
| } |
| @@ -1199,53 +1245,60 @@ |
| Format(instr, "vmstat'cond"); |
| } else { |
| Unknown(instr); |
| + decoded = false; |
| } |
| } |
| } else if (instr->IsMrcIdIsar0()) { |
| Format(instr, "mrc'cond p15, 0, 'rd, c0, c2, 0"); |
| } else { |
| Unknown(instr); |
| + decoded = false; |
| } |
| + |
| + return decoded; |
| } |
| -void ARMDecoder::InstructionDecode(uword pc) { |
| -Instr* instr = Instr::At(pc); |
| +bool ARMDecoder::InstructionDecode(uword pc) { |
| + bool decoded = true; |
| + Instr* instr = Instr::At(pc); |
| + |
| if (instr->ConditionField() == kSpecialCondition) { |
| if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) { |
| Format(instr, "clrex"); |
| } else { |
| Unknown(instr); |
| + decoded = false; |
| } |
| } else { |
| switch (instr->TypeField()) { |
| case 0: |
| case 1: { |
| - DecodeType01(instr); |
| + decoded = DecodeType01(instr); |
| break; |
| } |
| case 2: { |
| - DecodeType2(instr); |
| + decoded = DecodeType2(instr); |
| break; |
| } |
| case 3: { |
| - DecodeType3(instr); |
| + decoded = DecodeType3(instr); |
| break; |
| } |
| case 4: { |
| - DecodeType4(instr); |
| + decoded = DecodeType4(instr); |
| break; |
| } |
| case 5: { |
| - DecodeType5(instr); |
| + decoded = DecodeType5(instr); |
| break; |
| } |
| case 6: { |
| - DecodeType6(instr); |
| + decoded = DecodeType6(instr); |
| break; |
| } |
| case 7: { |
| - DecodeType7(instr); |
| + decoded = DecodeType7(instr); |
| break; |
| } |
| default: { |
| @@ -1255,6 +1308,8 @@ |
| } |
| } |
| } |
| + |
| + return decoded; |
| } |
| @@ -1262,18 +1317,22 @@ |
| char* human_buffer, intptr_t human_size, |
| uword pc) { |
| ARMDecoder decoder(human_buffer, human_size); |
| - decoder.InstructionDecode(pc); |
| - int32_t instruction_bits = Instr::At(pc)->InstructionBits(); |
| - OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits); |
| - return Instr::kInstrSize; |
| + if (decoder.InstructionDecode(pc)) { |
| + int32_t instruction_bits = Instr::At(pc)->InstructionBits(); |
| + OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits); |
| + return Instr::kInstrSize; |
| + } else { |
| + return -Instr::kInstrSize; |
|
regis
2013/03/12 20:53:19
Did you mean to return 0? I am worried about retur
|
| + } |
| } |
| -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; |
| @@ -1292,13 +1351,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); |
|
regis
2013/03/12 20:53:19
I see. You encode success/failure in the returned
|
| + } |
| } |
| + |
| + return success; |
| } |
| } // namespace dart |