| Index: src/arm/disasm-arm.cc
|
| diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
|
| index abb13dd9f0d502de7a18b01af53913521d7ba498..7a42386d74aabd344294ac0d5fc731776cd7f24d 100644
|
| --- a/src/arm/disasm-arm.cc
|
| +++ b/src/arm/disasm-arm.cc
|
| @@ -1419,6 +1419,9 @@ int Decoder::DecodeType7(Instruction* instr) {
|
| // Sd = vsqrt(Sm)
|
| // vmrs
|
| // vmsr
|
| +// Qd = vdup.size(Qd, Rt)
|
| +// vmov.size: Dd[i] = Rt
|
| +// vmov.sign.size: Rt = Dn[i]
|
| void Decoder::DecodeTypeVFP(Instruction* instr) {
|
| VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
|
| VERIFY(instr->Bits(11, 9) == 0x5);
|
| @@ -1531,21 +1534,71 @@ void Decoder::DecodeTypeVFP(Instruction* instr) {
|
| if ((instr->VCValue() == 0x0) &&
|
| (instr->VAValue() == 0x0)) {
|
| DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
|
| - } else if ((instr->VLValue() == 0x0) &&
|
| - (instr->VCValue() == 0x1) &&
|
| - (instr->Bit(23) == 0x0)) {
|
| - if (instr->Bit(21) == 0x0) {
|
| - Format(instr, "vmov'cond.32 'Dd[0], 'rt");
|
| + } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
|
| + if (instr->Bit(23) == 0) {
|
| + int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
|
| + if ((opc1_opc2 & 0xb) == 0) {
|
| + // NeonS32/NeonU32
|
| + if (instr->Bit(21) == 0x0) {
|
| + Format(instr, "vmov'cond.32 'Dd[0], 'rt");
|
| + } else {
|
| + Format(instr, "vmov'cond.32 'Dd[1], 'rt");
|
| + }
|
| + } else {
|
| + int vd = instr->VFPNRegValue(kDoublePrecision);
|
| + int rt = instr->RtValue();
|
| + if ((opc1_opc2 & 0x8) != 0) {
|
| + // NeonS8 / NeonU8
|
| + int i = opc1_opc2 & 0x7;
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "vmov.8 d%d[%d], r%d", vd, i, rt);
|
| + } else if ((opc1_opc2 & 0x1) != 0) {
|
| + // NeonS16 / NeonU16
|
| + int i = (opc1_opc2 >> 1) & 0x3;
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "vmov.16 d%d[%d], r%d", vd, i, rt);
|
| + } else {
|
| + Unknown(instr);
|
| + }
|
| + }
|
| } else {
|
| - Format(instr, "vmov'cond.32 'Dd[1], 'rt");
|
| - }
|
| - } else if ((instr->VLValue() == 0x1) &&
|
| - (instr->VCValue() == 0x1) &&
|
| - (instr->Bit(23) == 0x0)) {
|
| - if (instr->Bit(21) == 0x0) {
|
| - Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
|
| + int size = 32;
|
| + if (instr->Bit(5) != 0)
|
| + size = 16;
|
| + else if (instr->Bit(22) != 0)
|
| + size = 8;
|
| + int Vd = instr->VFPNRegValue(kSimd128Precision);
|
| + int Rt = instr->RtValue();
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "vdup.%i q%d, r%d", size, Vd, Rt);
|
| + }
|
| + } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
|
| + int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
|
| + if ((opc1_opc2 & 0xb) == 0) {
|
| + // NeonS32 / NeonU32
|
| + if (instr->Bit(21) == 0x0) {
|
| + Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
|
| + } else {
|
| + Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
|
| + }
|
| } else {
|
| - Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
|
| + const char* sign = instr->Bit(23) != 0 ? "u" : "s";
|
| + int rt = instr->RtValue();
|
| + int vn = instr->VFPNRegValue(kDoublePrecision);
|
| + if ((opc1_opc2 & 0x8) != 0) {
|
| + // NeonS8 / NeonU8
|
| + int i = opc1_opc2 & 0x7;
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "vmov.%s8 r%d, d%d[%d]", sign, rt, vn, i);
|
| + } else if ((opc1_opc2 & 0x1) != 0) {
|
| + // NeonS16 / NeonU16
|
| + int i = (opc1_opc2 >> 1) & 0x3;
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "vmov.%s16 r%d, d%d[%d]",
|
| + sign, rt, vn, i);
|
| + } else {
|
| + Unknown(instr);
|
| + }
|
| }
|
| } else if ((instr->VCValue() == 0x0) &&
|
| (instr->VAValue() == 0x7) &&
|
| @@ -1563,6 +1616,8 @@ void Decoder::DecodeTypeVFP(Instruction* instr) {
|
| Format(instr, "vmrs'cond 'rt, FPSCR");
|
| }
|
| }
|
| + } else {
|
| + Unknown(instr); // Not used by V8.
|
| }
|
| }
|
| }
|
| @@ -1809,6 +1864,25 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
|
| int Vm = instr->VFPMRegValue(kSimd128Precision);
|
| out_buffer_pos_ +=
|
| SNPrintF(out_buffer_ + out_buffer_pos_, "vmov q%d, q%d", Vd, Vm);
|
| + } else if (instr->Bits(11, 8) == 8) {
|
| + const char* op = (instr->Bit(4) == 0) ? "vadd" : "vtst";
|
| + int size = kBitsPerByte * (1 << instr->Bits(21, 20));
|
| + int Vd = instr->VFPDRegValue(kSimd128Precision);
|
| + int Vm = instr->VFPMRegValue(kSimd128Precision);
|
| + int Vn = instr->VFPNRegValue(kSimd128Precision);
|
| + // vadd/vtst.i<size> Qd, Qm, Qn.
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "%s.i%d q%d, q%d, q%d", op,
|
| + size, Vd, Vn, Vm);
|
| + } else if (instr->Bits(11, 8) == 0xd && instr->Bit(4) == 0) {
|
| + const char* op = (instr->Bits(21, 20) == 0) ? "vadd" : "vsub";
|
| + int size = kBitsPerByte * (1 << instr->Bits(21, 20));
|
| + int Vd = instr->VFPDRegValue(kSimd128Precision);
|
| + int Vm = instr->VFPMRegValue(kSimd128Precision);
|
| + int Vn = instr->VFPNRegValue(kSimd128Precision);
|
| + // vadd/vsub.f32 Qd, Qm, Qn.
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm);
|
| } else {
|
| Unknown(instr);
|
| }
|
| @@ -1828,8 +1902,29 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
|
| }
|
| break;
|
| case 6:
|
| - if (instr->Bits(21, 20) == 0 && instr->Bits(11, 8) == 1 &&
|
| - instr->Bit(4) == 1) {
|
| + if (instr->Bits(11, 8) == 8) {
|
| + int size = kBitsPerByte * (1 << instr->Bits(21, 20));
|
| + int Vd = instr->VFPDRegValue(kSimd128Precision);
|
| + int Vm = instr->VFPMRegValue(kSimd128Precision);
|
| + int Vn = instr->VFPNRegValue(kSimd128Precision);
|
| + if (instr->Bit(4) == 0) {
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "vsub.i%d q%d, q%d, q%d",
|
| + size, Vd, Vn, Vm);
|
| + } else {
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "vceq.i%d q%d, q%d, q%d",
|
| + size, Vd, Vn, Vm);
|
| + }
|
| + } else if (instr->Bits(21, 20) == 1 && instr->Bits(11, 8) == 1 &&
|
| + instr->Bit(4) == 1) {
|
| + int Vd = instr->VFPDRegValue(kSimd128Precision);
|
| + int Vm = instr->VFPMRegValue(kSimd128Precision);
|
| + int Vn = instr->VFPNRegValue(kSimd128Precision);
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "vbsl q%d, q%d, q%d", Vd, Vn, Vm);
|
| + } else if (instr->Bits(21, 20) == 0 && instr->Bits(11, 8) == 1 &&
|
| + instr->Bit(4) == 1) {
|
| if (instr->Bit(6) == 0) {
|
| // veor Dd, Dn, Dm
|
| int Vd = instr->VFPDRegValue(kDoublePrecision);
|
| @@ -1860,6 +1955,35 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
|
| int imm3 = instr->Bits(21, 19);
|
| out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm);
|
| + } else if (instr->Opc1Value() == 7 && instr->Bits(19, 16) == 0 &&
|
| + instr->Bits(11, 6) == 0x17 && instr->Bit(4) == 0) {
|
| + int Vd = instr->VFPDRegValue(kSimd128Precision);
|
| + int Vm = instr->VFPMRegValue(kSimd128Precision);
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "vmvn q%d, q%d", Vd, Vm);
|
| + } else if (instr->Opc1Value() == 7 && instr->Bits(19, 16) == 0xB &&
|
| + instr->Bits(11, 9) == 0x3 && instr->Bit(6) == 1 &&
|
| + instr->Bit(4) == 0) {
|
| + int Vd = instr->VFPDRegValue(kSimd128Precision);
|
| + int Vm = instr->VFPMRegValue(kSimd128Precision);
|
| + const char* suffix = nullptr;
|
| + int op = instr->Bits(8, 7);
|
| + switch (op) {
|
| + case 0:
|
| + suffix = "f32.s32";
|
| + break;
|
| + case 1:
|
| + suffix = "f32.u32";
|
| + break;
|
| + case 2:
|
| + suffix = "s32.f32";
|
| + break;
|
| + case 3:
|
| + suffix = "u32.f32";
|
| + break;
|
| + }
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "vcvt.%s q%d, q%d", suffix, Vd, Vm);
|
| } else if ((instr->Bits(21, 16) == 0x32) && (instr->Bits(11, 7) == 0) &&
|
| (instr->Bit(4) == 0)) {
|
| if (instr->Bit(6) == 0) {
|
| @@ -1873,6 +1997,26 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
|
| out_buffer_pos_ +=
|
| SNPrintF(out_buffer_ + out_buffer_pos_, "vswp q%d, q%d", Vd, Vm);
|
| }
|
| + } else if (instr->Opc1Value() == 0x7 && instr->Bits(11, 7) == 0x18 &&
|
| + instr->Bit(4) == 0x0) {
|
| + int Vd = instr->VFPDRegValue(kSimd128Precision);
|
| + int Vm = instr->VFPMRegValue(kDoublePrecision);
|
| + int index = instr->Bit(19);
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "vdup q%d, d%d[%d]", Vd, Vm, index);
|
| + } else if (instr->Opc1Value() == 0x7 && instr->Bits(11, 10) == 0x2 &&
|
| + instr->Bit(4) == 0x0) {
|
| + int Vd = instr->VFPDRegValue(kDoublePrecision);
|
| + int Vn = instr->VFPNRegValue(kDoublePrecision);
|
| + int Vm = instr->VFPMRegValue(kDoublePrecision);
|
| + int len = instr->Bits(9, 8);
|
| + NeonListOperand list(DwVfpRegister::from_code(Vn), len + 1);
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "%s d%d, ",
|
| + instr->Bit(6) == 0 ? "vtbl.8" : "vtbx.8", Vd);
|
| + FormatNeonList(Vn, list.type());
|
| + Print(", ");
|
| + PrintDRegister(Vm);
|
| } else {
|
| Unknown(instr);
|
| }
|
|
|