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 |