| Index: src/arm/assembler-arm.cc
|
| diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
|
| index 6fef17b0b120039a72f5beef463c3ddf3092c28e..52213b06ccebc89d64b34939a0ebb730571f6828 100644
|
| --- a/src/arm/assembler-arm.cc
|
| +++ b/src/arm/assembler-arm.cc
|
| @@ -4412,6 +4412,48 @@ void Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
|
| emit(EncodeNeonBinOp(VMAX, dt, dst, src1, src2));
|
| }
|
|
|
| +enum NeonShiftOp { VSHL, VSHR };
|
| +
|
| +static Instr EncodeNeonShiftOp(NeonShiftOp op, NeonDataType dt,
|
| + QwNeonRegister dst, QwNeonRegister src,
|
| + int shift) {
|
| + int vd, d;
|
| + dst.split_code(&vd, &d);
|
| + int vm, m;
|
| + src.split_code(&vm, &m);
|
| + int size_in_bits = kBitsPerByte << NeonSz(dt);
|
| + int op_encoding = 0;
|
| + int imm6 = 0;
|
| + if (op == VSHL) {
|
| + DCHECK(shift >= 0 && size_in_bits > shift);
|
| + imm6 = size_in_bits + shift;
|
| + op_encoding = 0x5 * B8;
|
| + } else {
|
| + DCHECK_EQ(VSHR, op);
|
| + DCHECK(shift > 0 && size_in_bits >= shift);
|
| + imm6 = 2 * size_in_bits - shift;
|
| + op_encoding = NeonU(dt) * B24;
|
| + }
|
| + return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | B6 | m * B5 | B4 |
|
| + vm | op_encoding;
|
| +}
|
| +
|
| +void Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
|
| + int shift) {
|
| + DCHECK(IsEnabled(NEON));
|
| + // Qd = vshl(Qm, bits) SIMD shift left immediate.
|
| + // Instruction details available in ARM DDI 0406C.b, A8-1046.
|
| + emit(EncodeNeonShiftOp(VSHL, dt, dst, src, shift));
|
| +}
|
| +
|
| +void Assembler::vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
|
| + int shift) {
|
| + DCHECK(IsEnabled(NEON));
|
| + // Qd = vshl(Qm, bits) SIMD shift right immediate.
|
| + // Instruction details available in ARM DDI 0406C.b, A8-1052.
|
| + emit(EncodeNeonShiftOp(VSHR, dt, dst, src, shift));
|
| +}
|
| +
|
| static Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst,
|
| QwNeonRegister src) {
|
| int vd, d;
|
|
|