| 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 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 case 256: | 476 case 256: |
| 477 align_ = 3; | 477 align_ = 3; |
| 478 break; | 478 break; |
| 479 default: | 479 default: |
| 480 UNREACHABLE(); | 480 UNREACHABLE(); |
| 481 align_ = 0; | 481 align_ = 0; |
| 482 break; | 482 break; |
| 483 } | 483 } |
| 484 } | 484 } |
| 485 | 485 |
| 486 | |
| 487 NeonListOperand::NeonListOperand(DoubleRegister base, int registers_count) { | |
| 488 base_ = base; | |
| 489 switch (registers_count) { | |
| 490 case 1: | |
| 491 type_ = nlt_1; | |
| 492 break; | |
| 493 case 2: | |
| 494 type_ = nlt_2; | |
| 495 break; | |
| 496 case 3: | |
| 497 type_ = nlt_3; | |
| 498 break; | |
| 499 case 4: | |
| 500 type_ = nlt_4; | |
| 501 break; | |
| 502 default: | |
| 503 UNREACHABLE(); | |
| 504 type_ = nlt_1; | |
| 505 break; | |
| 506 } | |
| 507 } | |
| 508 | |
| 509 | |
| 510 // ----------------------------------------------------------------------------- | 486 // ----------------------------------------------------------------------------- |
| 511 // Specific instructions, constants, and masks. | 487 // Specific instructions, constants, and masks. |
| 512 | 488 |
| 513 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r)) | 489 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r)) |
| 514 // register r is not encoded. | 490 // register r is not encoded. |
| 515 const Instr kPushRegPattern = | 491 const Instr kPushRegPattern = |
| 516 al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16; | 492 al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16; |
| 517 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) | 493 // ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r)) |
| 518 // register r is not encoded. | 494 // register r is not encoded. |
| 519 const Instr kPopRegPattern = | 495 const Instr kPopRegPattern = |
| (...skipping 2441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2961 // Rt = Sn. | 2937 // Rt = Sn. |
| 2962 // Instruction details available in ARM DDI 0406A, A8-642. | 2938 // Instruction details available in ARM DDI 0406A, A8-642. |
| 2963 // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) | | 2939 // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) | |
| 2964 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) | 2940 // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0) |
| 2965 DCHECK(!dst.is(pc)); | 2941 DCHECK(!dst.is(pc)); |
| 2966 int sn, n; | 2942 int sn, n; |
| 2967 src.split_code(&sn, &n); | 2943 src.split_code(&sn, &n); |
| 2968 emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4); | 2944 emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4); |
| 2969 } | 2945 } |
| 2970 | 2946 |
| 2971 | |
| 2972 // Type of data to read from or write to VFP register. | 2947 // Type of data to read from or write to VFP register. |
| 2973 // Used as specifier in generic vcvt instruction. | 2948 // Used as specifier in generic vcvt instruction. |
| 2974 enum VFPType { S32, U32, F32, F64 }; | 2949 enum VFPType { S32, U32, F32, F64 }; |
| 2975 | 2950 |
| 2976 | 2951 |
| 2977 static bool IsSignedVFPType(VFPType type) { | 2952 static bool IsSignedVFPType(VFPType type) { |
| 2978 switch (type) { | 2953 switch (type) { |
| 2979 case S32: | 2954 case S32: |
| 2980 return true; | 2955 return true; |
| 2981 case U32: | 2956 case U32: |
| (...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3895 // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0) | 3870 // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0) |
| 3896 DCHECK(IsEnabled(NEON)); | 3871 DCHECK(IsEnabled(NEON)); |
| 3897 int vd, d; | 3872 int vd, d; |
| 3898 dst.split_code(&vd, &d); | 3873 dst.split_code(&vd, &d); |
| 3899 int vm, m; | 3874 int vm, m; |
| 3900 src.split_code(&vm, &m); | 3875 src.split_code(&vm, &m); |
| 3901 emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 | | 3876 emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 | |
| 3902 (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm); | 3877 (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm); |
| 3903 } | 3878 } |
| 3904 | 3879 |
| 3880 static int EncodeScalar(NeonDataType dt, int index) { |
| 3881 int opc1_opc2 = 0; |
| 3882 DCHECK_LE(0, index); |
| 3883 switch (dt) { |
| 3884 case NeonS8: |
| 3885 case NeonU8: |
| 3886 DCHECK_GT(8, index); |
| 3887 opc1_opc2 = 0x8 | index; |
| 3888 break; |
| 3889 case NeonS16: |
| 3890 case NeonU16: |
| 3891 DCHECK_GT(4, index); |
| 3892 opc1_opc2 = 0x1 | (index << 1); |
| 3893 break; |
| 3894 case NeonS32: |
| 3895 case NeonU32: |
| 3896 DCHECK_GT(2, index); |
| 3897 opc1_opc2 = index << 2; |
| 3898 break; |
| 3899 default: |
| 3900 UNREACHABLE(); |
| 3901 break; |
| 3902 } |
| 3903 return (opc1_opc2 >> 2) * B21 | (opc1_opc2 & 0x3) * B5; |
| 3904 } |
| 3905 |
| 3906 void Assembler::vmov(NeonDataType dt, DwVfpRegister dst, int index, |
| 3907 Register src) { |
| 3908 // Instruction details available in ARM DDI 0406C.b, A8.8.940. |
| 3909 // vmov ARM core register to scalar. |
| 3910 DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON)); |
| 3911 int vd, d; |
| 3912 dst.split_code(&vd, &d); |
| 3913 int opc1_opc2 = EncodeScalar(dt, index); |
| 3914 emit(0xEEu * B24 | vd * B16 | src.code() * B12 | 0xB * B8 | d * B7 | B4 | |
| 3915 opc1_opc2); |
| 3916 } |
| 3917 |
| 3918 void Assembler::vmov(NeonDataType dt, Register dst, DwVfpRegister src, |
| 3919 int index) { |
| 3920 // Instruction details available in ARM DDI 0406C.b, A8.8.942. |
| 3921 // vmov Arm scalar to core register. |
| 3922 DCHECK(dt == NeonS32 || dt == NeonU32 || IsEnabled(NEON)); |
| 3923 int vn, n; |
| 3924 src.split_code(&vn, &n); |
| 3925 int opc1_opc2 = EncodeScalar(dt, index); |
| 3926 int u = (dt & NeonDataTypeUMask) != 0 ? 1 : 0; |
| 3927 emit(0xEEu * B24 | u * B23 | B20 | vn * B16 | dst.code() * B12 | 0xB * B8 | |
| 3928 n * B7 | B4 | opc1_opc2); |
| 3929 } |
| 3930 |
| 3905 void Assembler::vmov(const QwNeonRegister dst, const QwNeonRegister src) { | 3931 void Assembler::vmov(const QwNeonRegister dst, const QwNeonRegister src) { |
| 3906 DCHECK(IsEnabled(NEON)); | 3932 DCHECK(IsEnabled(NEON)); |
| 3907 // Instruction details available in ARM DDI 0406C.b, A8-938. | 3933 // Instruction details available in ARM DDI 0406C.b, A8-938. |
| 3908 DCHECK(VfpRegisterIsAvailable(dst)); | 3934 DCHECK(VfpRegisterIsAvailable(dst)); |
| 3909 DCHECK(VfpRegisterIsAvailable(src)); | 3935 DCHECK(VfpRegisterIsAvailable(src)); |
| 3910 int vd, d; | 3936 int vd, d; |
| 3911 dst.split_code(&vd, &d); | 3937 dst.split_code(&vd, &d); |
| 3912 int vm, m; | 3938 int vm, m; |
| 3913 src.split_code(&vm, &m); | 3939 src.split_code(&vm, &m); |
| 3914 emit(0x1E4U * B23 | d * B22 | 2 * B20 | vm * B16 | vd * B12 | B8 | m * B7 | | 3940 emit(0x1E4U * B23 | d * B22 | 2 * B20 | vm * B16 | vd * B12 | B8 | m * B7 | |
| 3915 B6 | m * B5 | B4 | vm); | 3941 B6 | m * B5 | B4 | vm); |
| 3916 } | 3942 } |
| 3917 | 3943 |
| 3944 void Assembler::vmvn(const QwNeonRegister dst, const QwNeonRegister src) { |
| 3945 DCHECK(IsEnabled(NEON)); |
| 3946 // Instruction details available in ARM DDI 0406C.b, A8-966. |
| 3947 DCHECK(VfpRegisterIsAvailable(dst)); |
| 3948 DCHECK(VfpRegisterIsAvailable(src)); |
| 3949 int vd, d; |
| 3950 dst.split_code(&vd, &d); |
| 3951 int vm, m; |
| 3952 src.split_code(&vm, &m); |
| 3953 emit(0x1E7U * B23 | d * B22 | 3 * B20 | vd * B12 | 0x17 * B6 | m * B5 | vm); |
| 3954 } |
| 3955 |
| 3918 void Assembler::vswp(DwVfpRegister dst, DwVfpRegister src) { | 3956 void Assembler::vswp(DwVfpRegister dst, DwVfpRegister src) { |
| 3919 // Instruction details available in ARM DDI 0406C.b, A8.8.418. | 3957 // Instruction details available in ARM DDI 0406C.b, A8.8.418. |
| 3920 // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) | | 3958 // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) | |
| 3921 // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0) | 3959 // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0) |
| 3922 DCHECK(IsEnabled(NEON)); | 3960 DCHECK(IsEnabled(NEON)); |
| 3923 int vd, d; | 3961 int vd, d; |
| 3924 dst.split_code(&vd, &d); | 3962 dst.split_code(&vd, &d); |
| 3925 int vm, m; | 3963 int vm, m; |
| 3926 src.split_code(&vm, &m); | 3964 src.split_code(&vm, &m); |
| 3927 emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | m * B5 | vm); | 3965 emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | m * B5 | vm); |
| 3928 } | 3966 } |
| 3929 | 3967 |
| 3930 void Assembler::vswp(QwNeonRegister dst, QwNeonRegister src) { | 3968 void Assembler::vswp(QwNeonRegister dst, QwNeonRegister src) { |
| 3931 // Instruction details available in ARM DDI 0406C.b, A8.8.418. | 3969 // Instruction details available in ARM DDI 0406C.b, A8.8.418. |
| 3932 // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) | | 3970 // 1111(31-28) | 00111(27-23) | D(22) | 110010(21-16) | |
| 3933 // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0) | 3971 // Vd(15-12) | 000000(11-6) | M(5) | 0(4) | Vm(3-0) |
| 3934 DCHECK(IsEnabled(NEON)); | 3972 DCHECK(IsEnabled(NEON)); |
| 3935 int vd, d; | 3973 int vd, d; |
| 3936 dst.split_code(&vd, &d); | 3974 dst.split_code(&vd, &d); |
| 3937 int vm, m; | 3975 int vm, m; |
| 3938 src.split_code(&vm, &m); | 3976 src.split_code(&vm, &m); |
| 3939 emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | B6 | m * B5 | | 3977 emit(0xFU * B28 | 7 * B23 | d * B22 | 0x32 * B16 | vd * B12 | B6 | m * B5 | |
| 3940 vm); | 3978 vm); |
| 3941 } | 3979 } |
| 3942 | 3980 |
| 3981 void Assembler::vdup(NeonSize size, const QwNeonRegister dst, |
| 3982 const Register src) { |
| 3983 DCHECK(IsEnabled(NEON)); |
| 3984 // Instruction details available in ARM DDI 0406C.b, A8-886. |
| 3985 int B = 0, E = 0; |
| 3986 switch (size) { |
| 3987 case Neon8: |
| 3988 B = 1; |
| 3989 break; |
| 3990 case Neon16: |
| 3991 E = 1; |
| 3992 break; |
| 3993 case Neon32: |
| 3994 break; |
| 3995 default: |
| 3996 UNREACHABLE(); |
| 3997 break; |
| 3998 } |
| 3999 int vd, d; |
| 4000 dst.split_code(&vd, &d); |
| 4001 |
| 4002 emit(al | 0x1D * B23 | B * B22 | B21 | vd * B16 | src.code() * B12 | |
| 4003 0xB * B8 | d * B7 | E * B5 | B4); |
| 4004 } |
| 4005 |
| 4006 void Assembler::vdup(const QwNeonRegister dst, const SwVfpRegister src) { |
| 4007 DCHECK(IsEnabled(NEON)); |
| 4008 // Instruction details available in ARM DDI 0406C.b, A8-884. |
| 4009 int index = src.code() & 1; |
| 4010 int d_reg = src.code() / 2; |
| 4011 int imm4 = 4 | index << 3; // esize = 32, index in bit 3. |
| 4012 int vd, d; |
| 4013 dst.split_code(&vd, &d); |
| 4014 int vm, m; |
| 4015 DwVfpRegister::from_code(d_reg).split_code(&vm, &m); |
| 4016 |
| 4017 emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | imm4 * B16 | vd * B12 | 0x18 * B7 | |
| 4018 B6 | m * B5 | vm); |
| 4019 } |
| 4020 |
| 4021 // Encode NEON vcvt.src_type.dst_type instruction. |
| 4022 static Instr EncodeNeonVCVT(const VFPType dst_type, const QwNeonRegister dst, |
| 4023 const VFPType src_type, const QwNeonRegister src) { |
| 4024 DCHECK(src_type != dst_type); |
| 4025 DCHECK(src_type == F32 || dst_type == F32); |
| 4026 // Instruction details available in ARM DDI 0406C.b, A8.8.868. |
| 4027 int vd, d; |
| 4028 dst.split_code(&vd, &d); |
| 4029 int vm, m; |
| 4030 src.split_code(&vm, &m); |
| 4031 |
| 4032 int op = 0; |
| 4033 if (src_type == F32) { |
| 4034 DCHECK(dst_type == S32 || dst_type == U32); |
| 4035 op = dst_type == U32 ? 3 : 2; |
| 4036 } else { |
| 4037 DCHECK(src_type == S32 || src_type == U32); |
| 4038 op = src_type == U32 ? 1 : 0; |
| 4039 } |
| 4040 |
| 4041 return 0x1E7U * B23 | d * B22 | 0x3B * B16 | vd * B12 | 0x3 * B9 | op * B7 | |
| 4042 B6 | m * B5 | vm; |
| 4043 } |
| 4044 |
| 4045 void Assembler::vcvt_f32_s32(const QwNeonRegister dst, |
| 4046 const QwNeonRegister src) { |
| 4047 DCHECK(IsEnabled(NEON)); |
| 4048 DCHECK(VfpRegisterIsAvailable(dst)); |
| 4049 DCHECK(VfpRegisterIsAvailable(src)); |
| 4050 emit(EncodeNeonVCVT(F32, dst, S32, src)); |
| 4051 } |
| 4052 |
| 4053 void Assembler::vcvt_f32_u32(const QwNeonRegister dst, |
| 4054 const QwNeonRegister src) { |
| 4055 DCHECK(IsEnabled(NEON)); |
| 4056 DCHECK(VfpRegisterIsAvailable(dst)); |
| 4057 DCHECK(VfpRegisterIsAvailable(src)); |
| 4058 emit(EncodeNeonVCVT(F32, dst, U32, src)); |
| 4059 } |
| 4060 |
| 4061 void Assembler::vcvt_s32_f32(const QwNeonRegister dst, |
| 4062 const QwNeonRegister src) { |
| 4063 DCHECK(IsEnabled(NEON)); |
| 4064 DCHECK(VfpRegisterIsAvailable(dst)); |
| 4065 DCHECK(VfpRegisterIsAvailable(src)); |
| 4066 emit(EncodeNeonVCVT(S32, dst, F32, src)); |
| 4067 } |
| 4068 |
| 4069 void Assembler::vcvt_u32_f32(const QwNeonRegister dst, |
| 4070 const QwNeonRegister src) { |
| 4071 DCHECK(IsEnabled(NEON)); |
| 4072 DCHECK(VfpRegisterIsAvailable(dst)); |
| 4073 DCHECK(VfpRegisterIsAvailable(src)); |
| 4074 emit(EncodeNeonVCVT(U32, dst, F32, src)); |
| 4075 } |
| 4076 |
| 3943 void Assembler::veor(DwVfpRegister dst, DwVfpRegister src1, | 4077 void Assembler::veor(DwVfpRegister dst, DwVfpRegister src1, |
| 3944 DwVfpRegister src2) { | 4078 DwVfpRegister src2) { |
| 4079 // Dd = veor(Dn, Dm) 64 bit integer exclusive OR. |
| 3945 // Instruction details available in ARM DDI 0406C.b, A8.8.888. | 4080 // Instruction details available in ARM DDI 0406C.b, A8.8.888. |
| 3946 DCHECK(IsEnabled(NEON)); | 4081 DCHECK(IsEnabled(NEON)); |
| 3947 int vd, d; | 4082 int vd, d; |
| 3948 dst.split_code(&vd, &d); | 4083 dst.split_code(&vd, &d); |
| 3949 int vn, n; | 4084 int vn, n; |
| 3950 src1.split_code(&vn, &n); | 4085 src1.split_code(&vn, &n); |
| 3951 int vm, m; | 4086 int vm, m; |
| 3952 src2.split_code(&vm, &m); | 4087 src2.split_code(&vm, &m); |
| 3953 emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | B8 | n * B7 | m * B5 | | 4088 emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | B8 | n * B7 | m * B5 | |
| 3954 B4 | vm); | 4089 B4 | vm); |
| 3955 } | 4090 } |
| 3956 | 4091 |
| 3957 void Assembler::veor(QwNeonRegister dst, QwNeonRegister src1, | 4092 void Assembler::veor(QwNeonRegister dst, QwNeonRegister src1, |
| 3958 QwNeonRegister src2) { | 4093 QwNeonRegister src2) { |
| 4094 // Qd = veor(Qn, Qm) SIMD integer exclusive OR. |
| 3959 // Instruction details available in ARM DDI 0406C.b, A8.8.888. | 4095 // Instruction details available in ARM DDI 0406C.b, A8.8.888. |
| 3960 DCHECK(IsEnabled(NEON)); | 4096 DCHECK(IsEnabled(NEON)); |
| 3961 int vd, d; | 4097 int vd, d; |
| 3962 dst.split_code(&vd, &d); | 4098 dst.split_code(&vd, &d); |
| 3963 int vn, n; | 4099 int vn, n; |
| 3964 src1.split_code(&vn, &n); | 4100 src1.split_code(&vn, &n); |
| 3965 int vm, m; | 4101 int vm, m; |
| 3966 src2.split_code(&vm, &m); | 4102 src2.split_code(&vm, &m); |
| 3967 emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | B8 | n * B7 | B6 | | 4103 emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | B8 | n * B7 | B6 | |
| 3968 m * B5 | B4 | vm); | 4104 m * B5 | B4 | vm); |
| 3969 } | 4105 } |
| 3970 | 4106 |
| 4107 void Assembler::vadd(QwNeonRegister dst, const QwNeonRegister src1, |
| 4108 const QwNeonRegister src2) { |
| 4109 DCHECK(IsEnabled(NEON)); |
| 4110 // Qd = vadd(Qn, Qm) SIMD floating point addition. |
| 4111 // Instruction details available in ARM DDI 0406C.b, A8-830. |
| 4112 int vd, d; |
| 4113 dst.split_code(&vd, &d); |
| 4114 int vn, n; |
| 4115 src1.split_code(&vn, &n); |
| 4116 int vm, m; |
| 4117 src2.split_code(&vm, &m); |
| 4118 emit(0x1E4U * B23 | d * B22 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 | B6 | |
| 4119 m * B5 | vm); |
| 4120 } |
| 4121 |
| 4122 void Assembler::vadd(NeonSize size, QwNeonRegister dst, |
| 4123 const QwNeonRegister src1, const QwNeonRegister src2) { |
| 4124 DCHECK(IsEnabled(NEON)); |
| 4125 // Qd = vadd(Qn, Qm) SIMD integer addition. |
| 4126 // Instruction details available in ARM DDI 0406C.b, A8-828. |
| 4127 int vd, d; |
| 4128 dst.split_code(&vd, &d); |
| 4129 int vn, n; |
| 4130 src1.split_code(&vn, &n); |
| 4131 int vm, m; |
| 4132 src2.split_code(&vm, &m); |
| 4133 int sz = static_cast<int>(size); |
| 4134 emit(0x1E4U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x8 * B8 | |
| 4135 n * B7 | B6 | m * B5 | vm); |
| 4136 } |
| 4137 |
| 4138 void Assembler::vsub(QwNeonRegister dst, const QwNeonRegister src1, |
| 4139 const QwNeonRegister src2) { |
| 4140 DCHECK(IsEnabled(NEON)); |
| 4141 // Qd = vsub(Qn, Qm) SIMD floating point subtraction. |
| 4142 // Instruction details available in ARM DDI 0406C.b, A8-1086. |
| 4143 int vd, d; |
| 4144 dst.split_code(&vd, &d); |
| 4145 int vn, n; |
| 4146 src1.split_code(&vn, &n); |
| 4147 int vm, m; |
| 4148 src2.split_code(&vm, &m); |
| 4149 emit(0x1E4U * B23 | d * B22 | B21 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 | |
| 4150 B6 | m * B5 | vm); |
| 4151 } |
| 4152 |
| 4153 void Assembler::vsub(NeonSize size, QwNeonRegister dst, |
| 4154 const QwNeonRegister src1, const QwNeonRegister src2) { |
| 4155 DCHECK(IsEnabled(NEON)); |
| 4156 // Qd = vsub(Qn, Qm) SIMD integer subtraction. |
| 4157 // Instruction details available in ARM DDI 0406C.b, A8-1084. |
| 4158 int vd, d; |
| 4159 dst.split_code(&vd, &d); |
| 4160 int vn, n; |
| 4161 src1.split_code(&vn, &n); |
| 4162 int vm, m; |
| 4163 src2.split_code(&vm, &m); |
| 4164 int sz = static_cast<int>(size); |
| 4165 emit(0x1E6U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x8 * B8 | |
| 4166 n * B7 | B6 | m * B5 | vm); |
| 4167 } |
| 4168 |
| 4169 void Assembler::vtst(NeonSize size, QwNeonRegister dst, |
| 4170 const QwNeonRegister src1, const QwNeonRegister src2) { |
| 4171 DCHECK(IsEnabled(NEON)); |
| 4172 // Qd = vtst(Qn, Qm) SIMD test integer operands. |
| 4173 // Instruction details available in ARM DDI 0406C.b, A8-1098. |
| 4174 int vd, d; |
| 4175 dst.split_code(&vd, &d); |
| 4176 int vn, n; |
| 4177 src1.split_code(&vn, &n); |
| 4178 int vm, m; |
| 4179 src2.split_code(&vm, &m); |
| 4180 int sz = static_cast<int>(size); |
| 4181 emit(0x1E4U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x8 * B8 | |
| 4182 n * B7 | B6 | m * B5 | B4 | vm); |
| 4183 } |
| 4184 |
| 4185 void Assembler::vceq(NeonSize size, QwNeonRegister dst, |
| 4186 const QwNeonRegister src1, const QwNeonRegister src2) { |
| 4187 DCHECK(IsEnabled(NEON)); |
| 4188 // Qd = vceq(Qn, Qm) SIMD integer compare equal. |
| 4189 // Instruction details available in ARM DDI 0406C.b, A8-844. |
| 4190 int vd, d; |
| 4191 dst.split_code(&vd, &d); |
| 4192 int vn, n; |
| 4193 src1.split_code(&vn, &n); |
| 4194 int vm, m; |
| 4195 src2.split_code(&vm, &m); |
| 4196 int sz = static_cast<int>(size); |
| 4197 emit(0x1E6U * B23 | d * B22 | sz * B20 | vn * B16 | vd * B12 | 0x8 * B8 | |
| 4198 n * B7 | B6 | m * B5 | B4 | vm); |
| 4199 } |
| 4200 |
| 4201 void Assembler::vbsl(QwNeonRegister dst, const QwNeonRegister src1, |
| 4202 const QwNeonRegister src2) { |
| 4203 DCHECK(IsEnabled(NEON)); |
| 4204 // Qd = vbsl(Qn, Qm) SIMD bitwise select. |
| 4205 // Instruction details available in ARM DDI 0406C.b, A8-844. |
| 4206 int vd, d; |
| 4207 dst.split_code(&vd, &d); |
| 4208 int vn, n; |
| 4209 src1.split_code(&vn, &n); |
| 4210 int vm, m; |
| 4211 src2.split_code(&vm, &m); |
| 4212 int op = 1; // vbsl |
| 4213 emit(0x1E6U * B23 | d * B22 | op * B20 | vn * B16 | vd * B12 | 0x1 * B8 | |
| 4214 n * B7 | B6 | m * B5 | B4 | vm); |
| 4215 } |
| 4216 |
| 4217 // Encode NEON vtbl / vtbx instruction. |
| 4218 static Instr EncodeNeonVTB(const DwVfpRegister dst, const NeonListOperand& list, |
| 4219 const DwVfpRegister index, bool vtbx) { |
| 4220 // Dd = vtbl(table, Dm) SIMD vector permute, zero at out of range indices. |
| 4221 // Instruction details available in ARM DDI 0406C.b, A8-1094. |
| 4222 // Dd = vtbx(table, Dm) SIMD vector permute, skip out of range indices. |
| 4223 // Instruction details available in ARM DDI 0406C.b, A8-1094. |
| 4224 int vd, d; |
| 4225 dst.split_code(&vd, &d); |
| 4226 int vn, n; |
| 4227 list.base().split_code(&vn, &n); |
| 4228 int vm, m; |
| 4229 index.split_code(&vm, &m); |
| 4230 int op = vtbx ? 1 : 0; // vtbl = 0, vtbx = 1. |
| 4231 return 0x1E7U * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 | 0x2 * B10 | |
| 4232 list.length() * B8 | n * B7 | op * B6 | m * B5 | vm; |
| 4233 } |
| 4234 |
| 4235 void Assembler::vtbl(const DwVfpRegister dst, const NeonListOperand& list, |
| 4236 const DwVfpRegister index) { |
| 4237 DCHECK(IsEnabled(NEON)); |
| 4238 emit(EncodeNeonVTB(dst, list, index, false)); |
| 4239 } |
| 4240 |
| 4241 void Assembler::vtbx(const DwVfpRegister dst, const NeonListOperand& list, |
| 4242 const DwVfpRegister index) { |
| 4243 DCHECK(IsEnabled(NEON)); |
| 4244 emit(EncodeNeonVTB(dst, list, index, true)); |
| 4245 } |
| 4246 |
| 3971 // Pseudo instructions. | 4247 // Pseudo instructions. |
| 3972 void Assembler::nop(int type) { | 4248 void Assembler::nop(int type) { |
| 3973 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes | 4249 // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes |
| 3974 // some of the CPU's pipeline and has to issue. Older ARM chips simply used | 4250 // some of the CPU's pipeline and has to issue. Older ARM chips simply used |
| 3975 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. | 4251 // MOV Rx, Rx as NOP and it performs better even in newer CPUs. |
| 3976 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode | 4252 // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode |
| 3977 // a type. | 4253 // a type. |
| 3978 DCHECK(0 <= type && type <= 14); // mov pc, pc isn't a nop. | 4254 DCHECK(0 <= type && type <= 14); // mov pc, pc isn't a nop. |
| 3979 emit(al | 13*B21 | type*B12 | type); | 4255 emit(al | 13*B21 | type*B12 | type); |
| 3980 } | 4256 } |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4514 DCHECK(is_uint12(offset)); | 4790 DCHECK(is_uint12(offset)); |
| 4515 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); | 4791 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); |
| 4516 } | 4792 } |
| 4517 } | 4793 } |
| 4518 | 4794 |
| 4519 | 4795 |
| 4520 } // namespace internal | 4796 } // namespace internal |
| 4521 } // namespace v8 | 4797 } // namespace v8 |
| 4522 | 4798 |
| 4523 #endif // V8_TARGET_ARCH_ARM | 4799 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |