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; |