Chromium Code Reviews| Index: src/arm/assembler-arm.cc |
| diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc |
| index ec75b7d07e62b2cb103761ede5e4253d3090b7d7..588f016f9923250e6d36e76fcd670ec8c5926cb6 100644 |
| --- a/src/arm/assembler-arm.cc |
| +++ b/src/arm/assembler-arm.cc |
| @@ -4074,25 +4074,43 @@ void Assembler::vcvt_u32_f32(const QwNeonRegister dst, |
| emit(EncodeNeonVCVT(U32, dst, F32, src)); |
| } |
| -// op is instr->Bits(11, 7). |
| -static Instr EncodeNeonUnaryOp(int op, bool is_float, NeonSize size, |
| - const QwNeonRegister dst, |
| - const QwNeonRegister src) { |
| - DCHECK_IMPLIES(is_float, size == Neon32); |
| +enum UnaryOp { VABS, VABSF, VNEG, VNEGF }; |
| + |
| +static Instr EncodeNeonUnaryOp(UnaryOp op, NeonSize size, QwNeonRegister dst, |
| + QwNeonRegister src) { |
| + int op_encoding = 0; |
| + switch (op) { |
| + case VABS: |
|
martyn.capewell
2017/02/28 15:45:24
Depending on whether you like fallthrough cases, t
bbudge
2017/02/28 17:39:34
I think v8 style is to avoid fall through unless i
|
| + op_encoding = 0x6 * B7; |
| + break; |
| + case VABSF: |
| + DCHECK_EQ(Neon32, size); |
| + op_encoding = 0x6 * B7 | B10; |
| + break; |
| + case VNEG: |
| + op_encoding = 0x7 * B7; |
| + break; |
| + case VNEGF: |
| + DCHECK_EQ(Neon32, size); |
| + op_encoding = 0x7 * B7 | B10; |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| int vd, d; |
| dst.split_code(&vd, &d); |
| int vm, m; |
| src.split_code(&vm, &m); |
| - int F = is_float ? 1 : 0; |
| - return 0x1E7U * B23 | d * B22 | 0x3 * B20 | size * B18 | B16 | vd * B12 | |
| - F * B10 | B8 | op * B7 | B6 | m * B5 | vm; |
| + return 0x1E7U * B23 | d * B22 | 0x3 * B20 | size * B18 | B16 | vd * B12 | B8 | |
|
martyn.capewell
2017/02/28 15:45:24
The switch above always sets B8, so it can be remo
bbudge
2017/02/28 17:39:34
Wow, good eye. Done.
|
| + B6 | m * B5 | vm | op_encoding; |
| } |
| void Assembler::vabs(const QwNeonRegister dst, const 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(0x6, true, Neon32, dst, src)); |
| + emit(EncodeNeonUnaryOp(VABSF, Neon32, dst, src)); |
| } |
| void Assembler::vabs(NeonSize size, const QwNeonRegister dst, |
| @@ -4100,14 +4118,14 @@ void Assembler::vabs(NeonSize size, const QwNeonRegister dst, |
| // 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(0x6, false, size, dst, src)); |
| + emit(EncodeNeonUnaryOp(VABS, size, dst, src)); |
| } |
| void Assembler::vneg(const QwNeonRegister dst, const 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(0x7, true, Neon32, dst, src)); |
| + emit(EncodeNeonUnaryOp(VNEGF, Neon32, dst, src)); |
| } |
| void Assembler::vneg(NeonSize size, const QwNeonRegister dst, |
| @@ -4115,7 +4133,7 @@ void Assembler::vneg(NeonSize size, const QwNeonRegister dst, |
| // 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(0x7, false, size, dst, src)); |
| + emit(EncodeNeonUnaryOp(VNEG, size, dst, src)); |
| } |
| void Assembler::veor(DwVfpRegister dst, DwVfpRegister src1, |
| @@ -4135,10 +4153,9 @@ void Assembler::veor(DwVfpRegister dst, DwVfpRegister src1, |
| enum BinaryBitwiseOp { VAND, VBIC, VBIF, VBIT, VBSL, VEOR, VORR, VORN }; |
| -static Instr EncodeNeonBinaryBitwiseOp(BinaryBitwiseOp op, |
| - const QwNeonRegister dst, |
| - const QwNeonRegister src1, |
| - const QwNeonRegister src2) { |
| +static Instr EncodeNeonBinaryBitwiseOp(BinaryBitwiseOp op, QwNeonRegister dst, |
| + QwNeonRegister src1, |
| + QwNeonRegister src2) { |
| int op_encoding = 0; |
| switch (op) { |
| case VBIC: |
| @@ -4287,9 +4304,8 @@ enum IntegerBinOp { |
| }; |
| static Instr EncodeNeonBinOp(IntegerBinOp op, NeonDataType dt, |
| - const QwNeonRegister dst, |
| - const QwNeonRegister src1, |
| - const QwNeonRegister src2) { |
| + QwNeonRegister dst, QwNeonRegister src1, |
| + QwNeonRegister src2) { |
| int op_encoding = 0; |
| switch (op) { |
| case VADD: |
| @@ -4341,10 +4357,8 @@ static Instr EncodeNeonBinOp(IntegerBinOp op, NeonDataType dt, |
| n * B7 | B6 | m * B5 | vm | op_encoding; |
| } |
| -static Instr EncodeNeonBinOp(IntegerBinOp op, NeonSize size, |
| - const QwNeonRegister dst, |
| - const QwNeonRegister src1, |
| - const QwNeonRegister src2) { |
| +static Instr EncodeNeonBinOp(IntegerBinOp op, NeonSize size, QwNeonRegister dst, |
| + QwNeonRegister src1, QwNeonRegister src2) { |
| // Map NeonSize values to the signed values in NeonDataType, so the U bit |
| // will be 0. |
| return EncodeNeonBinOp(op, static_cast<NeonDataType>(size), dst, src1, src2); |
| @@ -4529,6 +4543,51 @@ void Assembler::vrsqrts(QwNeonRegister dst, QwNeonRegister src1, |
| emit(EncodeNeonBinOp(VRSQRTS, dst, src1, src2)); |
| } |
| +enum PairwiseOp { VPMIN, VPMAX }; |
| + |
| +static Instr EncodeNeonPairwiseOp(PairwiseOp op, NeonDataType dt, |
| + DwVfpRegister dst, DwVfpRegister src1, |
| + DwVfpRegister src2) { |
| + int op_encoding = 0; |
| + switch (op) { |
| + case VPMIN: |
| + op_encoding = 0xA * B8 | B4; |
| + break; |
| + case VPMAX: |
| + op_encoding = 0xA * B8; |
| + break; |
| + default: |
| + 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 size = NeonSz(dt); |
| + int u = NeonU(dt); |
| + return 0x1E4U * B23 | u * B24 | d * B22 | size * B20 | vn * B16 | vd * B12 | |
| + n * B7 | m * B5 | vm | op_encoding; |
| +} |
| + |
| +void Assembler::vpmin(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1, |
| + DwVfpRegister src2) { |
| + DCHECK(IsEnabled(NEON)); |
| + // Qd = vpmin(Qn, Qm) SIMD integer pairwise MIN. |
|
martyn.capewell
2017/02/28 15:45:24
These are D registers for min and max.
bbudge
2017/02/28 17:39:35
Done here and below.
|
| + // Instruction details available in ARM DDI 0406C.b, A8-986. |
| + emit(EncodeNeonPairwiseOp(VPMIN, dt, dst, src1, src2)); |
| +} |
| + |
| +void Assembler::vpmax(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1, |
| + DwVfpRegister src2) { |
| + DCHECK(IsEnabled(NEON)); |
| + // Qd = vpmax(Qn, Qm) SIMD integer pairwise MAX. |
| + // Instruction details available in ARM DDI 0406C.b, A8-986. |
| + emit(EncodeNeonPairwiseOp(VPMAX, dt, dst, src1, src2)); |
| +} |
| + |
| void Assembler::vtst(NeonSize size, QwNeonRegister dst, QwNeonRegister src1, |
| QwNeonRegister src2) { |
| DCHECK(IsEnabled(NEON)); |