| OLD | NEW |
| 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
| 2 // All Rights Reserved. | 2 // All Rights Reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are met: |
| 7 // | 7 // |
| 8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
| 9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
| 10 // | 10 // |
| (...skipping 3860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3871 | 3871 |
| 3872 void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) { | 3872 void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) { |
| 3873 // Instruction details available in ARM DDI 0406C.b, A8.8.346. | 3873 // Instruction details available in ARM DDI 0406C.b, A8.8.346. |
| 3874 // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) | | 3874 // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) | |
| 3875 // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0) | 3875 // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0) |
| 3876 DCHECK(IsEnabled(NEON)); | 3876 DCHECK(IsEnabled(NEON)); |
| 3877 int vd, d; | 3877 int vd, d; |
| 3878 dst.split_code(&vd, &d); | 3878 dst.split_code(&vd, &d); |
| 3879 int vm, m; | 3879 int vm, m; |
| 3880 src.split_code(&vm, &m); | 3880 src.split_code(&vm, &m); |
| 3881 emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 | | 3881 int U = NeonU(dt); |
| 3882 (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm); | 3882 int imm3 = 1 << NeonSz(dt); |
| 3883 emit(0xFU * B28 | B25 | U * B24 | B23 | d * B22 | imm3 * B19 | vd * B12 | |
| 3884 0xA * B8 | m * B5 | B4 | vm); |
| 3883 } | 3885 } |
| 3884 | 3886 |
| 3885 static int EncodeScalar(NeonDataType dt, int index) { | 3887 static int EncodeScalar(NeonDataType dt, int index) { |
| 3886 int opc1_opc2 = 0; | 3888 int opc1_opc2 = 0; |
| 3887 DCHECK_LE(0, index); | 3889 DCHECK_LE(0, index); |
| 3888 switch (dt) { | 3890 switch (dt) { |
| 3889 case NeonS8: | 3891 case NeonS8: |
| 3890 case NeonU8: | 3892 case NeonU8: |
| 3891 DCHECK_GT(8, index); | 3893 DCHECK_GT(8, index); |
| 3892 opc1_opc2 = 0x8 | index; | 3894 opc1_opc2 = 0x8 | index; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3921 } | 3923 } |
| 3922 | 3924 |
| 3923 void Assembler::vmov(NeonDataType dt, Register dst, DwVfpRegister src, | 3925 void Assembler::vmov(NeonDataType dt, Register dst, DwVfpRegister src, |
| 3924 int index) { | 3926 int index) { |
| 3925 // Instruction details available in ARM DDI 0406C.b, A8.8.942. | 3927 // Instruction details available in ARM DDI 0406C.b, A8.8.942. |
| 3926 // vmov Arm scalar to core register. | 3928 // vmov Arm scalar to core register. |
| 3927 DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON)); | 3929 DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON)); |
| 3928 int vn, n; | 3930 int vn, n; |
| 3929 src.split_code(&vn, &n); | 3931 src.split_code(&vn, &n); |
| 3930 int opc1_opc2 = EncodeScalar(dt, index); | 3932 int opc1_opc2 = EncodeScalar(dt, index); |
| 3931 int u = (dt & NeonDataTypeUMask) != 0 ? 1 : 0; | 3933 int u = NeonU(dt); |
| 3932 emit(0xEEu * B24 | u * B23 | B20 | vn * B16 | dst.code() * B12 | 0xB * B8 | | 3934 emit(0xEEu * B24 | u * B23 | B20 | vn * B16 | dst.code() * B12 | 0xB * B8 | |
| 3933 n * B7 | B4 | opc1_opc2); | 3935 n * B7 | B4 | opc1_opc2); |
| 3934 } | 3936 } |
| 3935 | 3937 |
| 3936 void Assembler::vmov(const QwNeonRegister dst, const QwNeonRegister src) { | 3938 void Assembler::vmov(const QwNeonRegister dst, const QwNeonRegister src) { |
| 3937 // Instruction details available in ARM DDI 0406C.b, A8-938. | 3939 // Instruction details available in ARM DDI 0406C.b, A8-938. |
| 3938 // vmov is encoded as vorr. | 3940 // vmov is encoded as vorr. |
| 3939 vorr(dst, src, src); | 3941 vorr(dst, src, src); |
| 3940 } | 3942 } |
| 3941 | 3943 |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4202 } | 4204 } |
| 4203 | 4205 |
| 4204 void Assembler::vorr(QwNeonRegister dst, QwNeonRegister src1, | 4206 void Assembler::vorr(QwNeonRegister dst, QwNeonRegister src1, |
| 4205 QwNeonRegister src2) { | 4207 QwNeonRegister src2) { |
| 4206 // Qd = vorr(Qn, Qm) SIMD OR. | 4208 // Qd = vorr(Qn, Qm) SIMD OR. |
| 4207 // Instruction details available in ARM DDI 0406C.b, A8.8.976. | 4209 // Instruction details available in ARM DDI 0406C.b, A8.8.976. |
| 4208 DCHECK(IsEnabled(NEON)); | 4210 DCHECK(IsEnabled(NEON)); |
| 4209 emit(EncodeNeonBinaryBitwiseOp(VORR, dst, src1, src2)); | 4211 emit(EncodeNeonBinaryBitwiseOp(VORR, dst, src1, src2)); |
| 4210 } | 4212 } |
| 4211 | 4213 |
| 4212 void Assembler::vadd(QwNeonRegister dst, const QwNeonRegister src1, | 4214 enum FPBinOp { |
| 4213 const QwNeonRegister src2) { | 4215 VADDF, |
| 4214 DCHECK(IsEnabled(NEON)); | 4216 VSUBF, |
| 4215 // Qd = vadd(Qn, Qm) SIMD floating point addition. | 4217 VMULF, |
| 4216 // Instruction details available in ARM DDI 0406C.b, A8-830. | 4218 VMINF, |
| 4219 VMAXF, |
| 4220 VRECPS, |
| 4221 VRSQRTS, |
| 4222 VCEQF, |
| 4223 VCGEF, |
| 4224 VCGTF |
| 4225 }; |
| 4226 |
| 4227 static Instr EncodeNeonBinOp(FPBinOp op, QwNeonRegister dst, |
| 4228 QwNeonRegister src1, QwNeonRegister src2) { |
| 4229 int op_encoding = 0; |
| 4230 switch (op) { |
| 4231 case VADDF: |
| 4232 op_encoding = 0xD * B8; |
| 4233 break; |
| 4234 case VSUBF: |
| 4235 op_encoding = B21 | 0xD * B8; |
| 4236 break; |
| 4237 case VMULF: |
| 4238 op_encoding = B24 | 0xD * B8 | B4; |
| 4239 break; |
| 4240 case VMINF: |
| 4241 op_encoding = B21 | 0xF * B8; |
| 4242 break; |
| 4243 case VMAXF: |
| 4244 op_encoding = 0xF * B8; |
| 4245 break; |
| 4246 case VRECPS: |
| 4247 op_encoding = 0xF * B8 | B4; |
| 4248 break; |
| 4249 case VRSQRTS: |
| 4250 op_encoding = B21 | 0xF * B8 | B4; |
| 4251 break; |
| 4252 case VCEQF: |
| 4253 op_encoding = 0xE * B8; |
| 4254 break; |
| 4255 case VCGEF: |
| 4256 op_encoding = B24 | 0xE * B8; |
| 4257 break; |
| 4258 case VCGTF: |
| 4259 op_encoding = B24 | B21 | 0xE * B8; |
| 4260 break; |
| 4261 default: |
| 4262 UNREACHABLE(); |
| 4263 break; |
| 4264 } |
| 4217 int vd, d; | 4265 int vd, d; |
| 4218 dst.split_code(&vd, &d); | 4266 dst.split_code(&vd, &d); |
| 4219 int vn, n; | 4267 int vn, n; |
| 4220 src1.split_code(&vn, &n); | 4268 src1.split_code(&vn, &n); |
| 4221 int vm, m; | 4269 int vm, m; |
| 4222 src2.split_code(&vm, &m); | 4270 src2.split_code(&vm, &m); |
| 4223 emit(0x1E4U * B23 | d * B22 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 | B6 | | 4271 return 0x1E4U * B23 | d * B22 | vn * B16 | vd * B12 | n * B7 | B6 | m * B5 | |
| 4224 m * B5 | vm); | 4272 vm | op_encoding; |
| 4225 } | 4273 } |
| 4226 | 4274 |
| 4227 void Assembler::vadd(NeonSize size, QwNeonRegister dst, | 4275 enum IntegerBinOp { VADD, VSUB, VMUL, VMIN, VMAX, VTST, VCEQ, VCGE, VCGT }; |
| 4228 const QwNeonRegister src1, const QwNeonRegister src2) { | 4276 |
| 4229 DCHECK(IsEnabled(NEON)); | 4277 static Instr EncodeNeonBinOp(IntegerBinOp op, NeonDataType dt, |
| 4230 // Qd = vadd(Qn, Qm) SIMD integer addition. | 4278 const QwNeonRegister dst, |
| 4231 // Instruction details available in ARM DDI 0406C.b, A8-828. | 4279 const QwNeonRegister src1, |
| 4280 const QwNeonRegister src2) { |
| 4281 int op_encoding = 0; |
| 4282 switch (op) { |
| 4283 case VADD: |
| 4284 op_encoding = 0x8 * B8; |
| 4285 break; |
| 4286 case VSUB: |
| 4287 op_encoding = B24 | 0x8 * B8; |
| 4288 break; |
| 4289 case VMUL: |
| 4290 op_encoding = 0x9 * B8 | B4; |
| 4291 break; |
| 4292 case VMIN: |
| 4293 op_encoding = 0x6 * B8 | B4; |
| 4294 break; |
| 4295 case VMAX: |
| 4296 op_encoding = 0x6 * B8; |
| 4297 break; |
| 4298 case VTST: |
| 4299 op_encoding = 0x8 * B8 | B4; |
| 4300 break; |
| 4301 case VCEQ: |
| 4302 op_encoding = B24 | 0x8 * B8 | B4; |
| 4303 break; |
| 4304 case VCGE: |
| 4305 op_encoding = 0x3 * B8 | B4; |
| 4306 break; |
| 4307 case VCGT: |
| 4308 op_encoding = 0x3 * B8; |
| 4309 break; |
| 4310 default: |
| 4311 UNREACHABLE(); |
| 4312 break; |
| 4313 } |
| 4232 int vd, d; | 4314 int vd, d; |
| 4233 dst.split_code(&vd, &d); | 4315 dst.split_code(&vd, &d); |
| 4234 int vn, n; | 4316 int vn, n; |
| 4235 src1.split_code(&vn, &n); | 4317 src1.split_code(&vn, &n); |
| 4236 int vm, m; | 4318 int vm, m; |
| 4237 src2.split_code(&vm, &m); | 4319 src2.split_code(&vm, &m); |
| 4238 int sz = static_cast<int>(size); | 4320 int size = NeonSz(dt); |
| 4239 emit(0x1E4U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x8 * B8 | | 4321 int u = NeonU(dt); |
| 4240 n * B7 | B6 | m * B5 | vm); | 4322 return 0x1E4U * B23 | u * B24 | d * B22 | size * B20 | vn * B16 | vd * B12 | |
| 4323 n * B7 | B6 | m * B5 | vm | op_encoding; |
| 4241 } | 4324 } |
| 4242 | 4325 |
| 4243 void Assembler::vsub(QwNeonRegister dst, const QwNeonRegister src1, | 4326 static Instr EncodeNeonBinOp(IntegerBinOp op, NeonSize size, |
| 4244 const QwNeonRegister src2) { | 4327 const QwNeonRegister dst, |
| 4328 const QwNeonRegister src1, |
| 4329 const QwNeonRegister src2) { |
| 4330 // Map NeonSize values to the signed values in NeonDataType, so the U bit |
| 4331 // will be 0. |
| 4332 return EncodeNeonBinOp(op, static_cast<NeonDataType>(size), dst, src1, src2); |
| 4333 } |
| 4334 |
| 4335 void Assembler::vadd(QwNeonRegister dst, QwNeonRegister src1, |
| 4336 QwNeonRegister src2) { |
| 4337 DCHECK(IsEnabled(NEON)); |
| 4338 // Qd = vadd(Qn, Qm) SIMD floating point addition. |
| 4339 // Instruction details available in ARM DDI 0406C.b, A8-830. |
| 4340 emit(EncodeNeonBinOp(VADDF, dst, src1, src2)); |
| 4341 } |
| 4342 |
| 4343 void Assembler::vadd(NeonSize size, QwNeonRegister dst, QwNeonRegister src1, |
| 4344 QwNeonRegister src2) { |
| 4345 DCHECK(IsEnabled(NEON)); |
| 4346 // Qd = vadd(Qn, Qm) SIMD integer addition. |
| 4347 // Instruction details available in ARM DDI 0406C.b, A8-828. |
| 4348 emit(EncodeNeonBinOp(VADD, size, dst, src1, src2)); |
| 4349 } |
| 4350 |
| 4351 void Assembler::vsub(QwNeonRegister dst, QwNeonRegister src1, |
| 4352 QwNeonRegister src2) { |
| 4245 DCHECK(IsEnabled(NEON)); | 4353 DCHECK(IsEnabled(NEON)); |
| 4246 // Qd = vsub(Qn, Qm) SIMD floating point subtraction. | 4354 // Qd = vsub(Qn, Qm) SIMD floating point subtraction. |
| 4247 // Instruction details available in ARM DDI 0406C.b, A8-1086. | 4355 // Instruction details available in ARM DDI 0406C.b, A8-1086. |
| 4248 int vd, d; | 4356 emit(EncodeNeonBinOp(VSUBF, dst, src1, src2)); |
| 4249 dst.split_code(&vd, &d); | |
| 4250 int vn, n; | |
| 4251 src1.split_code(&vn, &n); | |
| 4252 int vm, m; | |
| 4253 src2.split_code(&vm, &m); | |
| 4254 emit(0x1E4U * B23 | d * B22 | B21 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 | | |
| 4255 B6 | m * B5 | vm); | |
| 4256 } | 4357 } |
| 4257 | 4358 |
| 4258 void Assembler::vsub(NeonSize size, QwNeonRegister dst, | 4359 void Assembler::vsub(NeonSize size, QwNeonRegister dst, QwNeonRegister src1, |
| 4259 const QwNeonRegister src1, const QwNeonRegister src2) { | 4360 QwNeonRegister src2) { |
| 4260 DCHECK(IsEnabled(NEON)); | 4361 DCHECK(IsEnabled(NEON)); |
| 4261 // Qd = vsub(Qn, Qm) SIMD integer subtraction. | 4362 // Qd = vsub(Qn, Qm) SIMD integer subtraction. |
| 4262 // Instruction details available in ARM DDI 0406C.b, A8-1084. | 4363 // Instruction details available in ARM DDI 0406C.b, A8-1084. |
| 4263 int vd, d; | 4364 emit(EncodeNeonBinOp(VSUB, size, dst, src1, src2)); |
| 4264 dst.split_code(&vd, &d); | |
| 4265 int vn, n; | |
| 4266 src1.split_code(&vn, &n); | |
| 4267 int vm, m; | |
| 4268 src2.split_code(&vm, &m); | |
| 4269 int sz = static_cast<int>(size); | |
| 4270 emit(0x1E6U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x8 * B8 | | |
| 4271 n * B7 | B6 | m * B5 | vm); | |
| 4272 } | 4365 } |
| 4273 | 4366 |
| 4274 void Assembler::vmul(QwNeonRegister dst, const QwNeonRegister src1, | 4367 void Assembler::vmul(QwNeonRegister dst, QwNeonRegister src1, |
| 4275 const QwNeonRegister src2) { | 4368 QwNeonRegister src2) { |
| 4276 DCHECK(IsEnabled(NEON)); | 4369 DCHECK(IsEnabled(NEON)); |
| 4277 // Qd = vadd(Qn, Qm) SIMD floating point multiply. | 4370 // Qd = vadd(Qn, Qm) SIMD floating point multiply. |
| 4278 // Instruction details available in ARM DDI 0406C.b, A8-958. | 4371 // Instruction details available in ARM DDI 0406C.b, A8-958. |
| 4279 int vd, d; | 4372 emit(EncodeNeonBinOp(VMULF, dst, src1, src2)); |
| 4280 dst.split_code(&vd, &d); | |
| 4281 int vn, n; | |
| 4282 src1.split_code(&vn, &n); | |
| 4283 int vm, m; | |
| 4284 src2.split_code(&vm, &m); | |
| 4285 emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 | B6 | | |
| 4286 m * B5 | B4 | vm); | |
| 4287 } | 4373 } |
| 4288 | 4374 |
| 4289 void Assembler::vmul(NeonSize size, QwNeonRegister dst, | 4375 void Assembler::vmul(NeonSize size, QwNeonRegister dst, |
| 4290 const QwNeonRegister src1, const QwNeonRegister src2) { | 4376 const QwNeonRegister src1, const QwNeonRegister src2) { |
| 4291 DCHECK(IsEnabled(NEON)); | 4377 DCHECK(IsEnabled(NEON)); |
| 4292 // Qd = vadd(Qn, Qm) SIMD integer multiply. | 4378 // Qd = vadd(Qn, Qm) SIMD integer multiply. |
| 4293 // Instruction details available in ARM DDI 0406C.b, A8-960. | 4379 // Instruction details available in ARM DDI 0406C.b, A8-960. |
| 4294 int vd, d; | 4380 emit(EncodeNeonBinOp(VMUL, size, dst, src1, src2)); |
| 4295 dst.split_code(&vd, &d); | |
| 4296 int vn, n; | |
| 4297 src1.split_code(&vn, &n); | |
| 4298 int vm, m; | |
| 4299 src2.split_code(&vm, &m); | |
| 4300 int sz = static_cast<int>(size); | |
| 4301 emit(0x1E4U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x9 * B8 | | |
| 4302 n * B7 | B6 | m * B5 | B4 | vm); | |
| 4303 } | |
| 4304 | |
| 4305 static Instr EncodeNeonMinMax(bool is_min, QwNeonRegister dst, | |
| 4306 QwNeonRegister src1, QwNeonRegister src2) { | |
| 4307 int vd, d; | |
| 4308 dst.split_code(&vd, &d); | |
| 4309 int vn, n; | |
| 4310 src1.split_code(&vn, &n); | |
| 4311 int vm, m; | |
| 4312 src2.split_code(&vm, &m); | |
| 4313 int min = is_min ? 1 : 0; | |
| 4314 return 0x1E4U * B23 | d * B22 | min * B21 | vn * B16 | vd * B12 | 0xF * B8 | | |
| 4315 n * B7 | B6 | m * B5 | vm; | |
| 4316 } | |
| 4317 | |
| 4318 static Instr EncodeNeonMinMax(bool is_min, NeonDataType dt, QwNeonRegister dst, | |
| 4319 QwNeonRegister src1, QwNeonRegister src2) { | |
| 4320 int vd, d; | |
| 4321 dst.split_code(&vd, &d); | |
| 4322 int vn, n; | |
| 4323 src1.split_code(&vn, &n); | |
| 4324 int vm, m; | |
| 4325 src2.split_code(&vm, &m); | |
| 4326 int min = is_min ? 1 : 0; | |
| 4327 int size = (dt & NeonDataTypeSizeMask) / 2; | |
| 4328 int U = dt & NeonDataTypeUMask; | |
| 4329 return 0x1E4U * B23 | U | d * B22 | size * B20 | vn * B16 | vd * B12 | | |
| 4330 0x6 * B8 | B6 | m * B5 | min * B4 | vm; | |
| 4331 } | 4381 } |
| 4332 | 4382 |
| 4333 void Assembler::vmin(const QwNeonRegister dst, const QwNeonRegister src1, | 4383 void Assembler::vmin(const QwNeonRegister dst, const QwNeonRegister src1, |
| 4334 const QwNeonRegister src2) { | 4384 const QwNeonRegister src2) { |
| 4335 DCHECK(IsEnabled(NEON)); | 4385 DCHECK(IsEnabled(NEON)); |
| 4336 // Qd = vmin(Qn, Qm) SIMD floating point MIN. | 4386 // Qd = vmin(Qn, Qm) SIMD floating point MIN. |
| 4337 // Instruction details available in ARM DDI 0406C.b, A8-928. | 4387 // Instruction details available in ARM DDI 0406C.b, A8-928. |
| 4338 emit(EncodeNeonMinMax(true, dst, src1, src2)); | 4388 emit(EncodeNeonBinOp(VMINF, dst, src1, src2)); |
| 4339 } | 4389 } |
| 4340 | 4390 |
| 4341 void Assembler::vmin(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, | 4391 void Assembler::vmin(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, |
| 4342 QwNeonRegister src2) { | 4392 QwNeonRegister src2) { |
| 4343 DCHECK(IsEnabled(NEON)); | 4393 DCHECK(IsEnabled(NEON)); |
| 4344 // Qd = vmin(Qn, Qm) SIMD integer MIN. | 4394 // Qd = vmin(Qn, Qm) SIMD integer MIN. |
| 4345 // Instruction details available in ARM DDI 0406C.b, A8-926. | 4395 // Instruction details available in ARM DDI 0406C.b, A8-926. |
| 4346 emit(EncodeNeonMinMax(true, dt, dst, src1, src2)); | 4396 emit(EncodeNeonBinOp(VMIN, dt, dst, src1, src2)); |
| 4347 } | 4397 } |
| 4348 | 4398 |
| 4349 void Assembler::vmax(QwNeonRegister dst, QwNeonRegister src1, | 4399 void Assembler::vmax(QwNeonRegister dst, QwNeonRegister src1, |
| 4350 QwNeonRegister src2) { | 4400 QwNeonRegister src2) { |
| 4351 DCHECK(IsEnabled(NEON)); | 4401 DCHECK(IsEnabled(NEON)); |
| 4352 // Qd = vmax(Qn, Qm) SIMD floating point MAX. | 4402 // Qd = vmax(Qn, Qm) SIMD floating point MAX. |
| 4353 // Instruction details available in ARM DDI 0406C.b, A8-928. | 4403 // Instruction details available in ARM DDI 0406C.b, A8-928. |
| 4354 emit(EncodeNeonMinMax(false, dst, src1, src2)); | 4404 emit(EncodeNeonBinOp(VMAXF, dst, src1, src2)); |
| 4355 } | 4405 } |
| 4356 | 4406 |
| 4357 void Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, | 4407 void Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, |
| 4358 QwNeonRegister src2) { | 4408 QwNeonRegister src2) { |
| 4359 DCHECK(IsEnabled(NEON)); | 4409 DCHECK(IsEnabled(NEON)); |
| 4360 // Qd = vmax(Qn, Qm) SIMD integer MAX. | 4410 // Qd = vmax(Qn, Qm) SIMD integer MAX. |
| 4361 // Instruction details available in ARM DDI 0406C.b, A8-926. | 4411 // Instruction details available in ARM DDI 0406C.b, A8-926. |
| 4362 emit(EncodeNeonMinMax(false, dt, dst, src1, src2)); | 4412 emit(EncodeNeonBinOp(VMAX, dt, dst, src1, src2)); |
| 4363 } | 4413 } |
| 4364 | 4414 |
| 4365 static Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst, | 4415 static Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst, |
| 4366 QwNeonRegister src) { | 4416 QwNeonRegister src) { |
| 4367 int vd, d; | 4417 int vd, d; |
| 4368 dst.split_code(&vd, &d); | 4418 dst.split_code(&vd, &d); |
| 4369 int vm, m; | 4419 int vm, m; |
| 4370 src.split_code(&vm, &m); | 4420 src.split_code(&vm, &m); |
| 4371 int rsqrt = is_rsqrt ? 1 : 0; | 4421 int rsqrt = is_rsqrt ? 1 : 0; |
| 4372 return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 | | 4422 return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 | |
| 4373 rsqrt * B7 | B6 | m * B5 | vm; | 4423 rsqrt * B7 | B6 | m * B5 | vm; |
| 4374 } | 4424 } |
| 4375 | 4425 |
| 4376 void Assembler::vrecpe(const QwNeonRegister dst, const QwNeonRegister src) { | 4426 void Assembler::vrecpe(QwNeonRegister dst, QwNeonRegister src) { |
| 4377 DCHECK(IsEnabled(NEON)); | 4427 DCHECK(IsEnabled(NEON)); |
| 4378 // Qd = vrecpe(Qm) SIMD reciprocal estimate. | 4428 // Qd = vrecpe(Qm) SIMD reciprocal estimate. |
| 4379 // Instruction details available in ARM DDI 0406C.b, A8-1024. | 4429 // Instruction details available in ARM DDI 0406C.b, A8-1024. |
| 4380 emit(EncodeNeonEstimateOp(false, dst, src)); | 4430 emit(EncodeNeonEstimateOp(false, dst, src)); |
| 4381 } | 4431 } |
| 4382 | 4432 |
| 4383 void Assembler::vrsqrte(const QwNeonRegister dst, const QwNeonRegister src) { | 4433 void Assembler::vrsqrte(QwNeonRegister dst, QwNeonRegister src) { |
| 4384 DCHECK(IsEnabled(NEON)); | 4434 DCHECK(IsEnabled(NEON)); |
| 4385 // Qd = vrsqrte(Qm) SIMD reciprocal square root estimate. | 4435 // Qd = vrsqrte(Qm) SIMD reciprocal square root estimate. |
| 4386 // Instruction details available in ARM DDI 0406C.b, A8-1038. | 4436 // Instruction details available in ARM DDI 0406C.b, A8-1038. |
| 4387 emit(EncodeNeonEstimateOp(true, dst, src)); | 4437 emit(EncodeNeonEstimateOp(true, dst, src)); |
| 4388 } | 4438 } |
| 4389 | 4439 |
| 4390 static Instr EncodeNeonRefinementOp(bool is_rsqrt, QwNeonRegister dst, | 4440 void Assembler::vrecps(QwNeonRegister dst, QwNeonRegister src1, |
| 4391 QwNeonRegister src1, QwNeonRegister src2) { | 4441 QwNeonRegister src2) { |
| 4392 int vd, d; | |
| 4393 dst.split_code(&vd, &d); | |
| 4394 int vn, n; | |
| 4395 src1.split_code(&vn, &n); | |
| 4396 int vm, m; | |
| 4397 src2.split_code(&vm, &m); | |
| 4398 int rsqrt = is_rsqrt ? 1 : 0; | |
| 4399 return 0x1E4U * B23 | d * B22 | rsqrt * B21 | vn * B16 | vd * B12 | 0xF * B8 | | |
| 4400 n * B7 | B6 | m * B5 | B4 | vm; | |
| 4401 } | |
| 4402 | |
| 4403 void Assembler::vrecps(const QwNeonRegister dst, const QwNeonRegister src1, | |
| 4404 const QwNeonRegister src2) { | |
| 4405 DCHECK(IsEnabled(NEON)); | 4442 DCHECK(IsEnabled(NEON)); |
| 4406 // Qd = vrecps(Qn, Qm) SIMD reciprocal refinement step. | 4443 // Qd = vrecps(Qn, Qm) SIMD reciprocal refinement step. |
| 4407 // Instruction details available in ARM DDI 0406C.b, A8-1026. | 4444 // Instruction details available in ARM DDI 0406C.b, A8-1026. |
| 4408 emit(EncodeNeonRefinementOp(false, dst, src1, src2)); | 4445 emit(EncodeNeonBinOp(VRECPS, dst, src1, src2)); |
| 4409 } | 4446 } |
| 4410 | 4447 |
| 4411 void Assembler::vrsqrts(const QwNeonRegister dst, const QwNeonRegister src1, | 4448 void Assembler::vrsqrts(QwNeonRegister dst, QwNeonRegister src1, |
| 4412 const QwNeonRegister src2) { | 4449 QwNeonRegister src2) { |
| 4413 DCHECK(IsEnabled(NEON)); | 4450 DCHECK(IsEnabled(NEON)); |
| 4414 // Qd = vrsqrts(Qn, Qm) SIMD reciprocal square root refinement step. | 4451 // Qd = vrsqrts(Qn, Qm) SIMD reciprocal square root refinement step. |
| 4415 // Instruction details available in ARM DDI 0406C.b, A8-1040. | 4452 // Instruction details available in ARM DDI 0406C.b, A8-1040. |
| 4416 emit(EncodeNeonRefinementOp(true, dst, src1, src2)); | 4453 emit(EncodeNeonBinOp(VRSQRTS, dst, src1, src2)); |
| 4417 } | 4454 } |
| 4418 | 4455 |
| 4419 void Assembler::vtst(NeonSize size, QwNeonRegister dst, | 4456 void Assembler::vtst(NeonSize size, QwNeonRegister dst, QwNeonRegister src1, |
| 4420 const QwNeonRegister src1, const QwNeonRegister src2) { | 4457 QwNeonRegister src2) { |
| 4421 DCHECK(IsEnabled(NEON)); | 4458 DCHECK(IsEnabled(NEON)); |
| 4422 // Qd = vtst(Qn, Qm) SIMD test integer operands. | 4459 // Qd = vtst(Qn, Qm) SIMD test integer operands. |
| 4423 // Instruction details available in ARM DDI 0406C.b, A8-1098. | 4460 // Instruction details available in ARM DDI 0406C.b, A8-1098. |
| 4424 int vd, d; | 4461 emit(EncodeNeonBinOp(VTST, size, dst, src1, src2)); |
| 4425 dst.split_code(&vd, &d); | |
| 4426 int vn, n; | |
| 4427 src1.split_code(&vn, &n); | |
| 4428 int vm, m; | |
| 4429 src2.split_code(&vm, &m); | |
| 4430 int sz = static_cast<int>(size); | |
| 4431 emit(0x1E4U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x8 * B8 | | |
| 4432 n * B7 | B6 | m * B5 | B4 | vm); | |
| 4433 } | 4462 } |
| 4434 | 4463 |
| 4435 void Assembler::vceq(const QwNeonRegister dst, const QwNeonRegister src1, | 4464 void Assembler::vceq(QwNeonRegister dst, QwNeonRegister src1, |
| 4436 const QwNeonRegister src2) { | 4465 QwNeonRegister src2) { |
| 4437 DCHECK(IsEnabled(NEON)); | 4466 DCHECK(IsEnabled(NEON)); |
| 4438 // Qd = vceq(Qn, Qm) SIMD floating point compare equal. | 4467 // Qd = vceq(Qn, Qm) SIMD floating point compare equal. |
| 4439 // Instruction details available in ARM DDI 0406C.b, A8-844. | 4468 // Instruction details available in ARM DDI 0406C.b, A8-844. |
| 4440 int vd, d; | 4469 emit(EncodeNeonBinOp(VCEQF, dst, src1, src2)); |
| 4441 dst.split_code(&vd, &d); | |
| 4442 int vn, n; | |
| 4443 src1.split_code(&vn, &n); | |
| 4444 int vm, m; | |
| 4445 src2.split_code(&vm, &m); | |
| 4446 emit(0x1E4U * B23 | d * B22 | vn * B16 | vd * B12 | 0xe * B8 | n * B7 | B6 | | |
| 4447 m * B5 | vm); | |
| 4448 } | 4470 } |
| 4449 | 4471 |
| 4450 void Assembler::vceq(NeonSize size, QwNeonRegister dst, | 4472 void Assembler::vceq(NeonSize size, QwNeonRegister dst, QwNeonRegister src1, |
| 4451 const QwNeonRegister src1, const QwNeonRegister src2) { | 4473 QwNeonRegister src2) { |
| 4452 DCHECK(IsEnabled(NEON)); | 4474 DCHECK(IsEnabled(NEON)); |
| 4453 // Qd = vceq(Qn, Qm) SIMD integer compare equal. | 4475 // Qd = vceq(Qn, Qm) SIMD integer compare equal. |
| 4454 // Instruction details available in ARM DDI 0406C.b, A8-844. | 4476 // Instruction details available in ARM DDI 0406C.b, A8-844. |
| 4455 int vd, d; | 4477 emit(EncodeNeonBinOp(VCEQ, size, dst, src1, src2)); |
| 4456 dst.split_code(&vd, &d); | |
| 4457 int vn, n; | |
| 4458 src1.split_code(&vn, &n); | |
| 4459 int vm, m; | |
| 4460 src2.split_code(&vm, &m); | |
| 4461 int sz = static_cast<int>(size); | |
| 4462 emit(0x1E6U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x8 * B8 | | |
| 4463 n * B7 | B6 | m * B5 | B4 | vm); | |
| 4464 } | 4478 } |
| 4465 | 4479 |
| 4466 static Instr EncodeNeonCompareOp(const QwNeonRegister dst, | 4480 void Assembler::vcge(QwNeonRegister dst, QwNeonRegister src1, |
| 4467 const QwNeonRegister src1, | 4481 QwNeonRegister src2) { |
| 4468 const QwNeonRegister src2, Condition cond) { | |
| 4469 DCHECK(cond == ge || cond == gt); | |
| 4470 int vd, d; | |
| 4471 dst.split_code(&vd, &d); | |
| 4472 int vn, n; | |
| 4473 src1.split_code(&vn, &n); | |
| 4474 int vm, m; | |
| 4475 src2.split_code(&vm, &m); | |
| 4476 int is_gt = (cond == gt) ? 1 : 0; | |
| 4477 return 0x1E6U * B23 | d * B22 | is_gt * B21 | vn * B16 | vd * B12 | 0xe * B8 | | |
| 4478 n * B7 | B6 | m * B5 | vm; | |
| 4479 } | |
| 4480 | |
| 4481 static Instr EncodeNeonCompareOp(NeonDataType dt, const QwNeonRegister dst, | |
| 4482 const QwNeonRegister src1, | |
| 4483 const QwNeonRegister src2, Condition cond) { | |
| 4484 DCHECK(cond == ge || cond == gt); | |
| 4485 int vd, d; | |
| 4486 dst.split_code(&vd, &d); | |
| 4487 int vn, n; | |
| 4488 src1.split_code(&vn, &n); | |
| 4489 int vm, m; | |
| 4490 src2.split_code(&vm, &m); | |
| 4491 int size = (dt & NeonDataTypeSizeMask) / 2; | |
| 4492 int U = dt & NeonDataTypeUMask; | |
| 4493 int is_ge = (cond == ge) ? 1 : 0; | |
| 4494 return 0x1E4U * B23 | U | d * B22 | size * B20 | vn * B16 | vd * B12 | | |
| 4495 0x3 * B8 | n * B7 | B6 | m * B5 | is_ge * B4 | vm; | |
| 4496 } | |
| 4497 | |
| 4498 void Assembler::vcge(const QwNeonRegister dst, const QwNeonRegister src1, | |
| 4499 const QwNeonRegister src2) { | |
| 4500 DCHECK(IsEnabled(NEON)); | 4482 DCHECK(IsEnabled(NEON)); |
| 4501 // Qd = vcge(Qn, Qm) SIMD floating point compare greater or equal. | 4483 // Qd = vcge(Qn, Qm) SIMD floating point compare greater or equal. |
| 4502 // Instruction details available in ARM DDI 0406C.b, A8-848. | 4484 // Instruction details available in ARM DDI 0406C.b, A8-848. |
| 4503 emit(EncodeNeonCompareOp(dst, src1, src2, ge)); | 4485 emit(EncodeNeonBinOp(VCGEF, dst, src1, src2)); |
| 4504 } | 4486 } |
| 4505 | 4487 |
| 4506 void Assembler::vcge(NeonDataType dt, QwNeonRegister dst, | 4488 void Assembler::vcge(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, |
| 4507 const QwNeonRegister src1, const QwNeonRegister src2) { | 4489 QwNeonRegister src2) { |
| 4508 DCHECK(IsEnabled(NEON)); | 4490 DCHECK(IsEnabled(NEON)); |
| 4509 // Qd = vcge(Qn, Qm) SIMD integer compare greater or equal. | 4491 // Qd = vcge(Qn, Qm) SIMD integer compare greater or equal. |
| 4510 // Instruction details available in ARM DDI 0406C.b, A8-848. | 4492 // Instruction details available in ARM DDI 0406C.b, A8-848. |
| 4511 emit(EncodeNeonCompareOp(dt, dst, src1, src2, ge)); | 4493 emit(EncodeNeonBinOp(VCGE, dt, dst, src1, src2)); |
| 4512 } | 4494 } |
| 4513 | 4495 |
| 4514 void Assembler::vcgt(const QwNeonRegister dst, const QwNeonRegister src1, | 4496 void Assembler::vcgt(QwNeonRegister dst, QwNeonRegister src1, |
| 4515 const QwNeonRegister src2) { | 4497 QwNeonRegister src2) { |
| 4516 DCHECK(IsEnabled(NEON)); | 4498 DCHECK(IsEnabled(NEON)); |
| 4517 // Qd = vcgt(Qn, Qm) SIMD floating point compare greater than. | 4499 // Qd = vcgt(Qn, Qm) SIMD floating point compare greater than. |
| 4518 // Instruction details available in ARM DDI 0406C.b, A8-852. | 4500 // Instruction details available in ARM DDI 0406C.b, A8-852. |
| 4519 emit(EncodeNeonCompareOp(dst, src1, src2, gt)); | 4501 emit(EncodeNeonBinOp(VCGTF, dst, src1, src2)); |
| 4520 } | 4502 } |
| 4521 | 4503 |
| 4522 void Assembler::vcgt(NeonDataType dt, QwNeonRegister dst, | 4504 void Assembler::vcgt(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, |
| 4523 const QwNeonRegister src1, const QwNeonRegister src2) { | 4505 QwNeonRegister src2) { |
| 4524 DCHECK(IsEnabled(NEON)); | 4506 DCHECK(IsEnabled(NEON)); |
| 4525 // Qd = vcgt(Qn, Qm) SIMD integer compare greater than. | 4507 // Qd = vcgt(Qn, Qm) SIMD integer compare greater than. |
| 4526 // Instruction details available in ARM DDI 0406C.b, A8-852. | 4508 // Instruction details available in ARM DDI 0406C.b, A8-852. |
| 4527 emit(EncodeNeonCompareOp(dt, dst, src1, src2, gt)); | 4509 emit(EncodeNeonBinOp(VCGT, dt, dst, src1, src2)); |
| 4528 } | 4510 } |
| 4529 | 4511 |
| 4530 void Assembler::vext(QwNeonRegister dst, const QwNeonRegister src1, | 4512 void Assembler::vext(QwNeonRegister dst, const QwNeonRegister src1, |
| 4531 const QwNeonRegister src2, int bytes) { | 4513 const QwNeonRegister src2, int bytes) { |
| 4532 DCHECK(IsEnabled(NEON)); | 4514 DCHECK(IsEnabled(NEON)); |
| 4533 // Qd = vext(Qn, Qm) SIMD byte extract. | 4515 // Qd = vext(Qn, Qm) SIMD byte extract. |
| 4534 // Instruction details available in ARM DDI 0406C.b, A8-890. | 4516 // Instruction details available in ARM DDI 0406C.b, A8-890. |
| 4535 int vd, d; | 4517 int vd, d; |
| 4536 dst.split_code(&vd, &d); | 4518 dst.split_code(&vd, &d); |
| 4537 int vn, n; | 4519 int vn, n; |
| (...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5167 DCHECK(is_uint12(offset)); | 5149 DCHECK(is_uint12(offset)); |
| 5168 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); | 5150 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); |
| 5169 } | 5151 } |
| 5170 } | 5152 } |
| 5171 | 5153 |
| 5172 | 5154 |
| 5173 } // namespace internal | 5155 } // namespace internal |
| 5174 } // namespace v8 | 5156 } // namespace v8 |
| 5175 | 5157 |
| 5176 #endif // V8_TARGET_ARCH_ARM | 5158 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |