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 |