Chromium Code Reviews| Index: src/arm/disasm-arm.cc |
| diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc |
| index f55552df5b321fc3c3b5a955984ca8a163c744a8..4bb646f5962434da2b780f3987c4abd5a3771548 100644 |
| --- a/src/arm/disasm-arm.cc |
| +++ b/src/arm/disasm-arm.cc |
| @@ -113,6 +113,8 @@ class Decoder { |
| // Handle formatting of instructions and their options. |
| int FormatRegister(Instruction* instr, const char* option); |
| + void FormatNeonList(int Vd, int type); |
| + void FormatNeonMemory(int Rn, int align, int Rm); |
| int FormatOption(Instruction* instr, const char* option); |
| void Format(Instruction* instr, const char* format); |
| void Unknown(Instruction* instr); |
| @@ -133,6 +135,8 @@ class Decoder { |
| void DecodeTypeVFP(Instruction* instr); |
| void DecodeType6CoprocessorIns(Instruction* instr); |
| + void DecodeSpecialCondition(Instruction* instr); |
| + |
| void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr); |
| void DecodeVCMP(Instruction* instr); |
| void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr); |
| @@ -417,6 +421,41 @@ int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) { |
| } |
| +void Decoder::FormatNeonList(int Vd, int type) { |
| + if (type == nlt_1) { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "{d%d}", Vd); |
| + } else if (type == nlt_2) { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "{d%d, d%d}", Vd, Vd + 1); |
| + } else if (type == nlt_3) { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2); |
| + } else if (type == nlt_4) { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3); |
| + } |
| +} |
| + |
| + |
| +void Decoder::FormatNeonMemory(int Rn, int align, int Rm) { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "[r%d", Rn); |
| + if (align != 0) { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + ":%d", (1<<align)<<6); |
|
ulan
2013/06/28 15:07:43
Spaces around "<<".
Rodolph Perfetta
2013/07/03 16:59:39
Done.
vincent.belliard.fr
2013/07/10 15:30:37
Done.
|
| + } |
| + if (Rm == 15) { |
| + Print("]"); |
| + } else if (Rm == 13) { |
| + Print("]!"); |
| + } else { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "], r%d", Rm); |
| + } |
| +} |
| + |
| + |
| // Print the movw or movt instruction. |
| void Decoder::PrintMovwMovt(Instruction* instr) { |
| int imm = instr->ImmedMovwMovtValue(); |
| @@ -980,15 +1019,107 @@ void Decoder::DecodeType3(Instruction* instr) { |
| break; |
| } |
| case ia_x: { |
| - if (instr->HasW()) { |
| - VERIFY(instr->Bits(5, 4) == 0x1); |
| - if (instr->Bit(22) == 0x1) { |
| - Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); |
| + if (instr->Bit(4) == 0) { |
| + Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); |
| + } else { |
| + if (instr->Bit(5) == 0) { |
| + switch (instr->Bits(22, 21)) { |
| + case 0: |
| + if (instr->Bit(20) == 0) { |
| + if (instr->Bit(6) == 0) { |
| + Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07"); |
| + } else { |
| + if (instr->Bits(11, 7) == 0) { |
| + Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32"); |
| + } else { |
| + Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07"); |
| + } |
| + } |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + break; |
| + case 1: |
| + UNREACHABLE(); |
| + break; |
| + case 2: |
| + UNREACHABLE(); |
| + break; |
| + case 3: |
| + Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); |
| + break; |
| + } |
| } else { |
| - UNREACHABLE(); // SSAT. |
| + switch (instr->Bits(22, 21)) { |
| + case 0: |
| + UNREACHABLE(); |
| + break; |
| + case 1: |
| + UNREACHABLE(); |
| + break; |
| + case 2: |
| + if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { |
| + if (instr->Bits(19, 16) == 0xF) { |
| + switch (instr->Bits(11, 10)) { |
| + case 0: |
| + Format(instr, "uxtb16'cond 'rd, 'rm, ror #0"); |
| + break; |
| + case 1: |
| + Format(instr, "uxtb16'cond 'rd, 'rm, ror #8"); |
| + break; |
| + case 2: |
| + Format(instr, "uxtb16'cond 'rd, 'rm, ror #16"); |
| + break; |
| + case 3: |
| + Format(instr, "uxtb16'cond 'rd, 'rm, ror #24"); |
| + break; |
| + } |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + break; |
| + case 3: |
| + if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) { |
| + if (instr->Bits(19, 16) == 0xF) { |
| + switch (instr->Bits(11, 10)) { |
| + case 0: |
| + Format(instr, "uxtb'cond 'rd, 'rm, ror #0"); |
| + break; |
| + case 1: |
| + Format(instr, "uxtb'cond 'rd, 'rm, ror #8"); |
| + break; |
| + case 2: |
| + Format(instr, "uxtb'cond 'rd, 'rm, ror #16"); |
| + break; |
| + case 3: |
| + Format(instr, "uxtb'cond 'rd, 'rm, ror #24"); |
| + break; |
| + } |
| + } else { |
| + switch (instr->Bits(11, 10)) { |
| + case 0: |
| + Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #0"); |
| + break; |
| + case 1: |
| + Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8"); |
| + break; |
| + case 2: |
| + Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16"); |
| + break; |
| + case 3: |
| + Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24"); |
| + break; |
| + } |
| + } |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + break; |
| + } |
| } |
| - } else { |
| - Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm"); |
| } |
| break; |
| } |
| @@ -1421,6 +1552,90 @@ void Decoder::DecodeType6CoprocessorIns(Instruction* instr) { |
| } |
| } |
| +void Decoder::DecodeSpecialCondition(Instruction* instr) { |
| + switch (instr->SpecialValue()) { |
| + case 5: |
| + if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && |
| + (instr->Bit(4) == 1)) { |
| + // vmovl signed |
| + int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| + int Vm = (instr->Bit(5) << 4) | instr->VmValue(); |
| + int imm3 = instr->Bits(21, 19); |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm); |
| + } else { |
| + Unknown(instr); |
| + } |
| + break; |
| + case 7: |
| + if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && |
| + (instr->Bit(4) == 1)) { |
| + // vmovl unsigned |
| + int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| + int Vm = (instr->Bit(5) << 4) | instr->VmValue(); |
| + int imm3 = instr->Bits(21, 19); |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm); |
| + } else { |
| + Unknown(instr); |
| + } |
| + break; |
| + case 8: |
| + if (instr->Bits(21, 20) == 0) { |
| + // vst1 |
| + int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| + int Rn = instr->VnValue(); |
| + int type = instr->Bits(11, 8); |
| + int size = instr->Bits(7, 6); |
| + int align = instr->Bits(5, 4); |
| + int Rm = instr->VmValue(); |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "vst1.%d ", (1 << size) << 3); |
| + FormatNeonList(Vd, type); |
| + Print(", "); |
| + FormatNeonMemory(Rn, align, Rm); |
| + } else if (instr->Bits(21, 20) == 2) { |
| + // vld1 |
| + int Vd = (instr->Bit(22) << 4) | instr->VdValue(); |
| + int Rn = instr->VnValue(); |
| + int type = instr->Bits(11, 8); |
| + int size = instr->Bits(7, 6); |
| + int align = instr->Bits(5, 4); |
| + int Rm = instr->VmValue(); |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "vld1.%d ", (1 << size) << 3); |
| + FormatNeonList(Vd, type); |
| + Print(", "); |
| + FormatNeonMemory(Rn, align, Rm); |
| + } else { |
| + Unknown(instr); |
| + } |
| + break; |
| + case 0xA: |
| + case 0xB: |
| + if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) { |
| + int Rn = instr->Bits(19, 16); |
| + int offset = instr->Bits(11, 0); |
| + if (offset == 0) { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "pld [r%d]", Rn); |
| + } else if (instr->Bit(23) == 0) { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "pld [r%d, #-%d]", Rn, offset); |
| + } else { |
| + out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| + "pld [r%d, #+%d]", Rn, offset); |
| + } |
| + } else { |
| + Unknown(instr); |
| + } |
| + break; |
| + default: |
| + Unknown(instr); |
| + break; |
| + } |
| +} |
| + |
| #undef VERIFIY |
| bool Decoder::IsConstantPoolAt(byte* instr_ptr) { |
| @@ -1447,7 +1662,7 @@ int Decoder::InstructionDecode(byte* instr_ptr) { |
| "%08x ", |
| instr->InstructionBits()); |
| if (instr->ConditionField() == kSpecialCondition) { |
| - Unknown(instr); |
| + DecodeSpecialCondition(instr); |
| return Instruction::kInstrSize; |
| } |
| int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); |