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 3892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3903 UNREACHABLE(); | 3903 UNREACHABLE(); |
3904 break; | 3904 break; |
3905 } | 3905 } |
3906 int vd, d; | 3906 int vd, d; |
3907 dst.split_code(&vd, &d); | 3907 dst.split_code(&vd, &d); |
3908 | 3908 |
3909 emit(al | 0x1D * B23 | B * B22 | B21 | vd * B16 | src.code() * B12 | | 3909 emit(al | 0x1D * B23 | B * B22 | B21 | vd * B16 | src.code() * B12 | |
3910 0xB * B8 | d * B7 | E * B5 | B4); | 3910 0xB * B8 | d * B7 | E * B5 | B4); |
3911 } | 3911 } |
3912 | 3912 |
3913 void Assembler::vdup(QwNeonRegister dst, SwVfpRegister src) { | 3913 enum NeonRegType { NEON_D, NEON_Q }; |
| 3914 |
| 3915 void NeonSplitCode(NeonRegType type, int code, int* vm, int* m, int* encoding) { |
| 3916 if (type == NEON_D) { |
| 3917 DwVfpRegister::split_code(code, vm, m); |
| 3918 } else { |
| 3919 DCHECK_EQ(type, NEON_Q); |
| 3920 QwNeonRegister::split_code(code, vm, m); |
| 3921 *encoding |= B6; |
| 3922 } |
| 3923 } |
| 3924 |
| 3925 static Instr EncodeNeonDupOp(NeonSize size, NeonRegType reg_type, int dst_code, |
| 3926 DwVfpRegister src, int index) { |
| 3927 DCHECK_NE(Neon64, size); |
| 3928 int sz = static_cast<int>(size); |
| 3929 DCHECK_LE(0, index); |
| 3930 DCHECK_GT(kSimd128Size / (1 << sz), index); |
| 3931 int imm4 = (1 << sz) | ((index << (sz + 1)) & 0xF); |
| 3932 int qbit = 0; |
| 3933 int vd, d; |
| 3934 NeonSplitCode(reg_type, dst_code, &vd, &d, &qbit); |
| 3935 int vm, m; |
| 3936 src.split_code(&vm, &m); |
| 3937 |
| 3938 return 0x1E7U * B23 | d * B22 | 0x3 * B20 | imm4 * B16 | vd * B12 | |
| 3939 0x18 * B7 | qbit | m * B5 | vm; |
| 3940 } |
| 3941 |
| 3942 void Assembler::vdup(NeonSize size, DwVfpRegister dst, DwVfpRegister src, |
| 3943 int index) { |
3914 DCHECK(IsEnabled(NEON)); | 3944 DCHECK(IsEnabled(NEON)); |
3915 // Instruction details available in ARM DDI 0406C.b, A8-884. | 3945 // Instruction details available in ARM DDI 0406C.b, A8-884. |
3916 int index = src.code() & 1; | 3946 emit(EncodeNeonDupOp(size, NEON_D, dst.code(), src, index)); |
3917 int d_reg = src.code() / 2; | 3947 } |
3918 int imm4 = 4 | index << 3; // esize = 32, index in bit 3. | |
3919 int vd, d; | |
3920 dst.split_code(&vd, &d); | |
3921 int vm, m; | |
3922 DwVfpRegister::from_code(d_reg).split_code(&vm, &m); | |
3923 | 3948 |
3924 emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | imm4 * B16 | vd * B12 | 0x18 * B7 | | 3949 void Assembler::vdup(NeonSize size, QwNeonRegister dst, DwVfpRegister src, |
3925 B6 | m * B5 | vm); | 3950 int index) { |
| 3951 // Instruction details available in ARM DDI 0406C.b, A8-884. |
| 3952 DCHECK(IsEnabled(NEON)); |
| 3953 emit(EncodeNeonDupOp(size, NEON_Q, dst.code(), src, index)); |
3926 } | 3954 } |
3927 | 3955 |
3928 // Encode NEON vcvt.src_type.dst_type instruction. | 3956 // Encode NEON vcvt.src_type.dst_type instruction. |
3929 static Instr EncodeNeonVCVT(VFPType dst_type, QwNeonRegister dst, | 3957 static Instr EncodeNeonVCVT(VFPType dst_type, QwNeonRegister dst, |
3930 VFPType src_type, QwNeonRegister src) { | 3958 VFPType src_type, QwNeonRegister src) { |
3931 DCHECK(src_type != dst_type); | 3959 DCHECK(src_type != dst_type); |
3932 DCHECK(src_type == F32 || dst_type == F32); | 3960 DCHECK(src_type == F32 || dst_type == F32); |
3933 // Instruction details available in ARM DDI 0406C.b, A8.8.868. | 3961 // Instruction details available in ARM DDI 0406C.b, A8.8.868. |
3934 int vd, d; | 3962 int vd, d; |
3935 dst.split_code(&vd, &d); | 3963 dst.split_code(&vd, &d); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3970 emit(EncodeNeonVCVT(S32, dst, F32, src)); | 3998 emit(EncodeNeonVCVT(S32, dst, F32, src)); |
3971 } | 3999 } |
3972 | 4000 |
3973 void Assembler::vcvt_u32_f32(QwNeonRegister dst, QwNeonRegister src) { | 4001 void Assembler::vcvt_u32_f32(QwNeonRegister dst, QwNeonRegister src) { |
3974 DCHECK(IsEnabled(NEON)); | 4002 DCHECK(IsEnabled(NEON)); |
3975 DCHECK(VfpRegisterIsAvailable(dst)); | 4003 DCHECK(VfpRegisterIsAvailable(dst)); |
3976 DCHECK(VfpRegisterIsAvailable(src)); | 4004 DCHECK(VfpRegisterIsAvailable(src)); |
3977 emit(EncodeNeonVCVT(U32, dst, F32, src)); | 4005 emit(EncodeNeonVCVT(U32, dst, F32, src)); |
3978 } | 4006 } |
3979 | 4007 |
3980 enum NeonRegType { NEON_D, NEON_Q }; | |
3981 | |
3982 void NeonSplitCode(NeonRegType type, int code, int* vm, int* m, int* encoding) { | |
3983 if (type == NEON_D) { | |
3984 DwVfpRegister::split_code(code, vm, m); | |
3985 } else { | |
3986 DCHECK_EQ(type, NEON_Q); | |
3987 QwNeonRegister::split_code(code, vm, m); | |
3988 *encoding |= B6; | |
3989 } | |
3990 } | |
3991 | |
3992 enum UnaryOp { VMVN, VSWP, VABS, VABSF, VNEG, VNEGF }; | 4008 enum UnaryOp { VMVN, VSWP, VABS, VABSF, VNEG, VNEGF }; |
3993 | 4009 |
3994 static Instr EncodeNeonUnaryOp(UnaryOp op, NeonRegType reg_type, NeonSize size, | 4010 static Instr EncodeNeonUnaryOp(UnaryOp op, NeonRegType reg_type, NeonSize size, |
3995 int dst_code, int src_code) { | 4011 int dst_code, int src_code) { |
3996 int op_encoding = 0; | 4012 int op_encoding = 0; |
3997 switch (op) { | 4013 switch (op) { |
3998 case VMVN: | 4014 case VMVN: |
3999 DCHECK_EQ(Neon8, size); // size == 0 for vmvn | 4015 DCHECK_EQ(Neon8, size); // size == 0 for vmvn |
4000 op_encoding = B10 | 0x3 * B7; | 4016 op_encoding = B10 | 0x3 * B7; |
4001 break; | 4017 break; |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4396 } | 4412 } |
4397 | 4413 |
4398 void Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, | 4414 void Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1, |
4399 QwNeonRegister src2) { | 4415 QwNeonRegister src2) { |
4400 DCHECK(IsEnabled(NEON)); | 4416 DCHECK(IsEnabled(NEON)); |
4401 // Qd = vmax(Qn, Qm) SIMD integer MAX. | 4417 // Qd = vmax(Qn, Qm) SIMD integer MAX. |
4402 // Instruction details available in ARM DDI 0406C.b, A8-926. | 4418 // Instruction details available in ARM DDI 0406C.b, A8-926. |
4403 emit(EncodeNeonBinOp(VMAX, dt, dst, src1, src2)); | 4419 emit(EncodeNeonBinOp(VMAX, dt, dst, src1, src2)); |
4404 } | 4420 } |
4405 | 4421 |
4406 enum NeonShiftOp { VSHL, VSHR }; | 4422 enum NeonShiftOp { VSHL, VSHR, VSLI, VSRI }; |
4407 | 4423 |
4408 static Instr EncodeNeonShiftOp(NeonShiftOp op, NeonDataType dt, | 4424 static Instr EncodeNeonShiftOp(NeonShiftOp op, NeonSize size, bool is_unsigned, |
4409 QwNeonRegister dst, QwNeonRegister src, | 4425 NeonRegType reg_type, int dst_code, int src_code, |
4410 int shift) { | 4426 int shift) { |
| 4427 int imm6 = 0; |
| 4428 int size_in_bits = kBitsPerByte << static_cast<int>(size); |
| 4429 int op_encoding = 0; |
| 4430 switch (op) { |
| 4431 case VSHL: { |
| 4432 DCHECK(shift >= 0 && size_in_bits > shift); |
| 4433 imm6 = size_in_bits + shift; |
| 4434 op_encoding = 0x5 * B8; |
| 4435 break; |
| 4436 } |
| 4437 case VSHR: { |
| 4438 DCHECK(shift > 0 && size_in_bits >= shift); |
| 4439 imm6 = 2 * size_in_bits - shift; |
| 4440 if (is_unsigned) op_encoding |= B24; |
| 4441 break; |
| 4442 } |
| 4443 case VSLI: { |
| 4444 DCHECK(shift >= 0 && size_in_bits > shift); |
| 4445 imm6 = size_in_bits + shift; |
| 4446 int L = imm6 >> 6; |
| 4447 imm6 &= 0x3F; |
| 4448 op_encoding = B24 | 0x5 * B8 | L * B7; |
| 4449 break; |
| 4450 } |
| 4451 case VSRI: { |
| 4452 DCHECK(shift > 0 && size_in_bits >= shift); |
| 4453 imm6 = 2 * size_in_bits - shift; |
| 4454 int L = imm6 >> 6; |
| 4455 imm6 &= 0x3F; |
| 4456 op_encoding = B24 | 0x4 * B8 | L * B7; |
| 4457 break; |
| 4458 } |
| 4459 default: |
| 4460 UNREACHABLE(); |
| 4461 break; |
| 4462 } |
| 4463 |
4411 int vd, d; | 4464 int vd, d; |
4412 dst.split_code(&vd, &d); | 4465 NeonSplitCode(reg_type, dst_code, &vd, &d, &op_encoding); |
4413 int vm, m; | 4466 int vm, m; |
4414 src.split_code(&vm, &m); | 4467 NeonSplitCode(reg_type, src_code, &vm, &m, &op_encoding); |
4415 int size_in_bits = kBitsPerByte << NeonSz(dt); | 4468 |
4416 int op_encoding = 0; | 4469 return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | m * B5 | B4 | vm | |
4417 int imm6 = 0; | 4470 op_encoding; |
4418 if (op == VSHL) { | |
4419 DCHECK(shift >= 0 && size_in_bits > shift); | |
4420 imm6 = size_in_bits + shift; | |
4421 op_encoding = 0x5 * B8; | |
4422 } else { | |
4423 DCHECK_EQ(VSHR, op); | |
4424 DCHECK(shift > 0 && size_in_bits >= shift); | |
4425 imm6 = 2 * size_in_bits - shift; | |
4426 op_encoding = NeonU(dt) * B24; | |
4427 } | |
4428 return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | B6 | m * B5 | B4 | | |
4429 vm | op_encoding; | |
4430 } | 4471 } |
4431 | 4472 |
4432 void Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, | 4473 void Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, |
4433 int shift) { | 4474 int shift) { |
4434 DCHECK(IsEnabled(NEON)); | 4475 DCHECK(IsEnabled(NEON)); |
4435 // Qd = vshl(Qm, bits) SIMD shift left immediate. | 4476 // Qd = vshl(Qm, bits) SIMD shift left immediate. |
4436 // Instruction details available in ARM DDI 0406C.b, A8-1046. | 4477 // Instruction details available in ARM DDI 0406C.b, A8-1046. |
4437 emit(EncodeNeonShiftOp(VSHL, dt, dst, src, shift)); | 4478 emit(EncodeNeonShiftOp(VSHL, NeonDataTypeToSize(dt), false, NEON_Q, |
| 4479 dst.code(), src.code(), shift)); |
4438 } | 4480 } |
4439 | 4481 |
4440 void Assembler::vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, | 4482 void Assembler::vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, |
4441 int shift) { | 4483 int shift) { |
4442 DCHECK(IsEnabled(NEON)); | 4484 DCHECK(IsEnabled(NEON)); |
4443 // Qd = vshl(Qm, bits) SIMD shift right immediate. | 4485 // Qd = vshl(Qm, bits) SIMD shift right immediate. |
4444 // Instruction details available in ARM DDI 0406C.b, A8-1052. | 4486 // Instruction details available in ARM DDI 0406C.b, A8-1052. |
4445 emit(EncodeNeonShiftOp(VSHR, dt, dst, src, shift)); | 4487 emit(EncodeNeonShiftOp(VSHR, NeonDataTypeToSize(dt), NeonU(dt), NEON_Q, |
| 4488 dst.code(), src.code(), shift)); |
| 4489 } |
| 4490 |
| 4491 void Assembler::vsli(NeonSize size, DwVfpRegister dst, DwVfpRegister src, |
| 4492 int shift) { |
| 4493 DCHECK(IsEnabled(NEON)); |
| 4494 // Dd = vsli(Dm, bits) SIMD shift left and insert. |
| 4495 // Instruction details available in ARM DDI 0406C.b, A8-1056. |
| 4496 emit(EncodeNeonShiftOp(VSLI, size, false, NEON_D, dst.code(), src.code(), |
| 4497 shift)); |
| 4498 } |
| 4499 |
| 4500 void Assembler::vsri(NeonSize size, DwVfpRegister dst, DwVfpRegister src, |
| 4501 int shift) { |
| 4502 DCHECK(IsEnabled(NEON)); |
| 4503 // Dd = vsri(Dm, bits) SIMD shift right and insert. |
| 4504 // Instruction details available in ARM DDI 0406C.b, A8-1062. |
| 4505 emit(EncodeNeonShiftOp(VSRI, size, false, NEON_D, dst.code(), src.code(), |
| 4506 shift)); |
4446 } | 4507 } |
4447 | 4508 |
4448 static Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst, | 4509 static Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst, |
4449 QwNeonRegister src) { | 4510 QwNeonRegister src) { |
4450 int vd, d; | 4511 int vd, d; |
4451 dst.split_code(&vd, &d); | 4512 dst.split_code(&vd, &d); |
4452 int vm, m; | 4513 int vm, m; |
4453 src.split_code(&vm, &m); | 4514 src.split_code(&vm, &m); |
4454 int rsqrt = is_rsqrt ? 1 : 0; | 4515 int rsqrt = is_rsqrt ? 1 : 0; |
4455 return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 | | 4516 return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x5 * B8 | |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4532 | 4593 |
4533 emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 | | 4594 emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 | |
4534 m * B5 | vm); | 4595 m * B5 | vm); |
4535 } | 4596 } |
4536 | 4597 |
4537 void Assembler::vpadd(NeonSize size, DwVfpRegister dst, DwVfpRegister src1, | 4598 void Assembler::vpadd(NeonSize size, DwVfpRegister dst, DwVfpRegister src1, |
4538 DwVfpRegister src2) { | 4599 DwVfpRegister src2) { |
4539 DCHECK(IsEnabled(NEON)); | 4600 DCHECK(IsEnabled(NEON)); |
4540 // Dd = vpadd(Dn, Dm) SIMD integer pairwise ADD. | 4601 // Dd = vpadd(Dn, Dm) SIMD integer pairwise ADD. |
4541 // Instruction details available in ARM DDI 0406C.b, A8-980. | 4602 // Instruction details available in ARM DDI 0406C.b, A8-980. |
4542 emit(EncodeNeonPairwiseOp(VPADD, NeonSizeToDatatype(size), dst, src1, src2)); | 4603 emit(EncodeNeonPairwiseOp(VPADD, NeonSizeToDataType(size), dst, src1, src2)); |
4543 } | 4604 } |
4544 | 4605 |
4545 void Assembler::vpmin(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1, | 4606 void Assembler::vpmin(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1, |
4546 DwVfpRegister src2) { | 4607 DwVfpRegister src2) { |
4547 DCHECK(IsEnabled(NEON)); | 4608 DCHECK(IsEnabled(NEON)); |
4548 // Dd = vpmin(Dn, Dm) SIMD integer pairwise MIN. | 4609 // Dd = vpmin(Dn, Dm) SIMD integer pairwise MIN. |
4549 // Instruction details available in ARM DDI 0406C.b, A8-986. | 4610 // Instruction details available in ARM DDI 0406C.b, A8-986. |
4550 emit(EncodeNeonPairwiseOp(VPMIN, dt, dst, src1, src2)); | 4611 emit(EncodeNeonPairwiseOp(VPMIN, dt, dst, src1, src2)); |
4551 } | 4612 } |
4552 | 4613 |
(...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5269 } | 5330 } |
5270 | 5331 |
5271 void PatchingAssembler::FlushICache(Isolate* isolate) { | 5332 void PatchingAssembler::FlushICache(Isolate* isolate) { |
5272 Assembler::FlushICache(isolate, buffer_, buffer_size_ - kGap); | 5333 Assembler::FlushICache(isolate, buffer_, buffer_size_ - kGap); |
5273 } | 5334 } |
5274 | 5335 |
5275 } // namespace internal | 5336 } // namespace internal |
5276 } // namespace v8 | 5337 } // namespace v8 |
5277 | 5338 |
5278 #endif // V8_TARGET_ARCH_ARM | 5339 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |