Index: src/arm/disasm-arm.cc |
=================================================================== |
--- src/arm/disasm-arm.cc (revision 4136) |
+++ src/arm/disasm-arm.cc (working copy) |
@@ -129,6 +129,10 @@ |
void DecodeTypeVFP(Instr* instr); |
void DecodeType6CoprocessorIns(Instr* instr); |
+ void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr); |
+ void DecodeVCMP(Instr* instr); |
+ void DecodeVCVTBetweenDoubleAndSingle(Instr* instr); |
+ void DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr); |
const disasm::NameConverter& converter_; |
v8::internal::Vector<char> out_buffer_; |
@@ -181,12 +185,12 @@ |
// Print the VFP S register name according to the active name converter. |
void Decoder::PrintSRegister(int reg) { |
- Print(assembler::arm::VFPRegisters::Name(reg)); |
+ Print(assembler::arm::VFPRegisters::Name(reg, false)); |
} |
// Print the VFP D register name according to the active name converter. |
void Decoder::PrintDRegister(int reg) { |
- Print(assembler::arm::VFPRegisters::Name(reg + 32)); |
+ Print(assembler::arm::VFPRegisters::Name(reg, true)); |
} |
@@ -930,88 +934,152 @@ |
// VMRS |
void Decoder::DecodeTypeVFP(Instr* instr) { |
ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); |
+ ASSERT(instr->Bits(11, 9) == 0x5); |
- if (instr->Bit(23) == 1) { |
- if ((instr->Bits(21, 19) == 0x7) && |
- (instr->Bits(18, 16) == 0x5) && |
- (instr->Bits(11, 9) == 0x5) && |
- (instr->Bit(8) == 1) && |
- (instr->Bit(6) == 1) && |
- (instr->Bit(4) == 0)) { |
- Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm"); |
- } else if ((instr->Bits(21, 19) == 0x7) && |
- (instr->Bits(18, 16) == 0x0) && |
- (instr->Bits(11, 9) == 0x5) && |
- (instr->Bit(8) == 1) && |
- (instr->Bit(7) == 1) && |
- (instr->Bit(6) == 1) && |
- (instr->Bit(4) == 0)) { |
- Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm"); |
- } else if ((instr->Bit(21) == 0x0) && |
- (instr->Bit(20) == 0x0) && |
- (instr->Bits(11, 9) == 0x5) && |
- (instr->Bit(8) == 1) && |
- (instr->Bit(6) == 0) && |
- (instr->Bit(4) == 0)) { |
+ if (instr->Bit(4) == 0) { |
+ if (instr->Opc1Field() == 0x7) { |
+ // Other data processing instructions |
+ if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) { |
+ DecodeVCVTBetweenDoubleAndSingle(instr); |
+ } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) { |
+ DecodeVCVTBetweenFloatingPointAndInteger(instr); |
+ } else if (((instr->Opc2Field() >> 1) == 0x6) && |
+ (instr->Opc3Field() & 0x1)) { |
+ DecodeVCVTBetweenFloatingPointAndInteger(instr); |
+ } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && |
+ (instr->Opc3Field() & 0x1)) { |
+ DecodeVCMP(instr); |
+ } else { |
+ Unknown(instr); // Not used by V8. |
+ } |
+ } else if (instr->Opc1Field() == 0x3) { |
+ if (instr->SzField() == 0x1) { |
+ if (instr->Opc3Field() & 0x1) { |
+ Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm"); |
+ } else { |
+ Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm"); |
+ } |
+ } else { |
+ Unknown(instr); // Not used by V8. |
+ } |
+ } else if ((instr->Opc1Field() == 0x2) && !(instr->Opc3Field() & 0x1)) { |
+ if (instr->SzField() == 0x1) { |
+ Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm"); |
+ } else { |
+ Unknown(instr); // Not used by V8. |
+ } |
+ } else if ((instr->Opc1Field() == 0x4) && !(instr->Opc3Field() & 0x1)) { |
+ if (instr->SzField() == 0x1) { |
Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm"); |
- } else if ((instr->Bits(21, 20) == 0x3) && |
- (instr->Bits(19, 16) == 0x4) && |
- (instr->Bits(11, 9) == 0x5) && |
- (instr->Bit(8) == 0x1) && |
- (instr->Bit(6) == 0x1) && |
- (instr->Bit(4) == 0x0)) { |
- Format(instr, "vcmp.f64'cond 'Dd, 'Dm"); |
- } else if ((instr->Bits(23, 20) == 0xF) && |
- (instr->Bits(19, 16) == 0x1) && |
- (instr->Bits(11, 8) == 0xA) && |
- (instr->Bits(7, 5) == 0x0) && |
- (instr->Bit(4) == 0x1) && |
- (instr->Bits(3, 0) == 0x0)) { |
- if (instr->Bits(15, 12) == 0xF) |
- Format(instr, "vmrs'cond APSR, FPSCR"); |
- else |
- Unknown(instr); // Not used by V8. |
+ } else { |
+ Unknown(instr); // Not used by V8. |
+ } |
} else { |
Unknown(instr); // Not used by V8. |
} |
- } else if (instr->Bit(21) == 1) { |
- if ((instr->Bit(20) == 0x1) && |
- (instr->Bits(11, 9) == 0x5) && |
- (instr->Bit(8) == 0x1) && |
- (instr->Bit(6) == 0) && |
- (instr->Bit(4) == 0)) { |
- Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm"); |
- } else if ((instr->Bit(20) == 0x1) && |
- (instr->Bits(11, 9) == 0x5) && |
- (instr->Bit(8) == 0x1) && |
- (instr->Bit(6) == 1) && |
- (instr->Bit(4) == 0)) { |
- Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm"); |
- } else if ((instr->Bit(20) == 0x0) && |
- (instr->Bits(11, 9) == 0x5) && |
- (instr->Bit(8) == 0x1) && |
- (instr->Bit(6) == 0) && |
- (instr->Bit(4) == 0)) { |
- Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm"); |
+ } else { |
+ if ((instr->VCField() == 0x0) && |
+ (instr->VAField() == 0x0)) { |
+ DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
+ } else if ((instr->VLField() == 0x1) && |
+ (instr->VCField() == 0x0) && |
+ (instr->VAField() == 0x7) && |
+ (instr->Bits(19, 16) == 0x1)) { |
+ if (instr->Bits(15, 12) == 0xF) |
+ Format(instr, "vmrs'cond APSR, FPSCR"); |
+ else |
+ Unknown(instr); // Not used by V8. |
} else { |
Unknown(instr); // Not used by V8. |
} |
+ } |
+} |
+ |
+ |
+void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) { |
+ ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) && |
+ (instr->VAField() == 0x0)); |
+ |
+ bool to_arm_register = (instr->VLField() == 0x1); |
+ |
+ if (to_arm_register) { |
+ Format(instr, "vmov'cond 'rt, 'Sn"); |
} else { |
- if ((instr->Bit(20) == 0x0) && |
- (instr->Bits(11, 8) == 0xA) && |
- (instr->Bits(6, 5) == 0x0) && |
- (instr->Bit(4) == 1) && |
- (instr->Bits(3, 0) == 0x0)) { |
- Format(instr, "vmov'cond 'Sn, 'rt"); |
- } else if ((instr->Bit(20) == 0x1) && |
- (instr->Bits(11, 8) == 0xA) && |
- (instr->Bits(6, 5) == 0x0) && |
- (instr->Bit(4) == 1) && |
- (instr->Bits(3, 0) == 0x0)) { |
- Format(instr, "vmov'cond 'rt, 'Sn"); |
+ Format(instr, "vmov'cond 'Sn, 'rt"); |
+ } |
+} |
+ |
+ |
+void Decoder::DecodeVCMP(Instr* instr) { |
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
+ ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && |
+ (instr->Opc3Field() & 0x1)); |
+ |
+ // Comparison. |
+ bool dp_operation = (instr->SzField() == 1); |
+ bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); |
+ |
+ if (dp_operation && !raise_exception_for_qnan) { |
+ Format(instr, "vcmp.f64'cond 'Dd, 'Dm"); |
+ } else { |
+ Unknown(instr); // Not used by V8. |
+ } |
+} |
+ |
+ |
+void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) { |
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
+ ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)); |
+ |
+ bool double_to_single = (instr->SzField() == 1); |
+ |
+ if (double_to_single) { |
+ Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm"); |
+ } else { |
+ Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm"); |
+ } |
+} |
+ |
+ |
+void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) { |
+ ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
+ ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) || |
+ (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1))); |
+ |
+ bool to_integer = (instr->Bit(18) == 1); |
+ bool dp_operation = (instr->SzField() == 1); |
+ if (to_integer) { |
+ bool unsigned_integer = (instr->Bit(16) == 0); |
+ |
+ if (dp_operation) { |
+ if (unsigned_integer) { |
+ Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm"); |
+ } else { |
+ Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm"); |
+ } |
} else { |
- Unknown(instr); // Not used by V8. |
+ if (unsigned_integer) { |
+ Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm"); |
+ } else { |
+ Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm"); |
+ } |
} |
+ } else { |
+ bool unsigned_integer = (instr->Bit(7) == 0); |
+ |
+ if (dp_operation) { |
+ if (unsigned_integer) { |
+ Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm"); |
+ } else { |
+ Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm"); |
+ } |
+ } else { |
+ if (unsigned_integer) { |
+ Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm"); |
+ } else { |
+ Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm"); |
+ } |
+ } |
} |
} |
@@ -1024,10 +1092,28 @@ |
void Decoder::DecodeType6CoprocessorIns(Instr* instr) { |
ASSERT((instr->TypeField() == 6)); |
- if (instr->CoprocessorField() != 0xB) { |
- Unknown(instr); // Not used by V8. |
- } else { |
+ if (instr->CoprocessorField() == 0xA) { |
switch (instr->OpcodeField()) { |
+ case 0x8: |
+ if (instr->HasL()) { |
+ Format(instr, "vldr'cond 'Sd, ['rn - 4*'off8]"); |
+ } else { |
+ Format(instr, "vstr'cond 'Sd, ['rn - 4*'off8]"); |
+ } |
+ break; |
+ case 0xC: |
+ if (instr->HasL()) { |
+ Format(instr, "vldr'cond 'Sd, ['rn + 4*'off8]"); |
+ } else { |
+ Format(instr, "vstr'cond 'Sd, ['rn + 4*'off8]"); |
+ } |
+ break; |
+ default: |
+ Unknown(instr); // Not used by V8. |
+ break; |
+ } |
+ } else if (instr->CoprocessorField() == 0xB) { |
+ switch (instr->OpcodeField()) { |
case 0x2: |
// Load and store double to two GP registers |
if (instr->Bits(7, 4) != 0x1) { |
@@ -1056,6 +1142,8 @@ |
Unknown(instr); // Not used by V8. |
break; |
} |
+ } else { |
+ UNIMPLEMENTED(); // Not used by V8. |
} |
} |