diff options
Diffstat (limited to 'deps/v8/src/arm/disasm-arm.cc')
-rw-r--r-- | deps/v8/src/arm/disasm-arm.cc | 379 |
1 files changed, 359 insertions, 20 deletions
diff --git a/deps/v8/src/arm/disasm-arm.cc b/deps/v8/src/arm/disasm-arm.cc index e408e85da3..db32fc98ce 100644 --- a/deps/v8/src/arm/disasm-arm.cc +++ b/deps/v8/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. } } } @@ -1801,6 +1856,104 @@ static const char* const barrier_option_names[] = { void Decoder::DecodeSpecialCondition(Instruction* instr) { switch (instr->SpecialValue()) { + case 4: + if (instr->Bits(11, 8) == 1 && instr->Bits(21, 20) == 2 && + instr->Bit(6) == 1 && instr->Bit(4) == 1) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + if (Vm == Vn) { + // vmov Qd, Qm + out_buffer_pos_ += + SNPrintF(out_buffer_ + out_buffer_pos_, "vmov q%d, q%d", Vd, Vm); + } else { + // vorr Qd, Qm, Qn. + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vorr q%d, q%d, q%d", Vd, Vn, 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 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 if (instr->Bits(11, 8) == 0x9 && instr->Bit(6) == 1 && + instr->Bit(4) == 1) { + int size = kBitsPerByte * (1 << instr->Bits(21, 20)); + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + // vmul.i<size> Qd, Qm, Qn. + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vmul.i%d q%d, q%d, q%d", size, Vd, Vn, Vm); + } else if (instr->Bits(11, 8) == 0xe && instr->Bits(21, 20) == 0 && + instr->Bit(4) == 0) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + // vceq.f32 Qd, Qm, Qn. + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vceq.f32 q%d, q%d, q%d", Vd, Vn, Vm); + } else if (instr->Bits(11, 8) == 1 && instr->Bits(21, 20) == 0 && + instr->Bit(6) == 1 && instr->Bit(4) == 1) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + // vand Qd, Qm, Qn. + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vand q%d, q%d, q%d", Vd, Vn, Vm); + } else if (instr->Bits(11, 8) == 0x3) { + int size = kBitsPerByte * (1 << instr->Bits(21, 20)); + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt"; + // vcge/vcgt.s<size> Qd, Qm, Qn. + out_buffer_pos_ += + SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d", op, + size, Vd, Vn, Vm); + } else if (instr->Bits(11, 8) == 0xf && instr->Bit(20) == 0 && + instr->Bit(6) == 1) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + if (instr->Bit(4) == 1) { + // vrecps/vrsqrts.f32 Qd, Qm, Qn. + const char* op = instr->Bit(21) == 0 ? "vrecps" : "vrsqrts"; + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm); + } else { + // vmin/max.f32 Qd, Qm, Qn. + const char* op = instr->Bit(21) == 1 ? "vmin" : "vmax"; + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "%s.f32 q%d, q%d, q%d", op, Vd, Vn, Vm); + } + } else if (instr->Bits(11, 8) == 0x6) { + int size = kBitsPerByte * (1 << instr->Bits(21, 20)); + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + // vmin/vmax.s<size> Qd, Qm, Qn. + const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax"; + out_buffer_pos_ += + SNPrintF(out_buffer_ + out_buffer_pos_, "%s.s%d q%d, q%d, q%d", op, + size, Vd, Vn, Vm); + } else { + Unknown(instr); + } + break; case 5: if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) && (instr->Bit(4) == 1)) { @@ -1811,6 +1964,96 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) { int imm3 = instr->Bits(21, 19); out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm); + } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) { + // vext.8 Qd, Qm, Qn, imm4 + int imm4 = instr->Bits(11, 8); + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + out_buffer_pos_ += + SNPrintF(out_buffer_ + out_buffer_pos_, "vext.8 q%d, q%d, q%d, #%d", + Vd, Vn, Vm, imm4); + } else { + Unknown(instr); + } + break; + case 6: + 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(11, 8) == 1 && instr->Bits(21, 20) == 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(11, 8) == 1 && instr->Bits(21, 20) == 0 && + instr->Bit(4) == 1) { + if (instr->Bit(6) == 0) { + // veor Dd, Dn, Dm + int Vd = instr->VFPDRegValue(kDoublePrecision); + int Vn = instr->VFPNRegValue(kDoublePrecision); + int Vm = instr->VFPMRegValue(kDoublePrecision); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "veor d%d, d%d, d%d", Vd, Vn, Vm); + + } else { + // veor Qd, Qn, Qm + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "veor q%d, q%d, q%d", Vd, Vn, Vm); + } + } else if (instr->Bits(11, 8) == 0xd && instr->Bit(21) == 0 && + instr->Bit(6) == 1 && instr->Bit(4) == 1) { + // vmul.f32 Qd, Qn, Qm + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vmul.f32 q%d, q%d, q%d", Vd, Vn, Vm); + } else if (instr->Bits(11, 8) == 0xe && instr->Bit(20) == 0 && + instr->Bit(4) == 0) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + const char* op = (instr->Bit(21) == 0) ? "vcge" : "vcgt"; + // vcge/vcgt.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 if (instr->Bits(11, 8) == 0x3) { + int size = kBitsPerByte * (1 << instr->Bits(21, 20)); + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + const char* op = (instr->Bit(4) == 1) ? "vcge" : "vcgt"; + // vcge/vcgt.u<size> Qd, Qm, Qn. + out_buffer_pos_ += + SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d", op, + size, Vd, Vn, Vm); + } else if (instr->Bits(11, 8) == 0x6) { + int size = kBitsPerByte * (1 << instr->Bits(21, 20)); + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int Vn = instr->VFPNRegValue(kSimd128Precision); + // vmin/vmax.u<size> Qd, Qm, Qn. + const char* op = instr->Bit(4) == 1 ? "vmin" : "vmax"; + out_buffer_pos_ += + SNPrintF(out_buffer_ + out_buffer_pos_, "%s.u%d q%d, q%d, q%d", op, + size, Vd, Vn, Vm); } else { Unknown(instr); } @@ -1825,13 +2068,109 @@ 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->Bits(21, 16) == 0x32) && (instr->Bits(11, 7) == 0) && - (instr->Bit(4) == 0)) { - int Vd = instr->VFPDRegValue(kDoublePrecision); - int Vm = instr->VFPMRegValue(kDoublePrecision); - char rtype = (instr->Bit(6) == 0) ? 'd' : 'q'; - out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, - "vswp %c%d, %c%d", rtype, Vd, rtype, Vm); + } else if (instr->Opc1Value() == 7 && instr->Bits(21, 20) == 0x3 && + instr->Bit(4) == 0) { + if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) { + if (instr->Bit(6) == 0) { + int Vd = instr->VFPDRegValue(kDoublePrecision); + int Vm = instr->VFPMRegValue(kDoublePrecision); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vswp d%d, d%d", Vd, Vm); + } else { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vswp q%d, q%d", Vd, Vm); + } + } else if (instr->Bits(11, 7) == 0x18) { + 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->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) { + 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->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 && + instr->Bit(6) == 1) { + 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(11, 10) == 0x2) { + 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 if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 6) == 0x7) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int size = kBitsPerByte * (1 << instr->Bits(19, 18)); + // vzip.<size> Qd, Qm. + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vzip.%d q%d, q%d", size, Vd, Vm); + } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int size = kBitsPerByte * (1 << instr->Bits(19, 18)); + int op = kBitsPerByte + << (static_cast<int>(Neon64) - instr->Bits(8, 7)); + // vrev<op>.<size> Qd, Qm. + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "vrev%d.%d q%d, q%d", op, size, Vd, Vm); + } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + int size = kBitsPerByte * (1 << instr->Bits(19, 18)); + const char* type = instr->Bit(10) != 0 ? "f" : "s"; + if (instr->Bits(9, 6) == 0xd) { + // vabs<type>.<size> Qd, Qm. + out_buffer_pos_ += + SNPrintF(out_buffer_ + out_buffer_pos_, "vabs.%s%d q%d, q%d", + type, size, Vd, Vm); + } else if (instr->Bits(9, 6) == 0xf) { + // vneg<type>.<size> Qd, Qm. + out_buffer_pos_ += + SNPrintF(out_buffer_ + out_buffer_pos_, "vneg.%s%d q%d, q%d", + type, size, Vd, Vm); + } else { + Unknown(instr); + } + } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5) { + int Vd = instr->VFPDRegValue(kSimd128Precision); + int Vm = instr->VFPMRegValue(kSimd128Precision); + const char* op = instr->Bit(7) == 0 ? "vrecpe" : "vrsqrte"; + // vrecpe/vrsqrte.f32 Qd, Qm. + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, + "%s.f32 q%d, q%d", op, Vd, Vm); + } else { + Unknown(instr); + } } else { Unknown(instr); } |