Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(304)

Side by Side Diff: src/arm/assembler-arm.cc

Issue 2546933002: [Turbofan] Add ARM NEON instructions for implementing SIMD. (Closed)
Patch Set: Fourth review comments. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/constants-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.h ('k') | src/arm/constants-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698