Index: src/arm/disasm-arm.cc |
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc |
index 6101bec947f65343e4ca4faeda262c530ed8d8f9..c58040fe8cdf15115996371b2aabf157376757d7 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); |
+ } |
+ 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)); |