Index: runtime/vm/disassembler_arm64.cc |
=================================================================== |
--- runtime/vm/disassembler_arm64.cc (revision 35658) |
+++ runtime/vm/disassembler_arm64.cc (working copy) |
@@ -31,6 +31,7 @@ |
// Printing of common values. |
void PrintRegister(int reg, R31Type r31t); |
+ void PrintVRegister(int reg); |
void PrintShiftExtendRm(Instr* instr); |
void PrintMemOperand(Instr* instr); |
void PrintS(Instr* instr); |
@@ -38,6 +39,7 @@ |
// Handle formatting of instructions and their options. |
int FormatRegister(Instr* instr, const char* option); |
+ int FormatVRegister(Instr*instr, const char* option); |
int FormatOption(Instr* instr, const char* format); |
void Format(Instr* instr, const char* format); |
void Unknown(Instr* instr); |
@@ -103,6 +105,15 @@ |
} |
+void ARM64Decoder::PrintVRegister(int reg) { |
+ ASSERT(0 <= reg); |
+ ASSERT(reg < kNumberOfVRegisters); |
+ buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
+ remaining_size_in_buffer(), |
+ "v%d", reg); |
+} |
+ |
+ |
// These shift names are defined in a way to match the native disassembler |
// formatting. See for example the command "objdump -d <binary file>". |
static const char* shift_names[kMaxShift] = { |
@@ -291,6 +302,22 @@ |
} |
+int ARM64Decoder::FormatVRegister(Instr* instr, const char* format) { |
+ ASSERT(format[0] == 'v'); |
+ if (format[1] == 'd') { |
+ int reg = instr->VdField(); |
+ PrintVRegister(reg); |
+ return 2; |
+ } else if (format[1] == 'n') { |
+ int reg = instr->VnField(); |
+ PrintVRegister(reg); |
+ return 2; |
+ } |
+ UNREACHABLE(); |
+ return -1; |
+} |
+ |
+ |
// FormatOption takes a formatting string and interprets it based on |
// the current instructions. The format string points to the first |
// character of the option string (the option escape has already been |
@@ -363,30 +390,41 @@ |
} |
return 2; |
} |
- case 'i': { // 'imm12, imm16 |
- uint64_t imm; |
- int ret = 5; |
- if (format[4] == '2') { |
- ASSERT(STRING_STARTS_WITH(format, "imm12")); |
- imm = instr->Imm12Field(); |
- if (format[5] == 's') { |
- // shifted immediate. |
- if (instr->Imm12ShiftField() == 1) { |
- imm = imm << 12; |
- } else if ((instr->Imm12ShiftField() & 0x2) != 0) { |
- Print("Unknown Shift"); |
+ case 'i': { // 'imm12, 'imm16, 'immd |
+ if (format[3] == '1') { |
+ uint64_t imm; |
+ int ret = 5; |
+ if (format[4] == '2') { |
+ ASSERT(STRING_STARTS_WITH(format, "imm12")); |
+ imm = instr->Imm12Field(); |
+ if (format[5] == 's') { |
+ // shifted immediate. |
+ if (instr->Imm12ShiftField() == 1) { |
+ imm = imm << 12; |
+ } else if ((instr->Imm12ShiftField() & 0x2) != 0) { |
+ Print("Unknown Shift"); |
+ } |
+ ret = 6; |
} |
- ret = 6; |
+ } else { |
+ ASSERT(STRING_STARTS_WITH(format, "imm16")); |
+ imm = instr->Imm16Field(); |
} |
+ buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
+ remaining_size_in_buffer(), |
+ "0x%"Px64, |
+ imm); |
+ return ret; |
} else { |
- ASSERT(STRING_STARTS_WITH(format, "imm16")); |
- imm = instr->Imm16Field(); |
+ ASSERT(STRING_STARTS_WITH(format, "immd")); |
+ double dimm = bit_cast<double, int64_t>( |
+ Instr::VFPExpandImm(instr->Imm8Field())); |
+ buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
+ remaining_size_in_buffer(), |
+ "%f", |
+ dimm); |
+ return 4; |
} |
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
- remaining_size_in_buffer(), |
- "0x%"Px64, |
- imm); |
- return ret; |
} |
case 'm': { |
ASSERT(STRING_STARTS_WITH(format, "memop")); |
@@ -420,6 +458,9 @@ |
case 'r': { |
return FormatRegister(instr, format); |
} |
+ case 'v': { |
+ return FormatVRegister(instr, format); |
+ } |
case 's': { // 's: S flag. |
if (format[1] == 'h') { |
ASSERT(STRING_STARTS_WITH(format, "shift_op")); |
@@ -879,8 +920,55 @@ |
} |
+void ARM64Decoder::DecodeFPImm(Instr* instr) { |
+ if ((instr->Bit(31) != 0) || (instr->Bit(29) != 0) || (instr->Bit(23) != 0) || |
+ (instr->Bits(5, 5) != 0)) { |
+ Unknown(instr); |
+ return; |
+ } |
+ if (instr->Bit(22) == 1) { |
+ // Double. |
+ Format(instr, "fmovd 'vd, 'immd"); |
+ } else { |
+ // Single. |
+ Unknown(instr); |
+ } |
+} |
+ |
+ |
+void ARM64Decoder::DecodeFPIntCvt(Instr* instr) { |
+ if ((instr->SFField() != 1) || (instr->Bit(29) != 0) || |
+ (instr->Bits(22, 2) != 1)) { |
+ Unknown(instr); |
+ return; |
+ } |
+ if (instr->Bits(16, 3) == 6) { |
+ Format(instr, "fmovrd 'rd, 'vn"); |
+ } else if (instr->Bits(16, 3) == 7) { |
+ Format(instr, "fmovdr 'vd, 'rn"); |
+ } else { |
+ Unknown(instr); |
+ } |
+} |
+ |
+ |
+void ARM64Decoder::DecodeFP(Instr* instr) { |
+ if (instr->IsFPImmOp()) { |
+ DecodeFPImm(instr); |
+ } else if (instr->IsFPIntCvtOp()) { |
+ DecodeFPIntCvt(instr); |
+ } else { |
+ Unknown(instr); |
+ } |
+} |
+ |
+ |
void ARM64Decoder::DecodeDPSimd2(Instr* instr) { |
- Unknown(instr); |
+ if (instr->IsFPOp()) { |
+ DecodeFP(instr); |
+ } else { |
+ Unknown(instr); |
+ } |
} |