| Index: src/arm/assembler-arm.cc
|
| diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
|
| index c88f1f4840e485f3dc1a10d158f6a8265052b0f8..f6fd3a0698182a4596f0723a962666cc53d96dd7 100644
|
| --- a/src/arm/assembler-arm.cc
|
| +++ b/src/arm/assembler-arm.cc
|
| @@ -3054,13 +3054,9 @@ static void SplitRegCode(VFPType reg_type,
|
| int* m) {
|
| DCHECK((reg_code >= 0) && (reg_code <= 31));
|
| if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
|
| - // 32 bit type.
|
| - *m = reg_code & 0x1;
|
| - *vm = reg_code >> 1;
|
| + SwVfpRegister::split_code(reg_code, vm, m);
|
| } else {
|
| - // 64 bit type.
|
| - *m = (reg_code & 0x10) >> 4;
|
| - *vm = reg_code & 0x0F;
|
| + DwVfpRegister::split_code(reg_code, vm, m);
|
| }
|
| }
|
|
|
| @@ -3903,9 +3899,7 @@ void Assembler::vld1(NeonSize size,
|
| dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code());
|
| }
|
|
|
| -
|
| -void Assembler::vst1(NeonSize size,
|
| - const NeonListOperand& src,
|
| +void Assembler::vst1(NeonSize size, const NeonListOperand& src,
|
| const NeonMemOperand& dst) {
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.404.
|
| // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) |
|
| @@ -3984,51 +3978,13 @@ void Assembler::vmov(NeonDataType dt, Register dst, DwVfpRegister src,
|
| n * B7 | B4 | opc1_opc2);
|
| }
|
|
|
| -void Assembler::vmov(const QwNeonRegister dst, const QwNeonRegister src) {
|
| +void Assembler::vmov(QwNeonRegister dst, QwNeonRegister src) {
|
| // Instruction details available in ARM DDI 0406C.b, A8-938.
|
| // vmov is encoded as vorr.
|
| vorr(dst, src, src);
|
| }
|
|
|
| -void Assembler::vmvn(const QwNeonRegister dst, const QwNeonRegister src) {
|
| - DCHECK(IsEnabled(NEON));
|
| - // Instruction details available in ARM DDI 0406C.b, A8-966.
|
| - DCHECK(VfpRegisterIsAvailable(dst));
|
| - DCHECK(VfpRegisterIsAvailable(src));
|
| - int vd, d;
|
| - dst.split_code(&vd, &d);
|
| - int vm, m;
|
| - src.split_code(&vm, &m);
|
| - emit(0x1E7U * B23 | d * B22 | 3 * B20 | vd * B12 | 0x17 * B6 | m * B5 | vm);
|
| -}
|
| -
|
| -void Assembler::vswp(DwVfpRegister dst, DwVfpRegister src) {
|
| - // Instruction details available in ARM DDI 0406C.b, A8.8.418.
|
| - // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) |
|
| - // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0)
|
| - DCHECK(IsEnabled(NEON));
|
| - int vd, d;
|
| - dst.split_code(&vd, &d);
|
| - int vm, m;
|
| - src.split_code(&vm, &m);
|
| - emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | m * B5 | vm);
|
| -}
|
| -
|
| -void Assembler::vswp(QwNeonRegister dst, QwNeonRegister src) {
|
| - // Instruction details available in ARM DDI 0406C.b, A8.8.418.
|
| - // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) |
|
| - // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0)
|
| - DCHECK(IsEnabled(NEON));
|
| - int vd, d;
|
| - dst.split_code(&vd, &d);
|
| - int vm, m;
|
| - src.split_code(&vm, &m);
|
| - emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | B6 | m * B5 |
|
| - vm);
|
| -}
|
| -
|
| -void Assembler::vdup(NeonSize size, const QwNeonRegister dst,
|
| - const Register src) {
|
| +void Assembler::vdup(NeonSize size, QwNeonRegister dst, Register src) {
|
| DCHECK(IsEnabled(NEON));
|
| // Instruction details available in ARM DDI 0406C.b, A8-886.
|
| int B = 0, E = 0;
|
| @@ -4052,7 +4008,7 @@ void Assembler::vdup(NeonSize size, const QwNeonRegister dst,
|
| 0xB * B8 | d * B7 | E * B5 | B4);
|
| }
|
|
|
| -void Assembler::vdup(const QwNeonRegister dst, const SwVfpRegister src) {
|
| +void Assembler::vdup(QwNeonRegister dst, SwVfpRegister src) {
|
| DCHECK(IsEnabled(NEON));
|
| // Instruction details available in ARM DDI 0406C.b, A8-884.
|
| int index = src.code() & 1;
|
| @@ -4068,8 +4024,8 @@ void Assembler::vdup(const QwNeonRegister dst, const SwVfpRegister src) {
|
| }
|
|
|
| // Encode NEON vcvt.src_type.dst_type instruction.
|
| -static Instr EncodeNeonVCVT(const VFPType dst_type, const QwNeonRegister dst,
|
| - const VFPType src_type, const QwNeonRegister src) {
|
| +static Instr EncodeNeonVCVT(VFPType dst_type, QwNeonRegister dst,
|
| + VFPType src_type, QwNeonRegister src) {
|
| DCHECK(src_type != dst_type);
|
| DCHECK(src_type == F32 || dst_type == F32);
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.868.
|
| @@ -4091,120 +4047,137 @@ static Instr EncodeNeonVCVT(const VFPType dst_type, const QwNeonRegister dst,
|
| B6 | m * B5 | vm;
|
| }
|
|
|
| -void Assembler::vcvt_f32_s32(const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vcvt_f32_s32(QwNeonRegister dst, QwNeonRegister src) {
|
| DCHECK(IsEnabled(NEON));
|
| DCHECK(VfpRegisterIsAvailable(dst));
|
| DCHECK(VfpRegisterIsAvailable(src));
|
| emit(EncodeNeonVCVT(F32, dst, S32, src));
|
| }
|
|
|
| -void Assembler::vcvt_f32_u32(const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vcvt_f32_u32(QwNeonRegister dst, QwNeonRegister src) {
|
| DCHECK(IsEnabled(NEON));
|
| DCHECK(VfpRegisterIsAvailable(dst));
|
| DCHECK(VfpRegisterIsAvailable(src));
|
| emit(EncodeNeonVCVT(F32, dst, U32, src));
|
| }
|
|
|
| -void Assembler::vcvt_s32_f32(const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vcvt_s32_f32(QwNeonRegister dst, QwNeonRegister src) {
|
| DCHECK(IsEnabled(NEON));
|
| DCHECK(VfpRegisterIsAvailable(dst));
|
| DCHECK(VfpRegisterIsAvailable(src));
|
| emit(EncodeNeonVCVT(S32, dst, F32, src));
|
| }
|
|
|
| -void Assembler::vcvt_u32_f32(const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vcvt_u32_f32(QwNeonRegister dst, QwNeonRegister src) {
|
| DCHECK(IsEnabled(NEON));
|
| DCHECK(VfpRegisterIsAvailable(dst));
|
| DCHECK(VfpRegisterIsAvailable(src));
|
| emit(EncodeNeonVCVT(U32, dst, F32, src));
|
| }
|
|
|
| -enum UnaryOp { VABS, VABSF, VNEG, VNEGF };
|
| +enum NeonRegType { NEON_D, NEON_Q };
|
| +
|
| +enum UnaryOp { VMVN, VSWP, VABS, VABSF, VNEG, VNEGF };
|
|
|
| -static Instr EncodeNeonUnaryOp(UnaryOp op, NeonSize size, QwNeonRegister dst,
|
| - QwNeonRegister src) {
|
| +static Instr EncodeNeonUnaryOp(UnaryOp op, NeonRegType reg_type, NeonSize size,
|
| + int dst_code, int src_code) {
|
| int op_encoding = 0;
|
| switch (op) {
|
| + case VMVN:
|
| + DCHECK_EQ(Neon8, size); // size == 0 for vmvn
|
| + op_encoding = B10 | 0x3 * B7;
|
| + break;
|
| + case VSWP:
|
| + DCHECK_EQ(Neon8, size); // size == 0 for vswp
|
| + op_encoding = B17;
|
| + break;
|
| case VABS:
|
| - op_encoding = 0x6 * B7;
|
| + op_encoding = B16 | 0x6 * B7;
|
| break;
|
| case VABSF:
|
| DCHECK_EQ(Neon32, size);
|
| - op_encoding = 0x6 * B7 | B10;
|
| + op_encoding = B16 | B10 | 0x6 * B7;
|
| break;
|
| case VNEG:
|
| - op_encoding = 0x7 * B7;
|
| + op_encoding = B16 | 0x7 * B7;
|
| break;
|
| case VNEGF:
|
| DCHECK_EQ(Neon32, size);
|
| - op_encoding = 0x7 * B7 | B10;
|
| + op_encoding = B16 | B10 | 0x7 * B7;
|
| break;
|
| default:
|
| UNREACHABLE();
|
| break;
|
| }
|
| - int vd, d;
|
| - dst.split_code(&vd, &d);
|
| - int vm, m;
|
| - src.split_code(&vm, &m);
|
| - return 0x1E7U * B23 | d * B22 | 0x3 * B20 | size * B18 | B16 | vd * B12 | B6 |
|
| - m * B5 | vm | op_encoding;
|
| + int vd, d, vm, m;
|
| + if (reg_type == NEON_Q) {
|
| + op_encoding |= B6;
|
| + QwNeonRegister::split_code(dst_code, &vd, &d);
|
| + QwNeonRegister::split_code(src_code, &vm, &m);
|
| + } else {
|
| + DCHECK_EQ(reg_type, NEON_D);
|
| + DwVfpRegister::split_code(dst_code, &vd, &d);
|
| + DwVfpRegister::split_code(src_code, &vm, &m);
|
| + }
|
| + return 0x1E7U * B23 | d * B22 | 0x3 * B20 | size * B18 | vd * B12 | m * B5 |
|
| + vm | op_encoding;
|
| +}
|
| +
|
| +void Assembler::vmvn(QwNeonRegister dst, QwNeonRegister src) {
|
| + // Qd = vmvn(Qn, Qm) SIMD bitwise negate.
|
| + // Instruction details available in ARM DDI 0406C.b, A8-966.
|
| + DCHECK(IsEnabled(NEON));
|
| + emit(EncodeNeonUnaryOp(VMVN, NEON_Q, Neon8, dst.code(), src.code()));
|
| }
|
|
|
| -void Assembler::vabs(const QwNeonRegister dst, const QwNeonRegister src) {
|
| +void Assembler::vswp(DwVfpRegister dst, DwVfpRegister src) {
|
| + DCHECK(IsEnabled(NEON));
|
| + // Dd = vswp(Dn, Dm) SIMD d-register swap.
|
| + // Instruction details available in ARM DDI 0406C.b, A8.8.418.
|
| + DCHECK(IsEnabled(NEON));
|
| + emit(EncodeNeonUnaryOp(VSWP, NEON_D, Neon8, dst.code(), src.code()));
|
| +}
|
| +
|
| +void Assembler::vswp(QwNeonRegister dst, QwNeonRegister src) {
|
| + // Qd = vswp(Qn, Qm) SIMD q-register swap.
|
| + // Instruction details available in ARM DDI 0406C.b, A8.8.418.
|
| + DCHECK(IsEnabled(NEON));
|
| + emit(EncodeNeonUnaryOp(VSWP, NEON_Q, Neon8, dst.code(), src.code()));
|
| +}
|
| +
|
| +void Assembler::vabs(QwNeonRegister dst, QwNeonRegister src) {
|
| // Qd = vabs.f<size>(Qn, Qm) SIMD floating point absolute value.
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.824.
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonUnaryOp(VABSF, Neon32, dst, src));
|
| + emit(EncodeNeonUnaryOp(VABSF, NEON_Q, Neon32, dst.code(), src.code()));
|
| }
|
|
|
| -void Assembler::vabs(NeonSize size, const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vabs(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
|
| // Qd = vabs.s<size>(Qn, Qm) SIMD integer absolute value.
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.824.
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonUnaryOp(VABS, size, dst, src));
|
| + emit(EncodeNeonUnaryOp(VABS, NEON_Q, size, dst.code(), src.code()));
|
| }
|
|
|
| -void Assembler::vneg(const QwNeonRegister dst, const QwNeonRegister src) {
|
| +void Assembler::vneg(QwNeonRegister dst, QwNeonRegister src) {
|
| // Qd = vabs.f<size>(Qn, Qm) SIMD floating point negate.
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.968.
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonUnaryOp(VNEGF, Neon32, dst, src));
|
| + emit(EncodeNeonUnaryOp(VNEGF, NEON_Q, Neon32, dst.code(), src.code()));
|
| }
|
|
|
| -void Assembler::vneg(NeonSize size, const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vneg(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
|
| // Qd = vabs.s<size>(Qn, Qm) SIMD integer negate.
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.968.
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonUnaryOp(VNEG, size, dst, src));
|
| -}
|
| -
|
| -void Assembler::veor(DwVfpRegister dst, DwVfpRegister src1,
|
| - DwVfpRegister src2) {
|
| - // Dd = veor(Dn, Dm) 64 bit integer exclusive OR.
|
| - // Instruction details available in ARM DDI 0406C.b, A8.8.888.
|
| - DCHECK(IsEnabled(NEON));
|
| - int vd, d;
|
| - dst.split_code(&vd, &d);
|
| - int vn, n;
|
| - src1.split_code(&vn, &n);
|
| - int vm, m;
|
| - src2.split_code(&vm, &m);
|
| - emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | B8 | n * B7 | m * B5 |
|
| - B4 | vm);
|
| + emit(EncodeNeonUnaryOp(VNEG, NEON_Q, size, dst.code(), src.code()));
|
| }
|
|
|
| enum BinaryBitwiseOp { VAND, VBIC, VBIF, VBIT, VBSL, VEOR, VORR, VORN };
|
|
|
| -static Instr EncodeNeonBinaryBitwiseOp(BinaryBitwiseOp op, QwNeonRegister dst,
|
| - QwNeonRegister src1,
|
| - QwNeonRegister src2) {
|
| +static Instr EncodeNeonBinaryBitwiseOp(BinaryBitwiseOp op, NeonRegType reg_type,
|
| + int dst_code, int src_code1,
|
| + int src_code2) {
|
| int op_encoding = 0;
|
| switch (op) {
|
| case VBIC:
|
| @@ -4235,14 +4208,20 @@ static Instr EncodeNeonBinaryBitwiseOp(BinaryBitwiseOp op, QwNeonRegister dst,
|
| UNREACHABLE();
|
| break;
|
| }
|
| - int vd, d;
|
| - dst.split_code(&vd, &d);
|
| - int vn, n;
|
| - src1.split_code(&vn, &n);
|
| - int vm, m;
|
| - src2.split_code(&vm, &m);
|
| + int vd, d, vn, n, vm, m;
|
| + if (reg_type == NEON_Q) {
|
| + op_encoding |= B6;
|
| + QwNeonRegister::split_code(dst_code, &vd, &d);
|
| + QwNeonRegister::split_code(src_code1, &vn, &n);
|
| + QwNeonRegister::split_code(src_code2, &vm, &m);
|
| + } else {
|
| + DCHECK_EQ(reg_type, NEON_D);
|
| + DwVfpRegister::split_code(dst_code, &vd, &d);
|
| + DwVfpRegister::split_code(src_code1, &vn, &n);
|
| + DwVfpRegister::split_code(src_code2, &vm, &m);
|
| + }
|
| return 0x1E4U * B23 | op_encoding | d * B22 | vn * B16 | vd * B12 | B8 |
|
| - n * B7 | B6 | m * B5 | B4 | vm;
|
| + n * B7 | m * B5 | B4 | vm;
|
| }
|
|
|
| void Assembler::vand(QwNeonRegister dst, QwNeonRegister src1,
|
| @@ -4250,15 +4229,26 @@ void Assembler::vand(QwNeonRegister dst, QwNeonRegister src1,
|
| // Qd = vand(Qn, Qm) SIMD AND.
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.836.
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonBinaryBitwiseOp(VAND, dst, src1, src2));
|
| + emit(EncodeNeonBinaryBitwiseOp(VAND, NEON_Q, dst.code(), src1.code(),
|
| + src2.code()));
|
| }
|
|
|
| -void Assembler::vbsl(QwNeonRegister dst, const QwNeonRegister src1,
|
| - const QwNeonRegister src2) {
|
| - DCHECK(IsEnabled(NEON));
|
| +void Assembler::vbsl(QwNeonRegister dst, QwNeonRegister src1,
|
| + QwNeonRegister src2) {
|
| // Qd = vbsl(Qn, Qm) SIMD bitwise select.
|
| // Instruction details available in ARM DDI 0406C.b, A8-844.
|
| - emit(EncodeNeonBinaryBitwiseOp(VBSL, dst, src1, src2));
|
| + DCHECK(IsEnabled(NEON));
|
| + emit(EncodeNeonBinaryBitwiseOp(VBSL, NEON_Q, dst.code(), src1.code(),
|
| + src2.code()));
|
| +}
|
| +
|
| +void Assembler::veor(DwVfpRegister dst, DwVfpRegister src1,
|
| + DwVfpRegister src2) {
|
| + // Dd = veor(Dn, Dm) SIMD exclusive OR.
|
| + // Instruction details available in ARM DDI 0406C.b, A8.8.888.
|
| + DCHECK(IsEnabled(NEON));
|
| + emit(EncodeNeonBinaryBitwiseOp(VEOR, NEON_D, dst.code(), src1.code(),
|
| + src2.code()));
|
| }
|
|
|
| void Assembler::veor(QwNeonRegister dst, QwNeonRegister src1,
|
| @@ -4266,7 +4256,8 @@ void Assembler::veor(QwNeonRegister dst, QwNeonRegister src1,
|
| // Qd = veor(Qn, Qm) SIMD exclusive OR.
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.888.
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonBinaryBitwiseOp(VEOR, dst, src1, src2));
|
| + emit(EncodeNeonBinaryBitwiseOp(VEOR, NEON_Q, dst.code(), src1.code(),
|
| + src2.code()));
|
| }
|
|
|
| void Assembler::vorr(QwNeonRegister dst, QwNeonRegister src1,
|
| @@ -4274,7 +4265,8 @@ void Assembler::vorr(QwNeonRegister dst, QwNeonRegister src1,
|
| // Qd = vorr(Qn, Qm) SIMD OR.
|
| // Instruction details available in ARM DDI 0406C.b, A8.8.976.
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonBinaryBitwiseOp(VORR, dst, src1, src2));
|
| + emit(EncodeNeonBinaryBitwiseOp(VORR, NEON_Q, dst.code(), src1.code(),
|
| + src2.code()));
|
| }
|
|
|
| enum FPBinOp {
|
| @@ -4469,16 +4461,16 @@ void Assembler::vmul(QwNeonRegister dst, QwNeonRegister src1,
|
| emit(EncodeNeonBinOp(VMULF, dst, src1, src2));
|
| }
|
|
|
| -void Assembler::vmul(NeonSize size, QwNeonRegister dst,
|
| - const QwNeonRegister src1, const QwNeonRegister src2) {
|
| +void Assembler::vmul(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
|
| + QwNeonRegister src2) {
|
| DCHECK(IsEnabled(NEON));
|
| // Qd = vadd(Qn, Qm) SIMD integer multiply.
|
| // Instruction details available in ARM DDI 0406C.b, A8-960.
|
| emit(EncodeNeonBinOp(VMUL, size, dst, src1, src2));
|
| }
|
|
|
| -void Assembler::vmin(const QwNeonRegister dst, const QwNeonRegister src1,
|
| - const QwNeonRegister src2) {
|
| +void Assembler::vmin(QwNeonRegister dst, QwNeonRegister src1,
|
| + QwNeonRegister src2) {
|
| DCHECK(IsEnabled(NEON));
|
| // Qd = vmin(Qn, Qm) SIMD floating point MIN.
|
| // Instruction details available in ARM DDI 0406C.b, A8-928.
|
| @@ -4592,9 +4584,9 @@ void Assembler::vrsqrts(QwNeonRegister dst, QwNeonRegister src1,
|
| emit(EncodeNeonBinOp(VRSQRTS, dst, src1, src2));
|
| }
|
|
|
| -enum PairwiseOp { VPMIN, VPMAX };
|
| +enum NeonPairwiseOp { VPMIN, VPMAX };
|
|
|
| -static Instr EncodeNeonPairwiseOp(PairwiseOp op, NeonDataType dt,
|
| +static Instr EncodeNeonPairwiseOp(NeonPairwiseOp op, NeonDataType dt,
|
| DwVfpRegister dst, DwVfpRegister src1,
|
| DwVfpRegister src2) {
|
| int op_encoding = 0;
|
| @@ -4693,8 +4685,8 @@ void Assembler::vcgt(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
|
| emit(EncodeNeonBinOp(VCGT, dt, dst, src1, src2));
|
| }
|
|
|
| -void Assembler::vext(QwNeonRegister dst, const QwNeonRegister src1,
|
| - const QwNeonRegister src2, int bytes) {
|
| +void Assembler::vext(QwNeonRegister dst, QwNeonRegister src1,
|
| + QwNeonRegister src2, int bytes) {
|
| DCHECK(IsEnabled(NEON));
|
| // Qd = vext(Qn, Qm) SIMD byte extract.
|
| // Instruction details available in ARM DDI 0406C.b, A8-890.
|
| @@ -4709,57 +4701,88 @@ void Assembler::vext(QwNeonRegister dst, const QwNeonRegister src1,
|
| n * B7 | B6 | m * B5 | vm);
|
| }
|
|
|
| -void Assembler::vzip(NeonSize size, QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| - DCHECK(IsEnabled(NEON));
|
| - // Qd = vzip.<size>(Qn, Qm) SIMD zip (interleave).
|
| - // Instruction details available in ARM DDI 0406C.b, A8-1102.
|
| +enum NeonSizedOp { VZIP, VUZP, VREV16, VREV32, VREV64, VTRN };
|
| +
|
| +static Instr EncodeNeonSizedOp(NeonSizedOp op, NeonSize size,
|
| + QwNeonRegister dst, QwNeonRegister src) {
|
| + int op_encoding = 0;
|
| + switch (op) {
|
| + case VZIP:
|
| + op_encoding = 0x2 * B16 | 0x3 * B7;
|
| + break;
|
| + case VUZP:
|
| + op_encoding = 0x2 * B16 | 0x2 * B7;
|
| + break;
|
| + case VREV16:
|
| + op_encoding = 0x2 * B7;
|
| + break;
|
| + case VREV32:
|
| + op_encoding = 0x1 * B7;
|
| + break;
|
| + case VREV64:
|
| + // op_encoding is 0;
|
| + break;
|
| + case VTRN:
|
| + op_encoding = 0x2 * B16 | B7;
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| int vd, d;
|
| dst.split_code(&vd, &d);
|
| int vm, m;
|
| src.split_code(&vm, &m);
|
| int sz = static_cast<int>(size);
|
| - emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | sz * B18 | 2 * B16 | vd * B12 |
|
| - 0x3 * B7 | B6 | m * B5 | vm);
|
| + return 0x1E7U * B23 | d * B22 | 0x3 * B20 | sz * B18 | vd * B12 | B6 |
|
| + m * B5 | vm | op_encoding;
|
| +}
|
| +
|
| +void Assembler::vzip(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
|
| + DCHECK(IsEnabled(NEON));
|
| + // Qd = vzip.<size>(Qn, Qm) SIMD zip (interleave).
|
| + // Instruction details available in ARM DDI 0406C.b, A8-1102.
|
| + emit(EncodeNeonSizedOp(VZIP, size, src1, src2));
|
| }
|
|
|
| -static Instr EncodeNeonVREV(NeonSize op_size, NeonSize size,
|
| - const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vuzp(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
|
| + DCHECK(IsEnabled(NEON));
|
| + // Qd = vuzp.<size>(Qn, Qm) SIMD un-zip (de-interleave).
|
| + // Instruction details available in ARM DDI 0406C.b, A8-1100.
|
| + emit(EncodeNeonSizedOp(VUZP, size, src1, src2));
|
| +}
|
| +
|
| +void Assembler::vrev16(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
|
| + DCHECK(IsEnabled(NEON));
|
| // Qd = vrev<op_size>.<size>(Qn, Qm) SIMD scalar reverse.
|
| // Instruction details available in ARM DDI 0406C.b, A8-1028.
|
| - DCHECK_GT(op_size, static_cast<int>(size));
|
| - int vd, d;
|
| - dst.split_code(&vd, &d);
|
| - int vm, m;
|
| - src.split_code(&vm, &m);
|
| - int sz = static_cast<int>(size);
|
| - int op = static_cast<int>(Neon64) - static_cast<int>(op_size);
|
| - return 0x1E7U * B23 | d * B22 | 0x3 * B20 | sz * B18 | vd * B12 | op * B7 |
|
| - B6 | m * B5 | vm;
|
| + emit(EncodeNeonSizedOp(VREV16, size, dst, src));
|
| }
|
|
|
| -void Assembler::vrev16(NeonSize size, const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vrev32(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonVREV(Neon16, size, dst, src));
|
| + // Qd = vrev<op_size>.<size>(Qn, Qm) SIMD scalar reverse.
|
| + // Instruction details available in ARM DDI 0406C.b, A8-1028.
|
| + emit(EncodeNeonSizedOp(VREV32, size, dst, src));
|
| }
|
|
|
| -void Assembler::vrev32(NeonSize size, const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vrev64(NeonSize size, QwNeonRegister dst, QwNeonRegister src) {
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonVREV(Neon32, size, dst, src));
|
| + // Qd = vrev<op_size>.<size>(Qn, Qm) SIMD scalar reverse.
|
| + // Instruction details available in ARM DDI 0406C.b, A8-1028.
|
| + emit(EncodeNeonSizedOp(VREV64, size, dst, src));
|
| }
|
|
|
| -void Assembler::vrev64(NeonSize size, const QwNeonRegister dst,
|
| - const QwNeonRegister src) {
|
| +void Assembler::vtrn(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
|
| DCHECK(IsEnabled(NEON));
|
| - emit(EncodeNeonVREV(Neon64, size, dst, src));
|
| + // Qd = vrev<op_size>.<size>(Qn, Qm) SIMD scalar reverse.
|
| + // Instruction details available in ARM DDI 0406C.b, A8-1096.
|
| + emit(EncodeNeonSizedOp(VTRN, size, src1, src2));
|
| }
|
|
|
| // Encode NEON vtbl / vtbx instruction.
|
| -static Instr EncodeNeonVTB(const DwVfpRegister dst, const NeonListOperand& list,
|
| - const DwVfpRegister index, bool vtbx) {
|
| +static Instr EncodeNeonVTB(DwVfpRegister dst, const NeonListOperand& list,
|
| + DwVfpRegister index, bool vtbx) {
|
| // Dd = vtbl(table, Dm) SIMD vector permute, zero at out of range indices.
|
| // Instruction details available in ARM DDI 0406C.b, A8-1094.
|
| // Dd = vtbx(table, Dm) SIMD vector permute, skip out of range indices.
|
| @@ -4775,14 +4798,14 @@ static Instr EncodeNeonVTB(const DwVfpRegister dst, const NeonListOperand& list,
|
| list.length() * B8 | n * B7 | op * B6 | m * B5 | vm;
|
| }
|
|
|
| -void Assembler::vtbl(const DwVfpRegister dst, const NeonListOperand& list,
|
| - const DwVfpRegister index) {
|
| +void Assembler::vtbl(DwVfpRegister dst, const NeonListOperand& list,
|
| + DwVfpRegister index) {
|
| DCHECK(IsEnabled(NEON));
|
| emit(EncodeNeonVTB(dst, list, index, false));
|
| }
|
|
|
| -void Assembler::vtbx(const DwVfpRegister dst, const NeonListOperand& list,
|
| - const DwVfpRegister index) {
|
| +void Assembler::vtbx(DwVfpRegister dst, const NeonListOperand& list,
|
| + DwVfpRegister index) {
|
| DCHECK(IsEnabled(NEON));
|
| emit(EncodeNeonVTB(dst, list, index, true));
|
| }
|
|
|