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