Index: src/arm/assembler-arm.cc |
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc |
index 60beea4b842a7be343a3568468165e88b2dd6e19..1350dc41a3183b699f1b55f9ab4990a47fb4203a 100644 |
--- a/src/arm/assembler-arm.cc |
+++ b/src/arm/assembler-arm.cc |
@@ -4302,58 +4302,118 @@ void Assembler::vmul(NeonSize size, QwNeonRegister dst, |
n * B7 | B6 | m * B5 | B4 | vm); |
} |
-void Assembler::vrecpe(const QwNeonRegister dst, const QwNeonRegister src) { |
- DCHECK(IsEnabled(NEON)); |
- // Qd = vadd(Qn, Qm) SIMD reciprocal estimate. |
- // Instruction details available in ARM DDI 0406C.b, A8-1024. |
+static Instr EncodeNeonMinMax(bool is_min, QwNeonRegister dst, |
+ QwNeonRegister src1, QwNeonRegister src2) { |
int vd, d; |
dst.split_code(&vd, &d); |
+ int vn, n; |
+ src1.split_code(&vn, &n); |
int vm, m; |
- src.split_code(&vm, &m); |
- emit(0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 | B6 | m * B5 | |
- vm); |
+ src2.split_code(&vm, &m); |
+ int min = is_min ? 1 : 0; |
+ return 0x1E4U * B23 | d * B22 | min * B21 | vn * B16 | vd * B12 | 0xF * B8 | |
+ n * B7 | B6 | m * B5 | vm; |
} |
-void Assembler::vrsqrte(const QwNeonRegister dst, const QwNeonRegister src) { |
+static Instr EncodeNeonMinMax(bool is_min, NeonDataType dt, QwNeonRegister dst, |
+ QwNeonRegister src1, QwNeonRegister src2) { |
+ 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 min = is_min ? 1 : 0; |
+ int size = (dt & NeonDataTypeSizeMask) / 2; |
+ int U = dt & NeonDataTypeUMask; |
+ return 0x1E4U * B23 | U | d * B22 | size * B20 | vn * B16 | vd * B12 | |
+ 0x6 * B8 | B6 | m * B5 | min * B4 | vm; |
+} |
+ |
+void Assembler::vmin(const QwNeonRegister dst, const QwNeonRegister src1, |
+ const QwNeonRegister src2) { |
DCHECK(IsEnabled(NEON)); |
- // Qd = vadd(Qn, Qm) SIMD reciprocal square root estimate. |
- // Instruction details available in ARM DDI 0406C.b, A8-1038. |
+ // Qd = vmin(Qn, Qm) SIMD floating point MIN. |
+ // Instruction details available in ARM DDI 0406C.b, A8-928. |
+ emit(EncodeNeonMinMax(true, dst, src1, src2)); |
+} |
+ |
+void Assembler::vmin(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, |
+ QwNeonRegister src2) { |
+ DCHECK(IsEnabled(NEON)); |
+ // Qd = vmin(Qn, Qm) SIMD integer MIN. |
+ // Instruction details available in ARM DDI 0406C.b, A8-926. |
+ emit(EncodeNeonMinMax(true, dt, dst, src1, src2)); |
+} |
+ |
+void Assembler::vmax(QwNeonRegister dst, QwNeonRegister src1, |
+ QwNeonRegister src2) { |
+ DCHECK(IsEnabled(NEON)); |
+ // Qd = vmax(Qn, Qm) SIMD floating point MAX. |
+ // Instruction details available in ARM DDI 0406C.b, A8-928. |
+ emit(EncodeNeonMinMax(false, dst, src1, src2)); |
+} |
+ |
+void Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, |
+ QwNeonRegister src2) { |
+ DCHECK(IsEnabled(NEON)); |
+ // Qd = vmax(Qn, Qm) SIMD integer MAX. |
+ // Instruction details available in ARM DDI 0406C.b, A8-926. |
+ emit(EncodeNeonMinMax(false, dt, dst, src1, src2)); |
+} |
+ |
+static Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst, |
+ QwNeonRegister src) { |
int vd, d; |
dst.split_code(&vd, &d); |
int vm, m; |
src.split_code(&vm, &m); |
- emit(0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 | 0x3 * B6 | |
- m * B5 | vm); |
+ int rsqrt = is_rsqrt ? 1 : 0; |
+ return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 | |
+ rsqrt * B7 | B6 | m * B5 | vm; |
} |
-void Assembler::vrecps(const QwNeonRegister dst, const QwNeonRegister src1, |
- const QwNeonRegister src2) { |
+void Assembler::vrecpe(const QwNeonRegister dst, const QwNeonRegister src) { |
DCHECK(IsEnabled(NEON)); |
- // Qd = vadd(Qn, Qm) SIMD reciprocal refinement step. |
- // Instruction details available in ARM DDI 0406C.b, A8-1026. |
+ // Qd = vrecpe(Qm) SIMD reciprocal estimate. |
+ // Instruction details available in ARM DDI 0406C.b, A8-1024. |
+ emit(EncodeNeonEstimateOp(false, dst, src)); |
+} |
+ |
+void Assembler::vrsqrte(const QwNeonRegister dst, const QwNeonRegister src) { |
+ DCHECK(IsEnabled(NEON)); |
+ // Qd = vrsqrte(Qm) SIMD reciprocal square root estimate. |
+ // Instruction details available in ARM DDI 0406C.b, A8-1038. |
+ emit(EncodeNeonEstimateOp(true, dst, src)); |
+} |
+ |
+static Instr EncodeNeonRefinementOp(bool is_rsqrt, QwNeonRegister dst, |
+ QwNeonRegister src1, QwNeonRegister src2) { |
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(0x1E4U * B23 | d * B22 | vn * B16 | vd * B12 | 0xF * B8 | n * B7 | B6 | |
- m * B5 | B4 | vm); |
+ int rsqrt = is_rsqrt ? 1 : 0; |
+ return 0x1E4U * B23 | d * B22 | rsqrt * B21 | vn * B16 | vd * B12 | 0xF * B8 | |
+ n * B7 | B6 | m * B5 | B4 | vm; |
+} |
+ |
+void Assembler::vrecps(const QwNeonRegister dst, const QwNeonRegister src1, |
+ const QwNeonRegister src2) { |
+ DCHECK(IsEnabled(NEON)); |
+ // Qd = vrecps(Qn, Qm) SIMD reciprocal refinement step. |
+ // Instruction details available in ARM DDI 0406C.b, A8-1026. |
+ emit(EncodeNeonRefinementOp(false, dst, src1, src2)); |
} |
void Assembler::vrsqrts(const QwNeonRegister dst, const QwNeonRegister src1, |
const QwNeonRegister src2) { |
DCHECK(IsEnabled(NEON)); |
- // Qd = vadd(Qn, Qm) SIMD reciprocal square root refinement step. |
+ // Qd = vrsqrts(Qn, Qm) SIMD reciprocal square root refinement step. |
// Instruction details available in ARM DDI 0406C.b, A8-1040. |
- 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(0x1E4U * B23 | d * B22 | B21 | vn * B16 | vd * B12 | 0xF * B8 | n * B7 | |
- B6 | m * B5 | B4 | vm); |
+ emit(EncodeNeonRefinementOp(true, dst, src1, src2)); |
} |
void Assembler::vtst(NeonSize size, QwNeonRegister dst, |