1;; ARM NEON coprocessor Machine Description 2;; Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. 3;; Written by CodeSourcery. 4;; 5;; This file is part of GCC. 6;; 7;; GCC is free software; you can redistribute it and/or modify it 8;; under the terms of the GNU General Public License as published by 9;; the Free Software Foundation; either version 3, or (at your option) 10;; any later version. 11;; 12;; GCC is distributed in the hope that it will be useful, but 13;; WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15;; General Public License for more details. 16;; 17;; You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. 20 21;; Constants for unspecs. 22(define_constants 23 [(UNSPEC_ASHIFT_SIGNED 65) 24 (UNSPEC_ASHIFT_UNSIGNED 66) 25 (UNSPEC_VABA 67) 26 (UNSPEC_VABAL 68) 27 (UNSPEC_VABD 69) 28 (UNSPEC_VABDL 70) 29 (UNSPEC_VABS 71) 30 (UNSPEC_VADD 72) 31 (UNSPEC_VADDHN 73) 32 (UNSPEC_VADDL 74) 33 (UNSPEC_VADDW 75) 34 (UNSPEC_VAND 76) 35 (UNSPEC_VBIC 77) 36 (UNSPEC_VBSL 78) 37 (UNSPEC_VCAGE 79) 38 (UNSPEC_VCAGT 80) 39 (UNSPEC_VCEQ 81) 40 (UNSPEC_VCGE 82) 41 (UNSPEC_VCGT 83) 42 (UNSPEC_VCLS 84) 43 (UNSPEC_VCLZ 85) 44 (UNSPEC_VCNT 86) 45 (UNSPEC_VCOMBINE 87) 46 (UNSPEC_VCVT 88) 47 (UNSPEC_VCVT_N 89) 48 (UNSPEC_VDUP_LANE 90) 49 (UNSPEC_VDUP_N 91) 50 (UNSPEC_VEOR 92) 51 (UNSPEC_VEXT 93) 52 (UNSPEC_VGET_HIGH 94) 53 (UNSPEC_VGET_LANE 95) 54 (UNSPEC_VGET_LOW 96) 55 (UNSPEC_VHADD 97) 56 (UNSPEC_VHSUB 98) 57 (UNSPEC_VLD1 99) 58 (UNSPEC_VLD1_DUP 100) 59 (UNSPEC_VLD1_LANE 101) 60 (UNSPEC_VLD2 102) 61 (UNSPEC_VLD2_DUP 103) 62 (UNSPEC_VLD2_LANE 104) 63 (UNSPEC_VLD3 105) 64 (UNSPEC_VLD3A 106) 65 (UNSPEC_VLD3B 107) 66 (UNSPEC_VLD3_DUP 108) 67 (UNSPEC_VLD3_LANE 109) 68 (UNSPEC_VLD4 110) 69 (UNSPEC_VLD4A 111) 70 (UNSPEC_VLD4B 112) 71 (UNSPEC_VLD4_DUP 113) 72 (UNSPEC_VLD4_LANE 114) 73 (UNSPEC_VMAX 115) 74 (UNSPEC_VMIN 116) 75 (UNSPEC_VMLA 117) 76 (UNSPEC_VMLAL 118) 77 (UNSPEC_VMLA_LANE 119) 78 (UNSPEC_VMLAL_LANE 120) 79 (UNSPEC_VMLS 121) 80 (UNSPEC_VMLSL 122) 81 (UNSPEC_VMLS_LANE 123) 82 (UNSPEC_VMLSL_LANE 124) 83 (UNSPEC_VMOVL 125) 84 (UNSPEC_VMOVN 126) 85 (UNSPEC_VMUL 127) 86 (UNSPEC_VMULL 128) 87 (UNSPEC_VMUL_LANE 129) 88 (UNSPEC_VMULL_LANE 130) 89 (UNSPEC_VMUL_N 131) 90 (UNSPEC_VMVN 132) 91 (UNSPEC_VORN 133) 92 (UNSPEC_VORR 134) 93 (UNSPEC_VPADAL 135) 94 (UNSPEC_VPADD 136) 95 (UNSPEC_VPADDL 137) 96 (UNSPEC_VPMAX 138) 97 (UNSPEC_VPMIN 139) 98 (UNSPEC_VPSMAX 140) 99 (UNSPEC_VPSMIN 141) 100 (UNSPEC_VPUMAX 142) 101 (UNSPEC_VPUMIN 143) 102 (UNSPEC_VQABS 144) 103 (UNSPEC_VQADD 145) 104 (UNSPEC_VQDMLAL 146) 105 (UNSPEC_VQDMLAL_LANE 147) 106 (UNSPEC_VQDMLSL 148) 107 (UNSPEC_VQDMLSL_LANE 149) 108 (UNSPEC_VQDMULH 150) 109 (UNSPEC_VQDMULH_LANE 151) 110 (UNSPEC_VQDMULL 152) 111 (UNSPEC_VQDMULL_LANE 153) 112 (UNSPEC_VQMOVN 154) 113 (UNSPEC_VQMOVUN 155) 114 (UNSPEC_VQNEG 156) 115 (UNSPEC_VQSHL 157) 116 (UNSPEC_VQSHL_N 158) 117 (UNSPEC_VQSHLU_N 159) 118 (UNSPEC_VQSHRN_N 160) 119 (UNSPEC_VQSHRUN_N 161) 120 (UNSPEC_VQSUB 162) 121 (UNSPEC_VRECPE 163) 122 (UNSPEC_VRECPS 164) 123 (UNSPEC_VREV16 165) 124 (UNSPEC_VREV32 166) 125 (UNSPEC_VREV64 167) 126 (UNSPEC_VRSQRTE 168) 127 (UNSPEC_VRSQRTS 169) 128 (UNSPEC_VSET_LANE 170) 129 (UNSPEC_VSHL 171) 130 (UNSPEC_VSHLL_N 172) 131 (UNSPEC_VSHL_N 173) 132 (UNSPEC_VSHR_N 174) 133 (UNSPEC_VSHRN_N 175) 134 (UNSPEC_VSLI 176) 135 (UNSPEC_VSRA_N 177) 136 (UNSPEC_VSRI 178) 137 (UNSPEC_VST1 179) 138 (UNSPEC_VST1_LANE 180) 139 (UNSPEC_VST2 181) 140 (UNSPEC_VST2_LANE 182) 141 (UNSPEC_VST3 183) 142 (UNSPEC_VST3A 184) 143 (UNSPEC_VST3B 185) 144 (UNSPEC_VST3_LANE 186) 145 (UNSPEC_VST4 187) 146 (UNSPEC_VST4A 188) 147 (UNSPEC_VST4B 189) 148 (UNSPEC_VST4_LANE 190) 149 (UNSPEC_VSTRUCTDUMMY 191) 150 (UNSPEC_VSUB 192) 151 (UNSPEC_VSUBHN 193) 152 (UNSPEC_VSUBL 194) 153 (UNSPEC_VSUBW 195) 154 (UNSPEC_VTBL 196) 155 (UNSPEC_VTBX 197) 156 (UNSPEC_VTRN1 198) 157 (UNSPEC_VTRN2 199) 158 (UNSPEC_VTST 200) 159 (UNSPEC_VUZP1 201) 160 (UNSPEC_VUZP2 202) 161 (UNSPEC_VZIP1 203) 162 (UNSPEC_VZIP2 204)]) 163 164;; Double-width vector modes. 165(define_mode_iterator VD [V8QI V4HI V2SI V2SF]) 166 167;; Double-width vector modes plus 64-bit elements. 168(define_mode_iterator VDX [V8QI V4HI V2SI V2SF DI]) 169 170;; Same, without floating-point elements. 171(define_mode_iterator VDI [V8QI V4HI V2SI]) 172 173;; Quad-width vector modes. 174(define_mode_iterator VQ [V16QI V8HI V4SI V4SF]) 175 176;; Quad-width vector modes plus 64-bit elements. 177(define_mode_iterator VQX [V16QI V8HI V4SI V4SF V2DI]) 178 179;; Same, without floating-point elements. 180(define_mode_iterator VQI [V16QI V8HI V4SI]) 181 182;; Same, with TImode added, for moves. 183(define_mode_iterator VQXMOV [V16QI V8HI V4SI V4SF V2DI TI]) 184 185;; Opaque structure types wider than TImode. 186(define_mode_iterator VSTRUCT [EI OI CI XI]) 187 188;; Opaque structure types used in table lookups (except vtbl1/vtbx1). 189(define_mode_iterator VTAB [TI EI OI]) 190 191;; vtbl<n> suffix for above modes. 192(define_mode_attr VTAB_n [(TI "2") (EI "3") (OI "4")]) 193 194;; Widenable modes. 195(define_mode_iterator VW [V8QI V4HI V2SI]) 196 197;; Narrowable modes. 198(define_mode_iterator VN [V8HI V4SI V2DI]) 199 200;; All supported vector modes (except singleton DImode). 201(define_mode_iterator VDQ [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF V2DI]) 202 203;; All supported vector modes (except those with 64-bit integer elements). 204(define_mode_iterator VDQW [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF]) 205 206;; Supported integer vector modes (not 64 bit elements). 207(define_mode_iterator VDQIW [V8QI V16QI V4HI V8HI V2SI V4SI]) 208 209;; Supported integer vector modes (not singleton DI) 210(define_mode_iterator VDQI [V8QI V16QI V4HI V8HI V2SI V4SI V2DI]) 211 212;; Vector modes, including 64-bit integer elements. 213(define_mode_iterator VDQX [V8QI V16QI V4HI V8HI V2SI V4SI V2SF V4SF DI V2DI]) 214 215;; Vector modes including 64-bit integer elements, but no floats. 216(define_mode_iterator VDQIX [V8QI V16QI V4HI V8HI V2SI V4SI DI V2DI]) 217 218;; Vector modes for float->int conversions. 219(define_mode_iterator VCVTF [V2SF V4SF]) 220 221;; Vector modes form int->float conversions. 222(define_mode_iterator VCVTI [V2SI V4SI]) 223 224;; Vector modes for doubleword multiply-accumulate, etc. insns. 225(define_mode_iterator VMD [V4HI V2SI V2SF]) 226 227;; Vector modes for quadword multiply-accumulate, etc. insns. 228(define_mode_iterator VMQ [V8HI V4SI V4SF]) 229 230;; Above modes combined. 231(define_mode_iterator VMDQ [V4HI V2SI V2SF V8HI V4SI V4SF]) 232 233;; As VMD, but integer modes only. 234(define_mode_iterator VMDI [V4HI V2SI]) 235 236;; As VMQ, but integer modes only. 237(define_mode_iterator VMQI [V8HI V4SI]) 238 239;; Above modes combined. 240(define_mode_iterator VMDQI [V4HI V2SI V8HI V4SI]) 241 242;; Modes with 8-bit and 16-bit elements. 243(define_mode_iterator VX [V8QI V4HI V16QI V8HI]) 244 245;; Modes with 8-bit elements. 246(define_mode_iterator VE [V8QI V16QI]) 247 248;; Modes with 64-bit elements only. 249(define_mode_iterator V64 [DI V2DI]) 250 251;; Modes with 32-bit elements only. 252(define_mode_iterator V32 [V2SI V2SF V4SI V4SF]) 253 254;; (Opposite) mode to convert to/from for above conversions. 255(define_mode_attr V_CVTTO [(V2SI "V2SF") (V2SF "V2SI") 256 (V4SI "V4SF") (V4SF "V4SI")]) 257 258;; Define element mode for each vector mode. 259(define_mode_attr V_elem [(V8QI "QI") (V16QI "QI") 260 (V4HI "HI") (V8HI "HI") 261 (V2SI "SI") (V4SI "SI") 262 (V2SF "SF") (V4SF "SF") 263 (DI "DI") (V2DI "DI")]) 264 265;; Element modes for vector extraction, padded up to register size. 266 267(define_mode_attr V_ext [(V8QI "SI") (V16QI "SI") 268 (V4HI "SI") (V8HI "SI") 269 (V2SI "SI") (V4SI "SI") 270 (V2SF "SF") (V4SF "SF") 271 (DI "DI") (V2DI "DI")]) 272 273;; Mode of pair of elements for each vector mode, to define transfer 274;; size for structure lane/dup loads and stores. 275(define_mode_attr V_two_elem [(V8QI "HI") (V16QI "HI") 276 (V4HI "SI") (V8HI "SI") 277 (V2SI "V2SI") (V4SI "V2SI") 278 (V2SF "V2SF") (V4SF "V2SF") 279 (DI "V2DI") (V2DI "V2DI")]) 280 281;; Similar, for three elements. 282;; ??? Should we define extra modes so that sizes of all three-element 283;; accesses can be accurately represented? 284(define_mode_attr V_three_elem [(V8QI "SI") (V16QI "SI") 285 (V4HI "V4HI") (V8HI "V4HI") 286 (V2SI "V4SI") (V4SI "V4SI") 287 (V2SF "V4SF") (V4SF "V4SF") 288 (DI "EI") (V2DI "EI")]) 289 290;; Similar, for four elements. 291(define_mode_attr V_four_elem [(V8QI "SI") (V16QI "SI") 292 (V4HI "V4HI") (V8HI "V4HI") 293 (V2SI "V4SI") (V4SI "V4SI") 294 (V2SF "V4SF") (V4SF "V4SF") 295 (DI "OI") (V2DI "OI")]) 296 297;; Register width from element mode 298(define_mode_attr V_reg [(V8QI "P") (V16QI "q") 299 (V4HI "P") (V8HI "q") 300 (V2SI "P") (V4SI "q") 301 (V2SF "P") (V4SF "q") 302 (DI "P") (V2DI "q")]) 303 304;; Wider modes with the same number of elements. 305(define_mode_attr V_widen [(V8QI "V8HI") (V4HI "V4SI") (V2SI "V2DI")]) 306 307;; Narrower modes with the same number of elements. 308(define_mode_attr V_narrow [(V8HI "V8QI") (V4SI "V4HI") (V2DI "V2SI")]) 309 310;; Modes with half the number of equal-sized elements. 311(define_mode_attr V_HALF [(V16QI "V8QI") (V8HI "V4HI") 312 (V4SI "V2SI") (V4SF "V2SF") 313 (V2DI "DI")]) 314 315;; Same, but lower-case. 316(define_mode_attr V_half [(V16QI "v8qi") (V8HI "v4hi") 317 (V4SI "v2si") (V4SF "v2sf") 318 (V2DI "di")]) 319 320;; Modes with twice the number of equal-sized elements. 321(define_mode_attr V_DOUBLE [(V8QI "V16QI") (V4HI "V8HI") 322 (V2SI "V4SI") (V2SF "V4SF") 323 (DI "V2DI")]) 324 325;; Same, but lower-case. 326(define_mode_attr V_double [(V8QI "v16qi") (V4HI "v8hi") 327 (V2SI "v4si") (V2SF "v4sf") 328 (DI "v2di")]) 329 330;; Modes with double-width elements. 331(define_mode_attr V_double_width [(V8QI "V4HI") (V16QI "V8HI") 332 (V4HI "V2SI") (V8HI "V4SI") 333 (V2SI "DI") (V4SI "V2DI")]) 334 335;; Mode of result of comparison operations (and bit-select operand 1). 336(define_mode_attr V_cmp_result [(V8QI "V8QI") (V16QI "V16QI") 337 (V4HI "V4HI") (V8HI "V8HI") 338 (V2SI "V2SI") (V4SI "V4SI") 339 (V2SF "V2SI") (V4SF "V4SI") 340 (DI "DI") (V2DI "V2DI")]) 341 342;; Get element type from double-width mode, for operations where we don't care 343;; about signedness. 344(define_mode_attr V_if_elem [(V8QI "i8") (V16QI "i8") 345 (V4HI "i16") (V8HI "i16") 346 (V2SI "i32") (V4SI "i32") 347 (DI "i64") (V2DI "i64") 348 (V2SF "f32") (V4SF "f32")]) 349 350;; Same, but for operations which work on signed values. 351(define_mode_attr V_s_elem [(V8QI "s8") (V16QI "s8") 352 (V4HI "s16") (V8HI "s16") 353 (V2SI "s32") (V4SI "s32") 354 (DI "s64") (V2DI "s64") 355 (V2SF "f32") (V4SF "f32")]) 356 357;; Same, but for operations which work on unsigned values. 358(define_mode_attr V_u_elem [(V8QI "u8") (V16QI "u8") 359 (V4HI "u16") (V8HI "u16") 360 (V2SI "u32") (V4SI "u32") 361 (DI "u64") (V2DI "u64") 362 (V2SF "f32") (V4SF "f32")]) 363 364;; Element types for extraction of unsigned scalars. 365(define_mode_attr V_uf_sclr [(V8QI "u8") (V16QI "u8") 366 (V4HI "u16") (V8HI "u16") 367 (V2SI "32") (V4SI "32") 368 (V2SF "32") (V4SF "32")]) 369 370(define_mode_attr V_sz_elem [(V8QI "8") (V16QI "8") 371 (V4HI "16") (V8HI "16") 372 (V2SI "32") (V4SI "32") 373 (DI "64") (V2DI "64") 374 (V2SF "32") (V4SF "32")]) 375 376;; Element sizes for duplicating ARM registers to all elements of a vector. 377(define_mode_attr VD_dup [(V8QI "8") (V4HI "16") (V2SI "32") (V2SF "32")]) 378 379;; Opaque integer types for results of pair-forming intrinsics (vtrn, etc.) 380(define_mode_attr V_PAIR [(V8QI "TI") (V16QI "OI") 381 (V4HI "TI") (V8HI "OI") 382 (V2SI "TI") (V4SI "OI") 383 (V2SF "TI") (V4SF "OI") 384 (DI "TI") (V2DI "OI")]) 385 386;; Same, but lower-case. 387(define_mode_attr V_pair [(V8QI "ti") (V16QI "oi") 388 (V4HI "ti") (V8HI "oi") 389 (V2SI "ti") (V4SI "oi") 390 (V2SF "ti") (V4SF "oi") 391 (DI "ti") (V2DI "oi")]) 392 393;; Operations on two halves of a quadword vector. 394(define_code_iterator vqh_ops [plus smin smax umin umax]) 395 396;; Same, without unsigned variants (for use with *SFmode pattern). 397(define_code_iterator vqhs_ops [plus smin smax]) 398 399;; Assembler mnemonics for above codes. 400(define_code_attr VQH_mnem [(plus "vadd") (smin "vmin") (smax "vmax") 401 (umin "vmin") (umax "vmax")]) 402 403;; Signs of above, where relevant. 404(define_code_attr VQH_sign [(plus "i") (smin "s") (smax "s") (umin "u") 405 (umax "u")]) 406 407;; Extra suffix on some 64-bit insn names (to avoid collision with standard 408;; names which we don't want to define). 409(define_mode_attr V_suf64 [(V8QI "") (V16QI "") 410 (V4HI "") (V8HI "") 411 (V2SI "") (V4SI "") 412 (V2SF "") (V4SF "") 413 (DI "_neon") (V2DI "")]) 414 415;; Scalars to be presented to scalar multiplication instructions 416;; must satisfy the following constraints. 417;; 1. If the mode specifies 16-bit elements, the scalar must be in D0-D7. 418;; 2. If the mode specifies 32-bit elements, the scalar must be in D0-D15. 419;; This mode attribute is used to obtain the correct register constraints. 420(define_mode_attr scalar_mul_constraint [(V4HI "x") (V2SI "t") (V2SF "t") 421 (V8HI "x") (V4SI "t") (V4SF "t")]) 422 423;; Attribute used to permit string comparisons against <VQH_mnem> in 424;; neon_type attribute definitions. 425(define_attr "vqh_mnem" "vadd,vmin,vmax" (const_string "vadd")) 426 427;; Predicates used for setting neon_type 428 429(define_mode_attr Is_float_mode [(V8QI "false") (V16QI "false") 430 (V4HI "false") (V8HI "false") 431 (V2SI "false") (V4SI "false") 432 (V2SF "true") (V4SF "true") 433 (DI "false") (V2DI "false")]) 434 435(define_mode_attr Scalar_mul_8_16 [(V8QI "true") (V16QI "true") 436 (V4HI "true") (V8HI "true") 437 (V2SI "false") (V4SI "false") 438 (V2SF "false") (V4SF "false") 439 (DI "false") (V2DI "false")]) 440 441 442(define_mode_attr Is_d_reg [(V8QI "true") (V16QI "false") 443 (V4HI "true") (V8HI "false") 444 (V2SI "true") (V4SI "false") 445 (V2SF "true") (V4SF "false") 446 (DI "true") (V2DI "false")]) 447 448(define_mode_attr V_mode_nunits [(V8QI "8") (V16QI "16") 449 (V4HI "4") (V8HI "8") 450 (V2SI "2") (V4SI "4") 451 (V2SF "2") (V4SF "4") 452 (DI "1") (V2DI "2")]) 453 454(define_insn "*neon_mov<mode>" 455 [(set (match_operand:VD 0 "nonimmediate_operand" 456 "=w,Uv,w, w, ?r,?w,?r,?r, ?Us") 457 (match_operand:VD 1 "general_operand" 458 " w,w, Dn,Uvi, w, r, r, Usi,r"))] 459 "TARGET_NEON 460 && (register_operand (operands[0], <MODE>mode) 461 || register_operand (operands[1], <MODE>mode))" 462{ 463 if (which_alternative == 2) 464 { 465 int width, is_valid; 466 static char templ[40]; 467 468 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode, 469 &operands[1], &width); 470 471 gcc_assert (is_valid != 0); 472 473 if (width == 0) 474 return "vmov.f32\t%P0, %1 @ <mode>"; 475 else 476 sprintf (templ, "vmov.i%d\t%%P0, %%1 @ <mode>", width); 477 478 return templ; 479 } 480 481 /* FIXME: If the memory layout is changed in big-endian mode, output_move_vfp 482 below must be changed to output_move_neon (which will use the 483 element/structure loads/stores), and the constraint changed to 'Um' instead 484 of 'Uv'. */ 485 486 switch (which_alternative) 487 { 488 case 0: return "vmov\t%P0, %P1 @ <mode>"; 489 case 1: case 3: return output_move_vfp (operands); 490 case 2: gcc_unreachable (); 491 case 4: return "vmov\t%Q0, %R0, %P1 @ <mode>"; 492 case 5: return "vmov\t%P0, %Q1, %R1 @ <mode>"; 493 default: return output_move_double (operands); 494 } 495} 496 [(set_attr "neon_type" "neon_int_1,*,neon_vmov,*,neon_mrrc,neon_mcr_2_mcrr,*,*,*") 497 (set_attr "type" "*,f_stored,*,f_loadd,*,*,alu,load2,store2") 498 (set_attr "insn" "*,*,*,*,*,*,mov,*,*") 499 (set_attr "length" "4,4,4,4,4,4,8,8,8") 500 (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*") 501 (set_attr "neg_pool_range" "*,*,*,1008,*,*,*,1008,*")]) 502 503(define_insn "*neon_mov<mode>" 504 [(set (match_operand:VQXMOV 0 "nonimmediate_operand" 505 "=w,Un,w, w, ?r,?w,?r,?r, ?Us") 506 (match_operand:VQXMOV 1 "general_operand" 507 " w,w, Dn,Uni, w, r, r, Usi, r"))] 508 "TARGET_NEON 509 && (register_operand (operands[0], <MODE>mode) 510 || register_operand (operands[1], <MODE>mode))" 511{ 512 if (which_alternative == 2) 513 { 514 int width, is_valid; 515 static char templ[40]; 516 517 is_valid = neon_immediate_valid_for_move (operands[1], <MODE>mode, 518 &operands[1], &width); 519 520 gcc_assert (is_valid != 0); 521 522 if (width == 0) 523 return "vmov.f32\t%q0, %1 @ <mode>"; 524 else 525 sprintf (templ, "vmov.i%d\t%%q0, %%1 @ <mode>", width); 526 527 return templ; 528 } 529 530 switch (which_alternative) 531 { 532 case 0: return "vmov\t%q0, %q1 @ <mode>"; 533 case 1: case 3: return output_move_neon (operands); 534 case 2: gcc_unreachable (); 535 case 4: return "vmov\t%Q0, %R0, %e1 @ <mode>\;vmov\t%J0, %K0, %f1"; 536 case 5: return "vmov\t%e0, %Q1, %R1 @ <mode>\;vmov\t%f0, %J1, %K1"; 537 default: return output_move_quad (operands); 538 } 539} 540 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_vmov,neon_ldm_2,\ 541 neon_mrrc,neon_mcr_2_mcrr,*,*,*") 542 (set_attr "type" "*,*,*,*,*,*,alu,load4,store4") 543 (set_attr "insn" "*,*,*,*,*,*,mov,*,*") 544 (set_attr "length" "4,8,4,8,8,8,16,8,16") 545 (set_attr "pool_range" "*,*,*,1020,*,*,*,1020,*") 546 (set_attr "neg_pool_range" "*,*,*,1008,*,*,*,1008,*")]) 547 548(define_expand "movti" 549 [(set (match_operand:TI 0 "nonimmediate_operand" "") 550 (match_operand:TI 1 "general_operand" ""))] 551 "TARGET_NEON" 552{ 553 if (can_create_pseudo_p ()) 554 { 555 if (GET_CODE (operands[0]) != REG) 556 operands[1] = force_reg (TImode, operands[1]); 557 } 558}) 559 560(define_expand "mov<mode>" 561 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "") 562 (match_operand:VSTRUCT 1 "general_operand" ""))] 563 "TARGET_NEON" 564{ 565 if (can_create_pseudo_p ()) 566 { 567 if (GET_CODE (operands[0]) != REG) 568 operands[1] = force_reg (<MODE>mode, operands[1]); 569 } 570}) 571 572(define_insn "*neon_mov<mode>" 573 [(set (match_operand:VSTRUCT 0 "nonimmediate_operand" "=w,Ut,w") 574 (match_operand:VSTRUCT 1 "general_operand" " w,w, Ut"))] 575 "TARGET_NEON 576 && (register_operand (operands[0], <MODE>mode) 577 || register_operand (operands[1], <MODE>mode))" 578{ 579 switch (which_alternative) 580 { 581 case 0: return "#"; 582 case 1: case 2: return output_move_neon (operands); 583 default: gcc_unreachable (); 584 } 585} 586 [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_ldm_2") 587 (set (attr "length") (symbol_ref "arm_attr_length_move_neon (insn)"))]) 588 589(define_split 590 [(set (match_operand:EI 0 "s_register_operand" "") 591 (match_operand:EI 1 "s_register_operand" ""))] 592 "TARGET_NEON && reload_completed" 593 [(set (match_dup 0) (match_dup 1)) 594 (set (match_dup 2) (match_dup 3))] 595{ 596 int rdest = REGNO (operands[0]); 597 int rsrc = REGNO (operands[1]); 598 rtx dest[2], src[2]; 599 600 dest[0] = gen_rtx_REG (TImode, rdest); 601 src[0] = gen_rtx_REG (TImode, rsrc); 602 dest[1] = gen_rtx_REG (DImode, rdest + 4); 603 src[1] = gen_rtx_REG (DImode, rsrc + 4); 604 605 neon_disambiguate_copy (operands, dest, src, 2); 606}) 607 608(define_split 609 [(set (match_operand:OI 0 "s_register_operand" "") 610 (match_operand:OI 1 "s_register_operand" ""))] 611 "TARGET_NEON && reload_completed" 612 [(set (match_dup 0) (match_dup 1)) 613 (set (match_dup 2) (match_dup 3))] 614{ 615 int rdest = REGNO (operands[0]); 616 int rsrc = REGNO (operands[1]); 617 rtx dest[2], src[2]; 618 619 dest[0] = gen_rtx_REG (TImode, rdest); 620 src[0] = gen_rtx_REG (TImode, rsrc); 621 dest[1] = gen_rtx_REG (TImode, rdest + 4); 622 src[1] = gen_rtx_REG (TImode, rsrc + 4); 623 624 neon_disambiguate_copy (operands, dest, src, 2); 625}) 626 627(define_split 628 [(set (match_operand:CI 0 "s_register_operand" "") 629 (match_operand:CI 1 "s_register_operand" ""))] 630 "TARGET_NEON && reload_completed" 631 [(set (match_dup 0) (match_dup 1)) 632 (set (match_dup 2) (match_dup 3)) 633 (set (match_dup 4) (match_dup 5))] 634{ 635 int rdest = REGNO (operands[0]); 636 int rsrc = REGNO (operands[1]); 637 rtx dest[3], src[3]; 638 639 dest[0] = gen_rtx_REG (TImode, rdest); 640 src[0] = gen_rtx_REG (TImode, rsrc); 641 dest[1] = gen_rtx_REG (TImode, rdest + 4); 642 src[1] = gen_rtx_REG (TImode, rsrc + 4); 643 dest[2] = gen_rtx_REG (TImode, rdest + 8); 644 src[2] = gen_rtx_REG (TImode, rsrc + 8); 645 646 neon_disambiguate_copy (operands, dest, src, 3); 647}) 648 649(define_split 650 [(set (match_operand:XI 0 "s_register_operand" "") 651 (match_operand:XI 1 "s_register_operand" ""))] 652 "TARGET_NEON && reload_completed" 653 [(set (match_dup 0) (match_dup 1)) 654 (set (match_dup 2) (match_dup 3)) 655 (set (match_dup 4) (match_dup 5)) 656 (set (match_dup 6) (match_dup 7))] 657{ 658 int rdest = REGNO (operands[0]); 659 int rsrc = REGNO (operands[1]); 660 rtx dest[4], src[4]; 661 662 dest[0] = gen_rtx_REG (TImode, rdest); 663 src[0] = gen_rtx_REG (TImode, rsrc); 664 dest[1] = gen_rtx_REG (TImode, rdest + 4); 665 src[1] = gen_rtx_REG (TImode, rsrc + 4); 666 dest[2] = gen_rtx_REG (TImode, rdest + 8); 667 src[2] = gen_rtx_REG (TImode, rsrc + 8); 668 dest[3] = gen_rtx_REG (TImode, rdest + 12); 669 src[3] = gen_rtx_REG (TImode, rsrc + 12); 670 671 neon_disambiguate_copy (operands, dest, src, 4); 672}) 673 674(define_insn "vec_set<mode>_internal" 675 [(set (match_operand:VD 0 "s_register_operand" "=w") 676 (vec_merge:VD 677 (vec_duplicate:VD 678 (match_operand:<V_elem> 1 "s_register_operand" "r")) 679 (match_operand:VD 3 "s_register_operand" "0") 680 (match_operand:SI 2 "immediate_operand" "i")))] 681 "TARGET_NEON" 682{ 683 int elt = ffs ((int) INTVAL (operands[2])) - 1; 684 if (BYTES_BIG_ENDIAN) 685 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt; 686 operands[2] = GEN_INT (elt); 687 688 return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1"; 689} 690 [(set_attr "predicable" "yes") 691 (set_attr "neon_type" "neon_mcr")]) 692 693(define_insn "vec_set<mode>_internal" 694 [(set (match_operand:VQ 0 "s_register_operand" "=w") 695 (vec_merge:VQ 696 (vec_duplicate:VQ 697 (match_operand:<V_elem> 1 "s_register_operand" "r")) 698 (match_operand:VQ 3 "s_register_operand" "0") 699 (match_operand:SI 2 "immediate_operand" "i")))] 700 "TARGET_NEON" 701{ 702 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1; 703 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2; 704 int elt = elem % half_elts; 705 int hi = (elem / half_elts) * 2; 706 int regno = REGNO (operands[0]); 707 708 if (BYTES_BIG_ENDIAN) 709 elt = half_elts - 1 - elt; 710 711 operands[0] = gen_rtx_REG (<V_HALF>mode, regno + hi); 712 operands[2] = GEN_INT (elt); 713 714 return "vmov%?.<V_uf_sclr>\t%P0[%c2], %1"; 715} 716 [(set_attr "predicable" "yes") 717 (set_attr "neon_type" "neon_mcr")] 718) 719 720(define_insn "vec_setv2di_internal" 721 [(set (match_operand:V2DI 0 "s_register_operand" "=w") 722 (vec_merge:V2DI 723 (vec_duplicate:V2DI 724 (match_operand:DI 1 "s_register_operand" "r")) 725 (match_operand:V2DI 3 "s_register_operand" "0") 726 (match_operand:SI 2 "immediate_operand" "i")))] 727 "TARGET_NEON" 728{ 729 HOST_WIDE_INT elem = ffs ((int) INTVAL (operands[2])) - 1; 730 int regno = REGNO (operands[0]) + 2 * elem; 731 732 operands[0] = gen_rtx_REG (DImode, regno); 733 734 return "vmov%?.64\t%P0, %Q1, %R1"; 735} 736 [(set_attr "predicable" "yes") 737 (set_attr "neon_type" "neon_mcr_2_mcrr")] 738) 739 740(define_expand "vec_set<mode>" 741 [(match_operand:VDQ 0 "s_register_operand" "") 742 (match_operand:<V_elem> 1 "s_register_operand" "") 743 (match_operand:SI 2 "immediate_operand" "")] 744 "TARGET_NEON" 745{ 746 HOST_WIDE_INT elem = (HOST_WIDE_INT) 1 << INTVAL (operands[2]); 747 emit_insn (gen_vec_set<mode>_internal (operands[0], operands[1], 748 GEN_INT (elem), operands[0])); 749 DONE; 750}) 751 752(define_insn "vec_extract<mode>" 753 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r") 754 (vec_select:<V_elem> 755 (match_operand:VD 1 "s_register_operand" "w") 756 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))] 757 "TARGET_NEON" 758{ 759 if (BYTES_BIG_ENDIAN) 760 { 761 int elt = INTVAL (operands[2]); 762 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt; 763 operands[2] = GEN_INT (elt); 764 } 765 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]"; 766} 767 [(set_attr "predicable" "yes") 768 (set_attr "neon_type" "neon_bp_simple")] 769) 770 771(define_insn "vec_extract<mode>" 772 [(set (match_operand:<V_elem> 0 "s_register_operand" "=r") 773 (vec_select:<V_elem> 774 (match_operand:VQ 1 "s_register_operand" "w") 775 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))] 776 "TARGET_NEON" 777{ 778 int half_elts = GET_MODE_NUNITS (<MODE>mode) / 2; 779 int elt = INTVAL (operands[2]) % half_elts; 780 int hi = (INTVAL (operands[2]) / half_elts) * 2; 781 int regno = REGNO (operands[1]); 782 783 if (BYTES_BIG_ENDIAN) 784 elt = half_elts - 1 - elt; 785 786 operands[1] = gen_rtx_REG (<V_HALF>mode, regno + hi); 787 operands[2] = GEN_INT (elt); 788 789 return "vmov%?.<V_uf_sclr>\t%0, %P1[%c2]"; 790} 791 [(set_attr "predicable" "yes") 792 (set_attr "neon_type" "neon_bp_simple")] 793) 794 795(define_insn "vec_extractv2di" 796 [(set (match_operand:DI 0 "s_register_operand" "=r") 797 (vec_select:DI 798 (match_operand:V2DI 1 "s_register_operand" "w") 799 (parallel [(match_operand:SI 2 "immediate_operand" "i")])))] 800 "TARGET_NEON" 801{ 802 int regno = REGNO (operands[1]) + INTVAL (operands[2]); 803 804 operands[1] = gen_rtx_REG (DImode, regno); 805 806 return "vmov%?.64\t%Q0, %R0, %P1"; 807} 808 [(set_attr "predicable" "yes") 809 (set_attr "neon_type" "neon_int_1")] 810) 811 812(define_expand "vec_init<mode>" 813 [(match_operand:VDQ 0 "s_register_operand" "") 814 (match_operand 1 "" "")] 815 "TARGET_NEON" 816{ 817 neon_expand_vector_init (operands[0], operands[1]); 818 DONE; 819}) 820 821;; Doubleword and quadword arithmetic. 822 823;; NOTE: vadd/vsub and some other instructions also support 64-bit integer 824;; element size, which we could potentially use for "long long" operations. We 825;; don't want to do this at present though, because moving values from the 826;; vector unit to the ARM core is currently slow and 64-bit addition (etc.) is 827;; easy to do with ARM instructions anyway. 828 829(define_insn "*add<mode>3_neon" 830 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 831 (plus:VDQ (match_operand:VDQ 1 "s_register_operand" "w") 832 (match_operand:VDQ 2 "s_register_operand" "w")))] 833 "TARGET_NEON" 834 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 835 [(set (attr "neon_type") 836 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 837 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 838 (const_string "neon_fp_vadd_ddd_vabs_dd") 839 (const_string "neon_fp_vadd_qqq_vabs_qq")) 840 (const_string "neon_int_1")))] 841) 842 843(define_insn "*sub<mode>3_neon" 844 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 845 (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "w") 846 (match_operand:VDQ 2 "s_register_operand" "w")))] 847 "TARGET_NEON" 848 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 849 [(set (attr "neon_type") 850 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 851 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 852 (const_string "neon_fp_vadd_ddd_vabs_dd") 853 (const_string "neon_fp_vadd_qqq_vabs_qq")) 854 (const_string "neon_int_2")))] 855) 856 857(define_insn "*mul<mode>3_neon" 858 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 859 (mult:VDQ (match_operand:VDQ 1 "s_register_operand" "w") 860 (match_operand:VDQ 2 "s_register_operand" "w")))] 861 "TARGET_NEON" 862 "vmul.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 863 [(set (attr "neon_type") 864 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 865 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 866 (const_string "neon_fp_vadd_ddd_vabs_dd") 867 (const_string "neon_fp_vadd_qqq_vabs_qq")) 868 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 869 (if_then_else 870 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 871 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") 872 (const_string "neon_mul_qqq_8_16_32_ddd_32")) 873 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 874 (const_string "neon_mul_qqq_8_16_32_ddd_32") 875 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))] 876) 877 878(define_insn "*mul<mode>3add<mode>_neon" 879 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 880 (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w") 881 (match_operand:VDQ 3 "s_register_operand" "w")) 882 (match_operand:VDQ 1 "s_register_operand" "0")))] 883 "TARGET_NEON" 884 "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" 885 [(set (attr "neon_type") 886 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 887 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 888 (const_string "neon_fp_vmla_ddd") 889 (const_string "neon_fp_vmla_qqq")) 890 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 891 (if_then_else 892 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 893 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") 894 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")) 895 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 896 (const_string "neon_mla_qqq_8_16") 897 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))] 898) 899 900(define_insn "*mul<mode>3neg<mode>add<mode>_neon" 901 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 902 (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0") 903 (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w") 904 (match_operand:VDQ 3 "s_register_operand" "w"))))] 905 "TARGET_NEON" 906 "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" 907 [(set (attr "neon_type") 908 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 909 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 910 (const_string "neon_fp_vmla_ddd") 911 (const_string "neon_fp_vmla_qqq")) 912 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 913 (if_then_else 914 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 915 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") 916 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")) 917 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 918 (const_string "neon_mla_qqq_8_16") 919 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))] 920) 921 922(define_insn "ior<mode>3" 923 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w") 924 (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0") 925 (match_operand:VDQ 2 "neon_logic_op2" "w,Dl")))] 926 "TARGET_NEON" 927{ 928 switch (which_alternative) 929 { 930 case 0: return "vorr\t%<V_reg>0, %<V_reg>1, %<V_reg>2"; 931 case 1: return neon_output_logic_immediate ("vorr", &operands[2], 932 <MODE>mode, 0, VALID_NEON_QREG_MODE (<MODE>mode)); 933 default: gcc_unreachable (); 934 } 935} 936 [(set_attr "neon_type" "neon_int_1")] 937) 938 939(define_insn "iordi3_neon" 940 [(set (match_operand:DI 0 "s_register_operand" "=w,w") 941 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0") 942 (match_operand:DI 2 "neon_logic_op2" "w,Dl")] 943 UNSPEC_VORR))] 944 "TARGET_NEON" 945{ 946 switch (which_alternative) 947 { 948 case 0: return "vorr\t%P0, %P1, %P2"; 949 case 1: return neon_output_logic_immediate ("vorr", &operands[2], 950 DImode, 0, VALID_NEON_QREG_MODE (DImode)); 951 default: gcc_unreachable (); 952 } 953} 954 [(set_attr "neon_type" "neon_int_1")] 955) 956 957;; The concrete forms of the Neon immediate-logic instructions are vbic and 958;; vorr. We support the pseudo-instruction vand instead, because that 959;; corresponds to the canonical form the middle-end expects to use for 960;; immediate bitwise-ANDs. 961 962(define_insn "and<mode>3" 963 [(set (match_operand:VDQ 0 "s_register_operand" "=w,w") 964 (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0") 965 (match_operand:VDQ 2 "neon_inv_logic_op2" "w,DL")))] 966 "TARGET_NEON" 967{ 968 switch (which_alternative) 969 { 970 case 0: return "vand\t%<V_reg>0, %<V_reg>1, %<V_reg>2"; 971 case 1: return neon_output_logic_immediate ("vand", &operands[2], 972 <MODE>mode, 1, VALID_NEON_QREG_MODE (<MODE>mode)); 973 default: gcc_unreachable (); 974 } 975} 976 [(set_attr "neon_type" "neon_int_1")] 977) 978 979(define_insn "anddi3_neon" 980 [(set (match_operand:DI 0 "s_register_operand" "=w,w") 981 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w,0") 982 (match_operand:DI 2 "neon_inv_logic_op2" "w,DL")] 983 UNSPEC_VAND))] 984 "TARGET_NEON" 985{ 986 switch (which_alternative) 987 { 988 case 0: return "vand\t%P0, %P1, %P2"; 989 case 1: return neon_output_logic_immediate ("vand", &operands[2], 990 DImode, 1, VALID_NEON_QREG_MODE (DImode)); 991 default: gcc_unreachable (); 992 } 993} 994 [(set_attr "neon_type" "neon_int_1")] 995) 996 997(define_insn "orn<mode>3_neon" 998 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 999 (ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w") 1000 (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))))] 1001 "TARGET_NEON" 1002 "vorn\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1003 [(set_attr "neon_type" "neon_int_1")] 1004) 1005 1006(define_insn "orndi3_neon" 1007 [(set (match_operand:DI 0 "s_register_operand" "=w") 1008 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") 1009 (match_operand:DI 2 "s_register_operand" "w")] 1010 UNSPEC_VORN))] 1011 "TARGET_NEON" 1012 "vorn\t%P0, %P1, %P2" 1013 [(set_attr "neon_type" "neon_int_1")] 1014) 1015 1016(define_insn "bic<mode>3_neon" 1017 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 1018 (and:VDQ (match_operand:VDQ 1 "s_register_operand" "w") 1019 (not:VDQ (match_operand:VDQ 2 "s_register_operand" "w"))))] 1020 "TARGET_NEON" 1021 "vbic\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1022 [(set_attr "neon_type" "neon_int_1")] 1023) 1024 1025(define_insn "bicdi3_neon" 1026 [(set (match_operand:DI 0 "s_register_operand" "=w") 1027 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") 1028 (match_operand:DI 2 "s_register_operand" "w")] 1029 UNSPEC_VBIC))] 1030 "TARGET_NEON" 1031 "vbic\t%P0, %P1, %P2" 1032 [(set_attr "neon_type" "neon_int_1")] 1033) 1034 1035(define_insn "xor<mode>3" 1036 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 1037 (xor:VDQ (match_operand:VDQ 1 "s_register_operand" "w") 1038 (match_operand:VDQ 2 "s_register_operand" "w")))] 1039 "TARGET_NEON" 1040 "veor\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1041 [(set_attr "neon_type" "neon_int_1")] 1042) 1043 1044(define_insn "xordi3_neon" 1045 [(set (match_operand:DI 0 "s_register_operand" "=w") 1046 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") 1047 (match_operand:DI 2 "s_register_operand" "w")] 1048 UNSPEC_VEOR))] 1049 "TARGET_NEON" 1050 "veor\t%P0, %P1, %P2" 1051 [(set_attr "neon_type" "neon_int_1")] 1052) 1053 1054(define_insn "one_cmpl<mode>2" 1055 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 1056 (not:VDQ (match_operand:VDQ 1 "s_register_operand" "w")))] 1057 "TARGET_NEON" 1058 "vmvn\t%<V_reg>0, %<V_reg>1" 1059 [(set_attr "neon_type" "neon_int_1")] 1060) 1061 1062(define_insn "abs<mode>2" 1063 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 1064 (abs:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))] 1065 "TARGET_NEON" 1066 "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1" 1067 [(set (attr "neon_type") 1068 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1069 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1070 (const_string "neon_fp_vadd_ddd_vabs_dd") 1071 (const_string "neon_fp_vadd_qqq_vabs_qq")) 1072 (const_string "neon_int_3")))] 1073) 1074 1075(define_insn "neg<mode>2" 1076 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 1077 (neg:VDQW (match_operand:VDQW 1 "s_register_operand" "w")))] 1078 "TARGET_NEON" 1079 "vneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1" 1080 [(set (attr "neon_type") 1081 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1082 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1083 (const_string "neon_fp_vadd_ddd_vabs_dd") 1084 (const_string "neon_fp_vadd_qqq_vabs_qq")) 1085 (const_string "neon_int_3")))] 1086) 1087 1088(define_insn "*umin<mode>3_neon" 1089 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 1090 (umin:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") 1091 (match_operand:VDQIW 2 "s_register_operand" "w")))] 1092 "TARGET_NEON" 1093 "vmin.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1094 [(set_attr "neon_type" "neon_int_5")] 1095) 1096 1097(define_insn "*umax<mode>3_neon" 1098 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 1099 (umax:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") 1100 (match_operand:VDQIW 2 "s_register_operand" "w")))] 1101 "TARGET_NEON" 1102 "vmax.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1103 [(set_attr "neon_type" "neon_int_5")] 1104) 1105 1106(define_insn "*smin<mode>3_neon" 1107 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 1108 (smin:VDQW (match_operand:VDQW 1 "s_register_operand" "w") 1109 (match_operand:VDQW 2 "s_register_operand" "w")))] 1110 "TARGET_NEON" 1111 "vmin.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1112 [(set (attr "neon_type") 1113 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1114 (const_string "neon_fp_vadd_ddd_vabs_dd") 1115 (const_string "neon_int_5")))] 1116) 1117 1118(define_insn "*smax<mode>3_neon" 1119 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 1120 (smax:VDQW (match_operand:VDQW 1 "s_register_operand" "w") 1121 (match_operand:VDQW 2 "s_register_operand" "w")))] 1122 "TARGET_NEON" 1123 "vmax.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1124 [(set (attr "neon_type") 1125 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1126 (const_string "neon_fp_vadd_ddd_vabs_dd") 1127 (const_string "neon_int_5")))] 1128) 1129 1130; TODO: V2DI shifts are current disabled because there are bugs in the 1131; generic vectorizer code. It ends up creating a V2DI constructor with 1132; SImode elements. 1133 1134(define_insn "vashl<mode>3" 1135 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 1136 (ashift:VDQIW (match_operand:VDQIW 1 "s_register_operand" "w") 1137 (match_operand:VDQIW 2 "s_register_operand" "w")))] 1138 "TARGET_NEON" 1139 "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1140 [(set (attr "neon_type") 1141 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1142 (const_string "neon_vshl_ddd") 1143 (const_string "neon_shift_3")))] 1144) 1145 1146; Used for implementing logical shift-right, which is a left-shift by a negative 1147; amount, with signed operands. This is essentially the same as ashl<mode>3 1148; above, but using an unspec in case GCC tries anything tricky with negative 1149; shift amounts. 1150 1151(define_insn "ashl<mode>3_signed" 1152 [(set (match_operand:VDQI 0 "s_register_operand" "=w") 1153 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w") 1154 (match_operand:VDQI 2 "s_register_operand" "w")] 1155 UNSPEC_ASHIFT_SIGNED))] 1156 "TARGET_NEON" 1157 "vshl.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1158 [(set (attr "neon_type") 1159 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1160 (const_string "neon_vshl_ddd") 1161 (const_string "neon_shift_3")))] 1162) 1163 1164; Used for implementing logical shift-right, which is a left-shift by a negative 1165; amount, with unsigned operands. 1166 1167(define_insn "ashl<mode>3_unsigned" 1168 [(set (match_operand:VDQI 0 "s_register_operand" "=w") 1169 (unspec:VDQI [(match_operand:VDQI 1 "s_register_operand" "w") 1170 (match_operand:VDQI 2 "s_register_operand" "w")] 1171 UNSPEC_ASHIFT_UNSIGNED))] 1172 "TARGET_NEON" 1173 "vshl.<V_u_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1174 [(set (attr "neon_type") 1175 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1176 (const_string "neon_vshl_ddd") 1177 (const_string "neon_shift_3")))] 1178) 1179 1180(define_expand "vashr<mode>3" 1181 [(set (match_operand:VDQIW 0 "s_register_operand" "") 1182 (ashiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") 1183 (match_operand:VDQIW 2 "s_register_operand" "")))] 1184 "TARGET_NEON" 1185{ 1186 rtx neg = gen_reg_rtx (<MODE>mode); 1187 1188 emit_insn (gen_neg<mode>2 (neg, operands[2])); 1189 emit_insn (gen_ashl<mode>3_signed (operands[0], operands[1], neg)); 1190 1191 DONE; 1192}) 1193 1194(define_expand "vlshr<mode>3" 1195 [(set (match_operand:VDQIW 0 "s_register_operand" "") 1196 (lshiftrt:VDQIW (match_operand:VDQIW 1 "s_register_operand" "") 1197 (match_operand:VDQIW 2 "s_register_operand" "")))] 1198 "TARGET_NEON" 1199{ 1200 rtx neg = gen_reg_rtx (<MODE>mode); 1201 1202 emit_insn (gen_neg<mode>2 (neg, operands[2])); 1203 emit_insn (gen_ashl<mode>3_unsigned (operands[0], operands[1], neg)); 1204 1205 DONE; 1206}) 1207 1208;; Widening operations 1209 1210(define_insn "widen_ssum<mode>3" 1211 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1212 (plus:<V_widen> (sign_extend:<V_widen> 1213 (match_operand:VW 1 "s_register_operand" "%w")) 1214 (match_operand:<V_widen> 2 "s_register_operand" "w")))] 1215 "TARGET_NEON" 1216 "vaddw.<V_s_elem>\t%q0, %q2, %P1" 1217 [(set_attr "neon_type" "neon_int_3")] 1218) 1219 1220(define_insn "widen_usum<mode>3" 1221 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1222 (plus:<V_widen> (zero_extend:<V_widen> 1223 (match_operand:VW 1 "s_register_operand" "%w")) 1224 (match_operand:<V_widen> 2 "s_register_operand" "w")))] 1225 "TARGET_NEON" 1226 "vaddw.<V_u_elem>\t%q0, %q2, %P1" 1227 [(set_attr "neon_type" "neon_int_3")] 1228) 1229 1230;; VEXT can be used to synthesize coarse whole-vector shifts with 8-bit 1231;; shift-count granularity. That's good enough for the middle-end's current 1232;; needs. 1233 1234(define_expand "vec_shr_<mode>" 1235 [(match_operand:VDQ 0 "s_register_operand" "") 1236 (match_operand:VDQ 1 "s_register_operand" "") 1237 (match_operand:SI 2 "const_multiple_of_8_operand" "")] 1238 "TARGET_NEON" 1239{ 1240 rtx zero_reg; 1241 HOST_WIDE_INT num_bits = INTVAL (operands[2]); 1242 const int width = GET_MODE_BITSIZE (<MODE>mode); 1243 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode; 1244 rtx (*gen_ext) (rtx, rtx, rtx, rtx) = 1245 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi; 1246 1247 if (num_bits == width) 1248 { 1249 emit_move_insn (operands[0], operands[1]); 1250 DONE; 1251 } 1252 1253 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode)); 1254 operands[0] = gen_lowpart (bvecmode, operands[0]); 1255 operands[1] = gen_lowpart (bvecmode, operands[1]); 1256 1257 emit_insn (gen_ext (operands[0], operands[1], zero_reg, 1258 GEN_INT (num_bits / BITS_PER_UNIT))); 1259 DONE; 1260}) 1261 1262(define_expand "vec_shl_<mode>" 1263 [(match_operand:VDQ 0 "s_register_operand" "") 1264 (match_operand:VDQ 1 "s_register_operand" "") 1265 (match_operand:SI 2 "const_multiple_of_8_operand" "")] 1266 "TARGET_NEON" 1267{ 1268 rtx zero_reg; 1269 HOST_WIDE_INT num_bits = INTVAL (operands[2]); 1270 const int width = GET_MODE_BITSIZE (<MODE>mode); 1271 const enum machine_mode bvecmode = (width == 128) ? V16QImode : V8QImode; 1272 rtx (*gen_ext) (rtx, rtx, rtx, rtx) = 1273 (width == 128) ? gen_neon_vextv16qi : gen_neon_vextv8qi; 1274 1275 if (num_bits == 0) 1276 { 1277 emit_move_insn (operands[0], CONST0_RTX (<MODE>mode)); 1278 DONE; 1279 } 1280 1281 num_bits = width - num_bits; 1282 1283 zero_reg = force_reg (bvecmode, CONST0_RTX (bvecmode)); 1284 operands[0] = gen_lowpart (bvecmode, operands[0]); 1285 operands[1] = gen_lowpart (bvecmode, operands[1]); 1286 1287 emit_insn (gen_ext (operands[0], zero_reg, operands[1], 1288 GEN_INT (num_bits / BITS_PER_UNIT))); 1289 DONE; 1290}) 1291 1292;; Helpers for quad-word reduction operations 1293 1294; Add (or smin, smax...) the low N/2 elements of the N-element vector 1295; operand[1] to the high N/2 elements of same. Put the result in operand[0], an 1296; N/2-element vector. 1297 1298(define_insn "quad_halves_<code>v4si" 1299 [(set (match_operand:V2SI 0 "s_register_operand" "=w") 1300 (vqh_ops:V2SI 1301 (vec_select:V2SI (match_operand:V4SI 1 "s_register_operand" "w") 1302 (parallel [(const_int 0) (const_int 1)])) 1303 (vec_select:V2SI (match_dup 1) 1304 (parallel [(const_int 2) (const_int 3)]))))] 1305 "TARGET_NEON" 1306 "<VQH_mnem>.<VQH_sign>32\t%P0, %e1, %f1" 1307 [(set_attr "vqh_mnem" "<VQH_mnem>") 1308 (set (attr "neon_type") 1309 (if_then_else (eq_attr "vqh_mnem" "vadd") 1310 (const_string "neon_int_1") (const_string "neon_int_5")))] 1311) 1312 1313(define_insn "quad_halves_<code>v4sf" 1314 [(set (match_operand:V2SF 0 "s_register_operand" "=w") 1315 (vqhs_ops:V2SF 1316 (vec_select:V2SF (match_operand:V4SF 1 "s_register_operand" "w") 1317 (parallel [(const_int 0) (const_int 1)])) 1318 (vec_select:V2SF (match_dup 1) 1319 (parallel [(const_int 2) (const_int 3)]))))] 1320 "TARGET_NEON" 1321 "<VQH_mnem>.f32\t%P0, %e1, %f1" 1322 [(set_attr "vqh_mnem" "<VQH_mnem>") 1323 (set (attr "neon_type") 1324 (if_then_else (eq_attr "vqh_mnem" "vadd") 1325 (const_string "neon_int_1") (const_string "neon_int_5")))] 1326) 1327 1328(define_insn "quad_halves_<code>v8hi" 1329 [(set (match_operand:V4HI 0 "s_register_operand" "+w") 1330 (vqh_ops:V4HI 1331 (vec_select:V4HI (match_operand:V8HI 1 "s_register_operand" "w") 1332 (parallel [(const_int 0) (const_int 1) 1333 (const_int 2) (const_int 3)])) 1334 (vec_select:V4HI (match_dup 1) 1335 (parallel [(const_int 4) (const_int 5) 1336 (const_int 6) (const_int 7)]))))] 1337 "TARGET_NEON" 1338 "<VQH_mnem>.<VQH_sign>16\t%P0, %e1, %f1" 1339 [(set_attr "vqh_mnem" "<VQH_mnem>") 1340 (set (attr "neon_type") 1341 (if_then_else (eq_attr "vqh_mnem" "vadd") 1342 (const_string "neon_int_1") (const_string "neon_int_5")))] 1343) 1344 1345(define_insn "quad_halves_<code>v16qi" 1346 [(set (match_operand:V8QI 0 "s_register_operand" "+w") 1347 (vqh_ops:V8QI 1348 (vec_select:V8QI (match_operand:V16QI 1 "s_register_operand" "w") 1349 (parallel [(const_int 0) (const_int 1) 1350 (const_int 2) (const_int 3) 1351 (const_int 4) (const_int 5) 1352 (const_int 6) (const_int 7)])) 1353 (vec_select:V8QI (match_dup 1) 1354 (parallel [(const_int 8) (const_int 9) 1355 (const_int 10) (const_int 11) 1356 (const_int 12) (const_int 13) 1357 (const_int 14) (const_int 15)]))))] 1358 "TARGET_NEON" 1359 "<VQH_mnem>.<VQH_sign>8\t%P0, %e1, %f1" 1360 [(set_attr "vqh_mnem" "<VQH_mnem>") 1361 (set (attr "neon_type") 1362 (if_then_else (eq_attr "vqh_mnem" "vadd") 1363 (const_string "neon_int_1") (const_string "neon_int_5")))] 1364) 1365 1366; FIXME: We wouldn't need the following insns if we could write subregs of 1367; vector registers. Make an attempt at removing unnecessary moves, though 1368; we're really at the mercy of the register allocator. 1369 1370(define_insn "move_lo_quad_v4si" 1371 [(set (match_operand:V4SI 0 "s_register_operand" "+w") 1372 (vec_concat:V4SI 1373 (match_operand:V2SI 1 "s_register_operand" "w") 1374 (vec_select:V2SI (match_dup 0) 1375 (parallel [(const_int 2) (const_int 3)]))))] 1376 "TARGET_NEON" 1377{ 1378 int dest = REGNO (operands[0]); 1379 int src = REGNO (operands[1]); 1380 1381 if (dest != src) 1382 return "vmov\t%e0, %P1"; 1383 else 1384 return ""; 1385} 1386 [(set_attr "neon_type" "neon_bp_simple")] 1387) 1388 1389(define_insn "move_lo_quad_v4sf" 1390 [(set (match_operand:V4SF 0 "s_register_operand" "+w") 1391 (vec_concat:V4SF 1392 (match_operand:V2SF 1 "s_register_operand" "w") 1393 (vec_select:V2SF (match_dup 0) 1394 (parallel [(const_int 2) (const_int 3)]))))] 1395 "TARGET_NEON" 1396{ 1397 int dest = REGNO (operands[0]); 1398 int src = REGNO (operands[1]); 1399 1400 if (dest != src) 1401 return "vmov\t%e0, %P1"; 1402 else 1403 return ""; 1404} 1405 [(set_attr "neon_type" "neon_bp_simple")] 1406) 1407 1408(define_insn "move_lo_quad_v8hi" 1409 [(set (match_operand:V8HI 0 "s_register_operand" "+w") 1410 (vec_concat:V8HI 1411 (match_operand:V4HI 1 "s_register_operand" "w") 1412 (vec_select:V4HI (match_dup 0) 1413 (parallel [(const_int 4) (const_int 5) 1414 (const_int 6) (const_int 7)]))))] 1415 "TARGET_NEON" 1416{ 1417 int dest = REGNO (operands[0]); 1418 int src = REGNO (operands[1]); 1419 1420 if (dest != src) 1421 return "vmov\t%e0, %P1"; 1422 else 1423 return ""; 1424} 1425 [(set_attr "neon_type" "neon_bp_simple")] 1426) 1427 1428(define_insn "move_lo_quad_v16qi" 1429 [(set (match_operand:V16QI 0 "s_register_operand" "+w") 1430 (vec_concat:V16QI 1431 (match_operand:V8QI 1 "s_register_operand" "w") 1432 (vec_select:V8QI (match_dup 0) 1433 (parallel [(const_int 8) (const_int 9) 1434 (const_int 10) (const_int 11) 1435 (const_int 12) (const_int 13) 1436 (const_int 14) (const_int 15)]))))] 1437 "TARGET_NEON" 1438{ 1439 int dest = REGNO (operands[0]); 1440 int src = REGNO (operands[1]); 1441 1442 if (dest != src) 1443 return "vmov\t%e0, %P1"; 1444 else 1445 return ""; 1446} 1447 [(set_attr "neon_type" "neon_bp_simple")] 1448) 1449 1450;; Reduction operations 1451 1452(define_expand "reduc_splus_<mode>" 1453 [(match_operand:VD 0 "s_register_operand" "") 1454 (match_operand:VD 1 "s_register_operand" "")] 1455 "TARGET_NEON" 1456{ 1457 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, 1458 &gen_neon_vpadd_internal<mode>); 1459 DONE; 1460}) 1461 1462(define_expand "reduc_splus_<mode>" 1463 [(match_operand:VQ 0 "s_register_operand" "") 1464 (match_operand:VQ 1 "s_register_operand" "")] 1465 "TARGET_NEON" 1466{ 1467 rtx step1 = gen_reg_rtx (<V_HALF>mode); 1468 rtx res_d = gen_reg_rtx (<V_HALF>mode); 1469 1470 emit_insn (gen_quad_halves_plus<mode> (step1, operands[1])); 1471 emit_insn (gen_reduc_splus_<V_half> (res_d, step1)); 1472 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); 1473 1474 DONE; 1475}) 1476 1477(define_insn "reduc_splus_v2di" 1478 [(set (match_operand:V2DI 0 "s_register_operand" "=w") 1479 (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")] 1480 UNSPEC_VPADD))] 1481 "TARGET_NEON" 1482 "vadd.i64\t%e0, %e1, %f1" 1483 [(set_attr "neon_type" "neon_int_1")] 1484) 1485 1486;; NEON does not distinguish between signed and unsigned addition except on 1487;; widening operations. 1488(define_expand "reduc_uplus_<mode>" 1489 [(match_operand:VDQI 0 "s_register_operand" "") 1490 (match_operand:VDQI 1 "s_register_operand" "")] 1491 "TARGET_NEON" 1492{ 1493 emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1])); 1494 DONE; 1495}) 1496 1497(define_expand "reduc_smin_<mode>" 1498 [(match_operand:VD 0 "s_register_operand" "") 1499 (match_operand:VD 1 "s_register_operand" "")] 1500 "TARGET_NEON" 1501{ 1502 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, 1503 &gen_neon_vpsmin<mode>); 1504 DONE; 1505}) 1506 1507(define_expand "reduc_smin_<mode>" 1508 [(match_operand:VQ 0 "s_register_operand" "") 1509 (match_operand:VQ 1 "s_register_operand" "")] 1510 "TARGET_NEON" 1511{ 1512 rtx step1 = gen_reg_rtx (<V_HALF>mode); 1513 rtx res_d = gen_reg_rtx (<V_HALF>mode); 1514 1515 emit_insn (gen_quad_halves_smin<mode> (step1, operands[1])); 1516 emit_insn (gen_reduc_smin_<V_half> (res_d, step1)); 1517 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); 1518 1519 DONE; 1520}) 1521 1522(define_expand "reduc_smax_<mode>" 1523 [(match_operand:VD 0 "s_register_operand" "") 1524 (match_operand:VD 1 "s_register_operand" "")] 1525 "TARGET_NEON" 1526{ 1527 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, 1528 &gen_neon_vpsmax<mode>); 1529 DONE; 1530}) 1531 1532(define_expand "reduc_smax_<mode>" 1533 [(match_operand:VQ 0 "s_register_operand" "") 1534 (match_operand:VQ 1 "s_register_operand" "")] 1535 "TARGET_NEON" 1536{ 1537 rtx step1 = gen_reg_rtx (<V_HALF>mode); 1538 rtx res_d = gen_reg_rtx (<V_HALF>mode); 1539 1540 emit_insn (gen_quad_halves_smax<mode> (step1, operands[1])); 1541 emit_insn (gen_reduc_smax_<V_half> (res_d, step1)); 1542 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); 1543 1544 DONE; 1545}) 1546 1547(define_expand "reduc_umin_<mode>" 1548 [(match_operand:VDI 0 "s_register_operand" "") 1549 (match_operand:VDI 1 "s_register_operand" "")] 1550 "TARGET_NEON" 1551{ 1552 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, 1553 &gen_neon_vpumin<mode>); 1554 DONE; 1555}) 1556 1557(define_expand "reduc_umin_<mode>" 1558 [(match_operand:VQI 0 "s_register_operand" "") 1559 (match_operand:VQI 1 "s_register_operand" "")] 1560 "TARGET_NEON" 1561{ 1562 rtx step1 = gen_reg_rtx (<V_HALF>mode); 1563 rtx res_d = gen_reg_rtx (<V_HALF>mode); 1564 1565 emit_insn (gen_quad_halves_umin<mode> (step1, operands[1])); 1566 emit_insn (gen_reduc_umin_<V_half> (res_d, step1)); 1567 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); 1568 1569 DONE; 1570}) 1571 1572(define_expand "reduc_umax_<mode>" 1573 [(match_operand:VDI 0 "s_register_operand" "") 1574 (match_operand:VDI 1 "s_register_operand" "")] 1575 "TARGET_NEON" 1576{ 1577 neon_pairwise_reduce (operands[0], operands[1], <MODE>mode, 1578 &gen_neon_vpumax<mode>); 1579 DONE; 1580}) 1581 1582(define_expand "reduc_umax_<mode>" 1583 [(match_operand:VQI 0 "s_register_operand" "") 1584 (match_operand:VQI 1 "s_register_operand" "")] 1585 "TARGET_NEON" 1586{ 1587 rtx step1 = gen_reg_rtx (<V_HALF>mode); 1588 rtx res_d = gen_reg_rtx (<V_HALF>mode); 1589 1590 emit_insn (gen_quad_halves_umax<mode> (step1, operands[1])); 1591 emit_insn (gen_reduc_umax_<V_half> (res_d, step1)); 1592 emit_insn (gen_move_lo_quad_<mode> (operands[0], res_d)); 1593 1594 DONE; 1595}) 1596 1597(define_insn "neon_vpadd_internal<mode>" 1598 [(set (match_operand:VD 0 "s_register_operand" "=w") 1599 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") 1600 (match_operand:VD 2 "s_register_operand" "w")] 1601 UNSPEC_VPADD))] 1602 "TARGET_NEON" 1603 "vpadd.<V_if_elem>\t%P0, %P1, %P2" 1604 ;; Assume this schedules like vadd. 1605 [(set (attr "neon_type") 1606 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1607 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1608 (const_string "neon_fp_vadd_ddd_vabs_dd") 1609 (const_string "neon_fp_vadd_qqq_vabs_qq")) 1610 (const_string "neon_int_1")))] 1611) 1612 1613(define_insn "neon_vpsmin<mode>" 1614 [(set (match_operand:VD 0 "s_register_operand" "=w") 1615 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") 1616 (match_operand:VD 2 "s_register_operand" "w")] 1617 UNSPEC_VPSMIN))] 1618 "TARGET_NEON" 1619 "vpmin.<V_s_elem>\t%P0, %P1, %P2" 1620 ;; Assume this schedules like vmin. 1621 [(set (attr "neon_type") 1622 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1623 (const_string "neon_fp_vadd_ddd_vabs_dd") 1624 (const_string "neon_int_5")))] 1625) 1626 1627(define_insn "neon_vpsmax<mode>" 1628 [(set (match_operand:VD 0 "s_register_operand" "=w") 1629 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") 1630 (match_operand:VD 2 "s_register_operand" "w")] 1631 UNSPEC_VPSMAX))] 1632 "TARGET_NEON" 1633 "vpmax.<V_s_elem>\t%P0, %P1, %P2" 1634 ;; Assume this schedules like vmax. 1635 [(set (attr "neon_type") 1636 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1637 (const_string "neon_fp_vadd_ddd_vabs_dd") 1638 (const_string "neon_int_5")))] 1639) 1640 1641(define_insn "neon_vpumin<mode>" 1642 [(set (match_operand:VDI 0 "s_register_operand" "=w") 1643 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w") 1644 (match_operand:VDI 2 "s_register_operand" "w")] 1645 UNSPEC_VPUMIN))] 1646 "TARGET_NEON" 1647 "vpmin.<V_u_elem>\t%P0, %P1, %P2" 1648 ;; Assume this schedules like umin. 1649 [(set_attr "neon_type" "neon_int_5")] 1650) 1651 1652(define_insn "neon_vpumax<mode>" 1653 [(set (match_operand:VDI 0 "s_register_operand" "=w") 1654 (unspec:VDI [(match_operand:VDI 1 "s_register_operand" "w") 1655 (match_operand:VDI 2 "s_register_operand" "w")] 1656 UNSPEC_VPUMAX))] 1657 "TARGET_NEON" 1658 "vpmax.<V_u_elem>\t%P0, %P1, %P2" 1659 ;; Assume this schedules like umax. 1660 [(set_attr "neon_type" "neon_int_5")] 1661) 1662 1663;; Saturating arithmetic 1664 1665; NOTE: Neon supports many more saturating variants of instructions than the 1666; following, but these are all GCC currently understands. 1667; FIXME: Actually, GCC doesn't know how to create saturating add/sub by itself 1668; yet either, although these patterns may be used by intrinsics when they're 1669; added. 1670 1671(define_insn "*ss_add<mode>_neon" 1672 [(set (match_operand:VD 0 "s_register_operand" "=w") 1673 (ss_plus:VD (match_operand:VD 1 "s_register_operand" "w") 1674 (match_operand:VD 2 "s_register_operand" "w")))] 1675 "TARGET_NEON" 1676 "vqadd.<V_s_elem>\t%P0, %P1, %P2" 1677 [(set_attr "neon_type" "neon_int_4")] 1678) 1679 1680(define_insn "*us_add<mode>_neon" 1681 [(set (match_operand:VD 0 "s_register_operand" "=w") 1682 (us_plus:VD (match_operand:VD 1 "s_register_operand" "w") 1683 (match_operand:VD 2 "s_register_operand" "w")))] 1684 "TARGET_NEON" 1685 "vqadd.<V_u_elem>\t%P0, %P1, %P2" 1686 [(set_attr "neon_type" "neon_int_4")] 1687) 1688 1689(define_insn "*ss_sub<mode>_neon" 1690 [(set (match_operand:VD 0 "s_register_operand" "=w") 1691 (ss_minus:VD (match_operand:VD 1 "s_register_operand" "w") 1692 (match_operand:VD 2 "s_register_operand" "w")))] 1693 "TARGET_NEON" 1694 "vqsub.<V_s_elem>\t%P0, %P1, %P2" 1695 [(set_attr "neon_type" "neon_int_5")] 1696) 1697 1698(define_insn "*us_sub<mode>_neon" 1699 [(set (match_operand:VD 0 "s_register_operand" "=w") 1700 (us_minus:VD (match_operand:VD 1 "s_register_operand" "w") 1701 (match_operand:VD 2 "s_register_operand" "w")))] 1702 "TARGET_NEON" 1703 "vqsub.<V_u_elem>\t%P0, %P1, %P2" 1704 [(set_attr "neon_type" "neon_int_5")] 1705) 1706 1707;; Patterns for builtins. 1708 1709; good for plain vadd, vaddq. 1710 1711(define_insn "neon_vadd<mode>" 1712 [(set (match_operand:VDQX 0 "s_register_operand" "=w") 1713 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w") 1714 (match_operand:VDQX 2 "s_register_operand" "w") 1715 (match_operand:SI 3 "immediate_operand" "i")] 1716 UNSPEC_VADD))] 1717 "TARGET_NEON" 1718 "vadd.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1719 [(set (attr "neon_type") 1720 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1721 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1722 (const_string "neon_fp_vadd_ddd_vabs_dd") 1723 (const_string "neon_fp_vadd_qqq_vabs_qq")) 1724 (const_string "neon_int_1")))] 1725) 1726 1727; operand 3 represents in bits: 1728; bit 0: signed (vs unsigned). 1729; bit 1: rounding (vs none). 1730 1731(define_insn "neon_vaddl<mode>" 1732 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1733 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w") 1734 (match_operand:VDI 2 "s_register_operand" "w") 1735 (match_operand:SI 3 "immediate_operand" "i")] 1736 UNSPEC_VADDL))] 1737 "TARGET_NEON" 1738 "vaddl.%T3%#<V_sz_elem>\t%q0, %P1, %P2" 1739 [(set_attr "neon_type" "neon_int_3")] 1740) 1741 1742(define_insn "neon_vaddw<mode>" 1743 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1744 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w") 1745 (match_operand:VDI 2 "s_register_operand" "w") 1746 (match_operand:SI 3 "immediate_operand" "i")] 1747 UNSPEC_VADDW))] 1748 "TARGET_NEON" 1749 "vaddw.%T3%#<V_sz_elem>\t%q0, %q1, %P2" 1750 [(set_attr "neon_type" "neon_int_2")] 1751) 1752 1753; vhadd and vrhadd. 1754 1755(define_insn "neon_vhadd<mode>" 1756 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 1757 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") 1758 (match_operand:VDQIW 2 "s_register_operand" "w") 1759 (match_operand:SI 3 "immediate_operand" "i")] 1760 UNSPEC_VHADD))] 1761 "TARGET_NEON" 1762 "v%O3hadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1763 [(set_attr "neon_type" "neon_int_4")] 1764) 1765 1766(define_insn "neon_vqadd<mode>" 1767 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 1768 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") 1769 (match_operand:VDQIX 2 "s_register_operand" "w") 1770 (match_operand:SI 3 "immediate_operand" "i")] 1771 UNSPEC_VQADD))] 1772 "TARGET_NEON" 1773 "vqadd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1774 [(set_attr "neon_type" "neon_int_4")] 1775) 1776 1777(define_insn "neon_vaddhn<mode>" 1778 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") 1779 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") 1780 (match_operand:VN 2 "s_register_operand" "w") 1781 (match_operand:SI 3 "immediate_operand" "i")] 1782 UNSPEC_VADDHN))] 1783 "TARGET_NEON" 1784 "v%O3addhn.<V_if_elem>\t%P0, %q1, %q2" 1785 [(set_attr "neon_type" "neon_int_4")] 1786) 1787 1788(define_insn "neon_vmul<mode>" 1789 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 1790 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") 1791 (match_operand:VDQW 2 "s_register_operand" "w") 1792 (match_operand:SI 3 "immediate_operand" "i")] 1793 UNSPEC_VMUL))] 1794 "TARGET_NEON" 1795 "vmul.%F3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1796 [(set (attr "neon_type") 1797 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1798 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1799 (const_string "neon_fp_vadd_ddd_vabs_dd") 1800 (const_string "neon_fp_vadd_qqq_vabs_qq")) 1801 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1802 (if_then_else 1803 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1804 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") 1805 (const_string "neon_mul_qqq_8_16_32_ddd_32")) 1806 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1807 (const_string "neon_mul_qqq_8_16_32_ddd_32") 1808 (const_string "neon_mul_qqq_8_16_32_ddd_32")))))] 1809) 1810 1811(define_insn "neon_vmla<mode>" 1812 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 1813 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0") 1814 (match_operand:VDQW 2 "s_register_operand" "w") 1815 (match_operand:VDQW 3 "s_register_operand" "w") 1816 (match_operand:SI 4 "immediate_operand" "i")] 1817 UNSPEC_VMLA))] 1818 "TARGET_NEON" 1819 "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" 1820 [(set (attr "neon_type") 1821 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1822 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1823 (const_string "neon_fp_vmla_ddd") 1824 (const_string "neon_fp_vmla_qqq")) 1825 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1826 (if_then_else 1827 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1828 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") 1829 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")) 1830 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1831 (const_string "neon_mla_qqq_8_16") 1832 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))] 1833) 1834 1835(define_insn "neon_vmlal<mode>" 1836 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1837 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 1838 (match_operand:VW 2 "s_register_operand" "w") 1839 (match_operand:VW 3 "s_register_operand" "w") 1840 (match_operand:SI 4 "immediate_operand" "i")] 1841 UNSPEC_VMLAL))] 1842 "TARGET_NEON" 1843 "vmlal.%T4%#<V_sz_elem>\t%q0, %P2, %P3" 1844 [(set (attr "neon_type") 1845 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1846 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") 1847 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] 1848) 1849 1850(define_insn "neon_vmls<mode>" 1851 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 1852 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0") 1853 (match_operand:VDQW 2 "s_register_operand" "w") 1854 (match_operand:VDQW 3 "s_register_operand" "w") 1855 (match_operand:SI 4 "immediate_operand" "i")] 1856 UNSPEC_VMLS))] 1857 "TARGET_NEON" 1858 "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" 1859 [(set (attr "neon_type") 1860 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1861 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1862 (const_string "neon_fp_vmla_ddd") 1863 (const_string "neon_fp_vmla_qqq")) 1864 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1865 (if_then_else 1866 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1867 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") 1868 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")) 1869 (if_then_else 1870 (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1871 (const_string "neon_mla_qqq_8_16") 1872 (const_string "neon_mla_qqq_32_qqd_32_scalar")))))] 1873) 1874 1875(define_insn "neon_vmlsl<mode>" 1876 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1877 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 1878 (match_operand:VW 2 "s_register_operand" "w") 1879 (match_operand:VW 3 "s_register_operand" "w") 1880 (match_operand:SI 4 "immediate_operand" "i")] 1881 UNSPEC_VMLSL))] 1882 "TARGET_NEON" 1883 "vmlsl.%T4%#<V_sz_elem>\t%q0, %P2, %P3" 1884 [(set (attr "neon_type") 1885 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1886 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") 1887 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] 1888) 1889 1890(define_insn "neon_vqdmulh<mode>" 1891 [(set (match_operand:VMDQI 0 "s_register_operand" "=w") 1892 (unspec:VMDQI [(match_operand:VMDQI 1 "s_register_operand" "w") 1893 (match_operand:VMDQI 2 "s_register_operand" "w") 1894 (match_operand:SI 3 "immediate_operand" "i")] 1895 UNSPEC_VQDMULH))] 1896 "TARGET_NEON" 1897 "vq%O3dmulh.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1898 [(set (attr "neon_type") 1899 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1900 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1901 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") 1902 (const_string "neon_mul_qqq_8_16_32_ddd_32")) 1903 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1904 (const_string "neon_mul_qqq_8_16_32_ddd_32") 1905 (const_string "neon_mul_qqq_8_16_32_ddd_32"))))] 1906) 1907 1908(define_insn "neon_vqdmlal<mode>" 1909 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1910 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 1911 (match_operand:VMDI 2 "s_register_operand" "w") 1912 (match_operand:VMDI 3 "s_register_operand" "w") 1913 (match_operand:SI 4 "immediate_operand" "i")] 1914 UNSPEC_VQDMLAL))] 1915 "TARGET_NEON" 1916 "vqdmlal.<V_s_elem>\t%q0, %P2, %P3" 1917 [(set (attr "neon_type") 1918 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1919 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") 1920 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] 1921) 1922 1923(define_insn "neon_vqdmlsl<mode>" 1924 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1925 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 1926 (match_operand:VMDI 2 "s_register_operand" "w") 1927 (match_operand:VMDI 3 "s_register_operand" "w") 1928 (match_operand:SI 4 "immediate_operand" "i")] 1929 UNSPEC_VQDMLSL))] 1930 "TARGET_NEON" 1931 "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3" 1932 [(set (attr "neon_type") 1933 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1934 (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long") 1935 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] 1936) 1937 1938(define_insn "neon_vmull<mode>" 1939 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1940 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w") 1941 (match_operand:VW 2 "s_register_operand" "w") 1942 (match_operand:SI 3 "immediate_operand" "i")] 1943 UNSPEC_VMULL))] 1944 "TARGET_NEON" 1945 "vmull.%T3%#<V_sz_elem>\t%q0, %P1, %P2" 1946 [(set (attr "neon_type") 1947 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1948 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") 1949 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] 1950) 1951 1952(define_insn "neon_vqdmull<mode>" 1953 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1954 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w") 1955 (match_operand:VMDI 2 "s_register_operand" "w") 1956 (match_operand:SI 3 "immediate_operand" "i")] 1957 UNSPEC_VQDMULL))] 1958 "TARGET_NEON" 1959 "vqdmull.<V_s_elem>\t%q0, %P1, %P2" 1960 [(set (attr "neon_type") 1961 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 1962 (const_string "neon_mul_ddd_8_16_qdd_16_8_long_32_16_long") 1963 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] 1964) 1965 1966(define_insn "neon_vsub<mode>" 1967 [(set (match_operand:VDQX 0 "s_register_operand" "=w") 1968 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w") 1969 (match_operand:VDQX 2 "s_register_operand" "w") 1970 (match_operand:SI 3 "immediate_operand" "i")] 1971 UNSPEC_VSUB))] 1972 "TARGET_NEON" 1973 "vsub.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 1974 [(set (attr "neon_type") 1975 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 1976 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 1977 (const_string "neon_fp_vadd_ddd_vabs_dd") 1978 (const_string "neon_fp_vadd_qqq_vabs_qq")) 1979 (const_string "neon_int_2")))] 1980) 1981 1982(define_insn "neon_vsubl<mode>" 1983 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1984 (unspec:<V_widen> [(match_operand:VDI 1 "s_register_operand" "w") 1985 (match_operand:VDI 2 "s_register_operand" "w") 1986 (match_operand:SI 3 "immediate_operand" "i")] 1987 UNSPEC_VSUBL))] 1988 "TARGET_NEON" 1989 "vsubl.%T3%#<V_sz_elem>\t%q0, %P1, %P2" 1990 [(set_attr "neon_type" "neon_int_2")] 1991) 1992 1993(define_insn "neon_vsubw<mode>" 1994 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 1995 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "w") 1996 (match_operand:VDI 2 "s_register_operand" "w") 1997 (match_operand:SI 3 "immediate_operand" "i")] 1998 UNSPEC_VSUBW))] 1999 "TARGET_NEON" 2000 "vsubw.%T3%#<V_sz_elem>\t%q0, %q1, %P2" 2001 [(set_attr "neon_type" "neon_int_2")] 2002) 2003 2004(define_insn "neon_vqsub<mode>" 2005 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 2006 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") 2007 (match_operand:VDQIX 2 "s_register_operand" "w") 2008 (match_operand:SI 3 "immediate_operand" "i")] 2009 UNSPEC_VQSUB))] 2010 "TARGET_NEON" 2011 "vqsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2012 [(set_attr "neon_type" "neon_int_5")] 2013) 2014 2015(define_insn "neon_vhsub<mode>" 2016 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 2017 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") 2018 (match_operand:VDQIW 2 "s_register_operand" "w") 2019 (match_operand:SI 3 "immediate_operand" "i")] 2020 UNSPEC_VHSUB))] 2021 "TARGET_NEON" 2022 "vhsub.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2023 [(set_attr "neon_type" "neon_int_5")] 2024) 2025 2026(define_insn "neon_vsubhn<mode>" 2027 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") 2028 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") 2029 (match_operand:VN 2 "s_register_operand" "w") 2030 (match_operand:SI 3 "immediate_operand" "i")] 2031 UNSPEC_VSUBHN))] 2032 "TARGET_NEON" 2033 "v%O3subhn.<V_if_elem>\t%P0, %q1, %q2" 2034 [(set_attr "neon_type" "neon_int_4")] 2035) 2036 2037(define_insn "neon_vceq<mode>" 2038 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") 2039 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w") 2040 (match_operand:VDQW 2 "s_register_operand" "w") 2041 (match_operand:SI 3 "immediate_operand" "i")] 2042 UNSPEC_VCEQ))] 2043 "TARGET_NEON" 2044 "vceq.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2045 [(set (attr "neon_type") 2046 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2047 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2048 (const_string "neon_fp_vadd_ddd_vabs_dd") 2049 (const_string "neon_fp_vadd_qqq_vabs_qq")) 2050 (const_string "neon_int_5")))] 2051) 2052 2053(define_insn "neon_vcge<mode>" 2054 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") 2055 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w") 2056 (match_operand:VDQW 2 "s_register_operand" "w") 2057 (match_operand:SI 3 "immediate_operand" "i")] 2058 UNSPEC_VCGE))] 2059 "TARGET_NEON" 2060 "vcge.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2061 [(set (attr "neon_type") 2062 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2063 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2064 (const_string "neon_fp_vadd_ddd_vabs_dd") 2065 (const_string "neon_fp_vadd_qqq_vabs_qq")) 2066 (const_string "neon_int_5")))] 2067) 2068 2069(define_insn "neon_vcgt<mode>" 2070 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") 2071 (unspec:<V_cmp_result> [(match_operand:VDQW 1 "s_register_operand" "w") 2072 (match_operand:VDQW 2 "s_register_operand" "w") 2073 (match_operand:SI 3 "immediate_operand" "i")] 2074 UNSPEC_VCGT))] 2075 "TARGET_NEON" 2076 "vcgt.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2077 [(set (attr "neon_type") 2078 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2079 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2080 (const_string "neon_fp_vadd_ddd_vabs_dd") 2081 (const_string "neon_fp_vadd_qqq_vabs_qq")) 2082 (const_string "neon_int_5")))] 2083) 2084 2085(define_insn "neon_vcage<mode>" 2086 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") 2087 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w") 2088 (match_operand:VCVTF 2 "s_register_operand" "w") 2089 (match_operand:SI 3 "immediate_operand" "i")] 2090 UNSPEC_VCAGE))] 2091 "TARGET_NEON" 2092 "vacge.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2093 [(set (attr "neon_type") 2094 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2095 (const_string "neon_fp_vadd_ddd_vabs_dd") 2096 (const_string "neon_fp_vadd_qqq_vabs_qq")))] 2097) 2098 2099(define_insn "neon_vcagt<mode>" 2100 [(set (match_operand:<V_cmp_result> 0 "s_register_operand" "=w") 2101 (unspec:<V_cmp_result> [(match_operand:VCVTF 1 "s_register_operand" "w") 2102 (match_operand:VCVTF 2 "s_register_operand" "w") 2103 (match_operand:SI 3 "immediate_operand" "i")] 2104 UNSPEC_VCAGT))] 2105 "TARGET_NEON" 2106 "vacgt.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2107 [(set (attr "neon_type") 2108 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2109 (const_string "neon_fp_vadd_ddd_vabs_dd") 2110 (const_string "neon_fp_vadd_qqq_vabs_qq")))] 2111) 2112 2113(define_insn "neon_vtst<mode>" 2114 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 2115 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") 2116 (match_operand:VDQIW 2 "s_register_operand" "w") 2117 (match_operand:SI 3 "immediate_operand" "i")] 2118 UNSPEC_VTST))] 2119 "TARGET_NEON" 2120 "vtst.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2121 [(set_attr "neon_type" "neon_int_4")] 2122) 2123 2124(define_insn "neon_vabd<mode>" 2125 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 2126 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") 2127 (match_operand:VDQW 2 "s_register_operand" "w") 2128 (match_operand:SI 3 "immediate_operand" "i")] 2129 UNSPEC_VABD))] 2130 "TARGET_NEON" 2131 "vabd.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2132 [(set (attr "neon_type") 2133 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2134 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2135 (const_string "neon_fp_vadd_ddd_vabs_dd") 2136 (const_string "neon_fp_vadd_qqq_vabs_qq")) 2137 (const_string "neon_int_5")))] 2138) 2139 2140(define_insn "neon_vabdl<mode>" 2141 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 2142 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w") 2143 (match_operand:VW 2 "s_register_operand" "w") 2144 (match_operand:SI 3 "immediate_operand" "i")] 2145 UNSPEC_VABDL))] 2146 "TARGET_NEON" 2147 "vabdl.%T3%#<V_sz_elem>\t%q0, %P1, %P2" 2148 [(set_attr "neon_type" "neon_int_5")] 2149) 2150 2151(define_insn "neon_vaba<mode>" 2152 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 2153 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "0") 2154 (match_operand:VDQIW 2 "s_register_operand" "w") 2155 (match_operand:VDQIW 3 "s_register_operand" "w") 2156 (match_operand:SI 4 "immediate_operand" "i")] 2157 UNSPEC_VABA))] 2158 "TARGET_NEON" 2159 "vaba.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3" 2160 [(set (attr "neon_type") 2161 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2162 (const_string "neon_vaba") (const_string "neon_vaba_qqq")))] 2163) 2164 2165(define_insn "neon_vabal<mode>" 2166 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 2167 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 2168 (match_operand:VW 2 "s_register_operand" "w") 2169 (match_operand:VW 3 "s_register_operand" "w") 2170 (match_operand:SI 4 "immediate_operand" "i")] 2171 UNSPEC_VABAL))] 2172 "TARGET_NEON" 2173 "vabal.%T4%#<V_sz_elem>\t%q0, %P2, %P3" 2174 [(set_attr "neon_type" "neon_vaba")] 2175) 2176 2177(define_insn "neon_vmax<mode>" 2178 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 2179 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") 2180 (match_operand:VDQW 2 "s_register_operand" "w") 2181 (match_operand:SI 3 "immediate_operand" "i")] 2182 UNSPEC_VMAX))] 2183 "TARGET_NEON" 2184 "vmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2185 [(set (attr "neon_type") 2186 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2187 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2188 (const_string "neon_fp_vadd_ddd_vabs_dd") 2189 (const_string "neon_fp_vadd_qqq_vabs_qq")) 2190 (const_string "neon_int_5")))] 2191) 2192 2193(define_insn "neon_vmin<mode>" 2194 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 2195 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") 2196 (match_operand:VDQW 2 "s_register_operand" "w") 2197 (match_operand:SI 3 "immediate_operand" "i")] 2198 UNSPEC_VMIN))] 2199 "TARGET_NEON" 2200 "vmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2201 [(set (attr "neon_type") 2202 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2203 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2204 (const_string "neon_fp_vadd_ddd_vabs_dd") 2205 (const_string "neon_fp_vadd_qqq_vabs_qq")) 2206 (const_string "neon_int_5")))] 2207) 2208 2209(define_expand "neon_vpadd<mode>" 2210 [(match_operand:VD 0 "s_register_operand" "=w") 2211 (match_operand:VD 1 "s_register_operand" "w") 2212 (match_operand:VD 2 "s_register_operand" "w") 2213 (match_operand:SI 3 "immediate_operand" "i")] 2214 "TARGET_NEON" 2215{ 2216 emit_insn (gen_neon_vpadd_internal<mode> (operands[0], operands[1], 2217 operands[2])); 2218 DONE; 2219}) 2220 2221(define_insn "neon_vpaddl<mode>" 2222 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w") 2223 (unspec:<V_double_width> [(match_operand:VDQIW 1 "s_register_operand" "w") 2224 (match_operand:SI 2 "immediate_operand" "i")] 2225 UNSPEC_VPADDL))] 2226 "TARGET_NEON" 2227 "vpaddl.%T2%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1" 2228 ;; Assume this schedules like vaddl. 2229 [(set_attr "neon_type" "neon_int_3")] 2230) 2231 2232(define_insn "neon_vpadal<mode>" 2233 [(set (match_operand:<V_double_width> 0 "s_register_operand" "=w") 2234 (unspec:<V_double_width> [(match_operand:<V_double_width> 1 "s_register_operand" "0") 2235 (match_operand:VDQIW 2 "s_register_operand" "w") 2236 (match_operand:SI 3 "immediate_operand" "i")] 2237 UNSPEC_VPADAL))] 2238 "TARGET_NEON" 2239 "vpadal.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2" 2240 ;; Assume this schedules like vpadd. 2241 [(set_attr "neon_type" "neon_int_1")] 2242) 2243 2244(define_insn "neon_vpmax<mode>" 2245 [(set (match_operand:VD 0 "s_register_operand" "=w") 2246 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") 2247 (match_operand:VD 2 "s_register_operand" "w") 2248 (match_operand:SI 3 "immediate_operand" "i")] 2249 UNSPEC_VPMAX))] 2250 "TARGET_NEON" 2251 "vpmax.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2252 ;; Assume this schedules like vmax. 2253 [(set (attr "neon_type") 2254 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2255 (const_string "neon_fp_vadd_ddd_vabs_dd") 2256 (const_string "neon_int_5")))] 2257) 2258 2259(define_insn "neon_vpmin<mode>" 2260 [(set (match_operand:VD 0 "s_register_operand" "=w") 2261 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") 2262 (match_operand:VD 2 "s_register_operand" "w") 2263 (match_operand:SI 3 "immediate_operand" "i")] 2264 UNSPEC_VPMIN))] 2265 "TARGET_NEON" 2266 "vpmin.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2267 ;; Assume this schedules like vmin. 2268 [(set (attr "neon_type") 2269 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2270 (const_string "neon_fp_vadd_ddd_vabs_dd") 2271 (const_string "neon_int_5")))] 2272) 2273 2274(define_insn "neon_vrecps<mode>" 2275 [(set (match_operand:VCVTF 0 "s_register_operand" "=w") 2276 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w") 2277 (match_operand:VCVTF 2 "s_register_operand" "w") 2278 (match_operand:SI 3 "immediate_operand" "i")] 2279 UNSPEC_VRECPS))] 2280 "TARGET_NEON" 2281 "vrecps.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2282 [(set (attr "neon_type") 2283 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2284 (const_string "neon_fp_vrecps_vrsqrts_ddd") 2285 (const_string "neon_fp_vrecps_vrsqrts_qqq")))] 2286) 2287 2288(define_insn "neon_vrsqrts<mode>" 2289 [(set (match_operand:VCVTF 0 "s_register_operand" "=w") 2290 (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w") 2291 (match_operand:VCVTF 2 "s_register_operand" "w") 2292 (match_operand:SI 3 "immediate_operand" "i")] 2293 UNSPEC_VRSQRTS))] 2294 "TARGET_NEON" 2295 "vrsqrts.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 2296 [(set (attr "neon_type") 2297 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2298 (const_string "neon_fp_vrecps_vrsqrts_ddd") 2299 (const_string "neon_fp_vrecps_vrsqrts_qqq")))] 2300) 2301 2302(define_insn "neon_vabs<mode>" 2303 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 2304 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "w") 2305 (match_operand:SI 2 "immediate_operand" "i")] 2306 UNSPEC_VABS))] 2307 "TARGET_NEON" 2308 "vabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1" 2309 [(set (attr "neon_type") 2310 (if_then_else (ior (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2311 (ne (symbol_ref "<Is_float_mode>") (const_int 0))) 2312 (if_then_else 2313 (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2314 (const_string "neon_fp_vadd_ddd_vabs_dd") 2315 (const_string "neon_fp_vadd_qqq_vabs_qq")) 2316 (const_string "neon_vqneg_vqabs")))] 2317) 2318 2319(define_insn "neon_vqabs<mode>" 2320 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 2321 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") 2322 (match_operand:SI 2 "immediate_operand" "i")] 2323 UNSPEC_VQABS))] 2324 "TARGET_NEON" 2325 "vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1" 2326 [(set_attr "neon_type" "neon_vqneg_vqabs")] 2327) 2328 2329(define_expand "neon_vneg<mode>" 2330 [(match_operand:VDQW 0 "s_register_operand" "") 2331 (match_operand:VDQW 1 "s_register_operand" "") 2332 (match_operand:SI 2 "immediate_operand" "")] 2333 "TARGET_NEON" 2334{ 2335 emit_insn (gen_neg<mode>2 (operands[0], operands[1])); 2336 DONE; 2337}) 2338 2339(define_insn "neon_vqneg<mode>" 2340 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 2341 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") 2342 (match_operand:SI 2 "immediate_operand" "i")] 2343 UNSPEC_VQNEG))] 2344 "TARGET_NEON" 2345 "vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1" 2346 [(set_attr "neon_type" "neon_vqneg_vqabs")] 2347) 2348 2349(define_insn "neon_vcls<mode>" 2350 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 2351 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") 2352 (match_operand:SI 2 "immediate_operand" "i")] 2353 UNSPEC_VCLS))] 2354 "TARGET_NEON" 2355 "vcls.<V_s_elem>\t%<V_reg>0, %<V_reg>1" 2356 [(set_attr "neon_type" "neon_int_1")] 2357) 2358 2359(define_insn "neon_vclz<mode>" 2360 [(set (match_operand:VDQIW 0 "s_register_operand" "=w") 2361 (unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w") 2362 (match_operand:SI 2 "immediate_operand" "i")] 2363 UNSPEC_VCLZ))] 2364 "TARGET_NEON" 2365 "vclz.<V_if_elem>\t%<V_reg>0, %<V_reg>1" 2366 [(set_attr "neon_type" "neon_int_1")] 2367) 2368 2369(define_insn "neon_vcnt<mode>" 2370 [(set (match_operand:VE 0 "s_register_operand" "=w") 2371 (unspec:VE [(match_operand:VE 1 "s_register_operand" "w") 2372 (match_operand:SI 2 "immediate_operand" "i")] 2373 UNSPEC_VCNT))] 2374 "TARGET_NEON" 2375 "vcnt.<V_sz_elem>\t%<V_reg>0, %<V_reg>1" 2376 [(set_attr "neon_type" "neon_int_1")] 2377) 2378 2379(define_insn "neon_vrecpe<mode>" 2380 [(set (match_operand:V32 0 "s_register_operand" "=w") 2381 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w") 2382 (match_operand:SI 2 "immediate_operand" "i")] 2383 UNSPEC_VRECPE))] 2384 "TARGET_NEON" 2385 "vrecpe.<V_u_elem>\t%<V_reg>0, %<V_reg>1" 2386 [(set (attr "neon_type") 2387 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2388 (const_string "neon_fp_vadd_ddd_vabs_dd") 2389 (const_string "neon_fp_vadd_qqq_vabs_qq")))] 2390) 2391 2392(define_insn "neon_vrsqrte<mode>" 2393 [(set (match_operand:V32 0 "s_register_operand" "=w") 2394 (unspec:V32 [(match_operand:V32 1 "s_register_operand" "w") 2395 (match_operand:SI 2 "immediate_operand" "i")] 2396 UNSPEC_VRSQRTE))] 2397 "TARGET_NEON" 2398 "vrsqrte.<V_u_elem>\t%<V_reg>0, %<V_reg>1" 2399 [(set (attr "neon_type") 2400 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2401 (const_string "neon_fp_vadd_ddd_vabs_dd") 2402 (const_string "neon_fp_vadd_qqq_vabs_qq")))] 2403) 2404 2405(define_expand "neon_vmvn<mode>" 2406 [(match_operand:VDQIW 0 "s_register_operand" "") 2407 (match_operand:VDQIW 1 "s_register_operand" "") 2408 (match_operand:SI 2 "immediate_operand" "")] 2409 "TARGET_NEON" 2410{ 2411 emit_insn (gen_one_cmpl<mode>2 (operands[0], operands[1])); 2412 DONE; 2413}) 2414 2415(define_insn "neon_vget_lane<mode>_sext_internal" 2416 [(set (match_operand:SI 0 "s_register_operand" "=r") 2417 (sign_extend:SI 2418 (vec_select:<V_elem> 2419 (match_operand:VD 1 "s_register_operand" "w") 2420 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] 2421 "TARGET_NEON" 2422{ 2423 if (BYTES_BIG_ENDIAN) 2424 { 2425 int elt = INTVAL (operands[2]); 2426 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt; 2427 operands[2] = GEN_INT (elt); 2428 } 2429 return "vmov%?.s<V_sz_elem>\t%0, %P1[%c2]"; 2430} 2431 [(set_attr "predicable" "yes") 2432 (set_attr "neon_type" "neon_bp_simple")] 2433) 2434 2435(define_insn "neon_vget_lane<mode>_zext_internal" 2436 [(set (match_operand:SI 0 "s_register_operand" "=r") 2437 (zero_extend:SI 2438 (vec_select:<V_elem> 2439 (match_operand:VD 1 "s_register_operand" "w") 2440 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] 2441 "TARGET_NEON" 2442{ 2443 if (BYTES_BIG_ENDIAN) 2444 { 2445 int elt = INTVAL (operands[2]); 2446 elt = GET_MODE_NUNITS (<MODE>mode) - 1 - elt; 2447 operands[2] = GEN_INT (elt); 2448 } 2449 return "vmov%?.u<V_sz_elem>\t%0, %P1[%c2]"; 2450} 2451 [(set_attr "predicable" "yes") 2452 (set_attr "neon_type" "neon_bp_simple")] 2453) 2454 2455(define_insn "neon_vget_lane<mode>_sext_internal" 2456 [(set (match_operand:SI 0 "s_register_operand" "=r") 2457 (sign_extend:SI 2458 (vec_select:<V_elem> 2459 (match_operand:VQ 1 "s_register_operand" "w") 2460 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] 2461 "TARGET_NEON" 2462{ 2463 rtx ops[3]; 2464 int regno = REGNO (operands[1]); 2465 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2; 2466 unsigned int elt = INTVAL (operands[2]); 2467 unsigned int elt_adj = elt % halfelts; 2468 2469 if (BYTES_BIG_ENDIAN) 2470 elt_adj = halfelts - 1 - elt_adj; 2471 2472 ops[0] = operands[0]; 2473 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts)); 2474 ops[2] = GEN_INT (elt_adj); 2475 output_asm_insn ("vmov%?.s<V_sz_elem>\t%0, %P1[%c2]", ops); 2476 2477 return ""; 2478} 2479 [(set_attr "predicable" "yes") 2480 (set_attr "neon_type" "neon_bp_simple")] 2481) 2482 2483(define_insn "neon_vget_lane<mode>_zext_internal" 2484 [(set (match_operand:SI 0 "s_register_operand" "=r") 2485 (zero_extend:SI 2486 (vec_select:<V_elem> 2487 (match_operand:VQ 1 "s_register_operand" "w") 2488 (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] 2489 "TARGET_NEON" 2490{ 2491 rtx ops[3]; 2492 int regno = REGNO (operands[1]); 2493 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2; 2494 unsigned int elt = INTVAL (operands[2]); 2495 unsigned int elt_adj = elt % halfelts; 2496 2497 if (BYTES_BIG_ENDIAN) 2498 elt_adj = halfelts - 1 - elt_adj; 2499 2500 ops[0] = operands[0]; 2501 ops[1] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts)); 2502 ops[2] = GEN_INT (elt_adj); 2503 output_asm_insn ("vmov%?.u<V_sz_elem>\t%0, %P1[%c2]", ops); 2504 2505 return ""; 2506} 2507 [(set_attr "predicable" "yes") 2508 (set_attr "neon_type" "neon_bp_simple")] 2509) 2510 2511(define_expand "neon_vget_lane<mode>" 2512 [(match_operand:<V_ext> 0 "s_register_operand" "") 2513 (match_operand:VDQW 1 "s_register_operand" "") 2514 (match_operand:SI 2 "immediate_operand" "") 2515 (match_operand:SI 3 "immediate_operand" "")] 2516 "TARGET_NEON" 2517{ 2518 HOST_WIDE_INT magic = INTVAL (operands[3]); 2519 rtx insn; 2520 2521 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode)); 2522 2523 if (BYTES_BIG_ENDIAN) 2524 { 2525 /* The intrinsics are defined in terms of a model where the 2526 element ordering in memory is vldm order, whereas the generic 2527 RTL is defined in terms of a model where the element ordering 2528 in memory is array order. Convert the lane number to conform 2529 to this model. */ 2530 unsigned int elt = INTVAL (operands[2]); 2531 unsigned int reg_nelts 2532 = 64 / GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)); 2533 elt ^= reg_nelts - 1; 2534 operands[2] = GEN_INT (elt); 2535 } 2536 2537 if ((magic & 3) == 3 || GET_MODE_BITSIZE (GET_MODE_INNER (<MODE>mode)) == 32) 2538 insn = gen_vec_extract<mode> (operands[0], operands[1], operands[2]); 2539 else 2540 { 2541 if ((magic & 1) != 0) 2542 insn = gen_neon_vget_lane<mode>_sext_internal (operands[0], operands[1], 2543 operands[2]); 2544 else 2545 insn = gen_neon_vget_lane<mode>_zext_internal (operands[0], operands[1], 2546 operands[2]); 2547 } 2548 emit_insn (insn); 2549 DONE; 2550}) 2551 2552; Operand 3 (info word) is ignored because it does nothing useful with 64-bit 2553; elements. 2554 2555(define_insn "neon_vget_lanedi" 2556 [(set (match_operand:DI 0 "s_register_operand" "=r") 2557 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") 2558 (match_operand:SI 2 "immediate_operand" "i") 2559 (match_operand:SI 3 "immediate_operand" "i")] 2560 UNSPEC_VGET_LANE))] 2561 "TARGET_NEON" 2562{ 2563 neon_lane_bounds (operands[2], 0, 1); 2564 return "vmov%?\t%Q0, %R0, %P1 @ di"; 2565} 2566 [(set_attr "predicable" "yes") 2567 (set_attr "neon_type" "neon_bp_simple")] 2568) 2569 2570(define_insn "neon_vget_lanev2di" 2571 [(set (match_operand:DI 0 "s_register_operand" "=r") 2572 (unspec:DI [(match_operand:V2DI 1 "s_register_operand" "w") 2573 (match_operand:SI 2 "immediate_operand" "i") 2574 (match_operand:SI 3 "immediate_operand" "i")] 2575 UNSPEC_VGET_LANE))] 2576 "TARGET_NEON" 2577{ 2578 rtx ops[2]; 2579 unsigned int regno = REGNO (operands[1]); 2580 unsigned int elt = INTVAL (operands[2]); 2581 2582 neon_lane_bounds (operands[2], 0, 2); 2583 2584 ops[0] = operands[0]; 2585 ops[1] = gen_rtx_REG (DImode, regno + 2 * elt); 2586 output_asm_insn ("vmov%?\t%Q0, %R0, %P1 @ v2di", ops); 2587 2588 return ""; 2589} 2590 [(set_attr "predicable" "yes") 2591 (set_attr "neon_type" "neon_bp_simple")] 2592) 2593 2594(define_insn "neon_vset_lane<mode>" 2595 [(set (match_operand:VD 0 "s_register_operand" "=w") 2596 (unspec:VD [(match_operand:<V_elem> 1 "s_register_operand" "r") 2597 (match_operand:VD 2 "s_register_operand" "0") 2598 (match_operand:SI 3 "immediate_operand" "i")] 2599 UNSPEC_VSET_LANE))] 2600 "TARGET_NEON" 2601{ 2602 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); 2603 return "vmov%?.<V_sz_elem>\t%P0[%c3], %1"; 2604} 2605 [(set_attr "predicable" "yes") 2606 (set_attr "neon_type" "neon_bp_simple")] 2607) 2608 2609; See neon_vget_lanedi comment for reasons operands 2 & 3 are ignored. 2610 2611(define_insn "neon_vset_lanedi" 2612 [(set (match_operand:DI 0 "s_register_operand" "=w") 2613 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r") 2614 (match_operand:DI 2 "s_register_operand" "0") 2615 (match_operand:SI 3 "immediate_operand" "i")] 2616 UNSPEC_VSET_LANE))] 2617 "TARGET_NEON" 2618{ 2619 neon_lane_bounds (operands[3], 0, 1); 2620 return "vmov%?\t%P0, %Q1, %R1 @ di"; 2621} 2622 [(set_attr "predicable" "yes") 2623 (set_attr "neon_type" "neon_bp_simple")] 2624) 2625 2626(define_insn "neon_vset_lane<mode>" 2627 [(set (match_operand:VQ 0 "s_register_operand" "=w") 2628 (unspec:VQ [(match_operand:<V_elem> 1 "s_register_operand" "r") 2629 (match_operand:VQ 2 "s_register_operand" "0") 2630 (match_operand:SI 3 "immediate_operand" "i")] 2631 UNSPEC_VSET_LANE))] 2632 "TARGET_NEON" 2633{ 2634 rtx ops[4]; 2635 unsigned int regno = REGNO (operands[0]); 2636 unsigned int halfelts = GET_MODE_NUNITS (<MODE>mode) / 2; 2637 unsigned int elt = INTVAL (operands[3]); 2638 2639 neon_lane_bounds (operands[3], 0, halfelts * 2); 2640 2641 ops[0] = gen_rtx_REG (<V_HALF>mode, regno + 2 * (elt / halfelts)); 2642 ops[1] = operands[1]; 2643 ops[2] = GEN_INT (elt % halfelts); 2644 output_asm_insn ("vmov%?.<V_sz_elem>\t%P0[%c2], %1", ops); 2645 2646 return ""; 2647} 2648 [(set_attr "predicable" "yes") 2649 (set_attr "neon_type" "neon_bp_simple")] 2650) 2651 2652(define_insn "neon_vset_lanev2di" 2653 [(set (match_operand:V2DI 0 "s_register_operand" "=w") 2654 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r") 2655 (match_operand:V2DI 2 "s_register_operand" "0") 2656 (match_operand:SI 3 "immediate_operand" "i")] 2657 UNSPEC_VSET_LANE))] 2658 "TARGET_NEON" 2659{ 2660 rtx ops[2]; 2661 unsigned int regno = REGNO (operands[0]); 2662 unsigned int elt = INTVAL (operands[3]); 2663 2664 neon_lane_bounds (operands[3], 0, 2); 2665 2666 ops[0] = gen_rtx_REG (DImode, regno + 2 * elt); 2667 ops[1] = operands[1]; 2668 output_asm_insn ("vmov%?\t%P0, %Q1, %R1 @ v2di", ops); 2669 2670 return ""; 2671} 2672 [(set_attr "predicable" "yes") 2673 (set_attr "neon_type" "neon_bp_simple")] 2674) 2675 2676(define_expand "neon_vcreate<mode>" 2677 [(match_operand:VDX 0 "s_register_operand" "") 2678 (match_operand:DI 1 "general_operand" "")] 2679 "TARGET_NEON" 2680{ 2681 rtx src = gen_lowpart (<MODE>mode, operands[1]); 2682 emit_move_insn (operands[0], src); 2683 DONE; 2684}) 2685 2686(define_insn "neon_vdup_n<mode>" 2687 [(set (match_operand:VX 0 "s_register_operand" "=w") 2688 (unspec:VX [(match_operand:<V_elem> 1 "s_register_operand" "r")] 2689 UNSPEC_VDUP_N))] 2690 "TARGET_NEON" 2691 "vdup%?.<V_sz_elem>\t%<V_reg>0, %1" 2692 ;; Assume this schedules like vmov. 2693 [(set_attr "predicable" "yes") 2694 (set_attr "neon_type" "neon_bp_simple")] 2695) 2696 2697(define_insn "neon_vdup_n<mode>" 2698 [(set (match_operand:V32 0 "s_register_operand" "=w,w") 2699 (unspec:V32 [(match_operand:<V_elem> 1 "s_register_operand" "r,t")] 2700 UNSPEC_VDUP_N))] 2701 "TARGET_NEON" 2702 "@ 2703 vdup%?.<V_sz_elem>\t%<V_reg>0, %1 2704 vdup%?.<V_sz_elem>\t%<V_reg>0, %y1" 2705 ;; Assume this schedules like vmov. 2706 [(set_attr "predicable" "yes") 2707 (set_attr "neon_type" "neon_bp_simple")] 2708) 2709 2710(define_insn "neon_vdup_ndi" 2711 [(set (match_operand:DI 0 "s_register_operand" "=w") 2712 (unspec:DI [(match_operand:DI 1 "s_register_operand" "r")] 2713 UNSPEC_VDUP_N))] 2714 "TARGET_NEON" 2715 "vmov%?\t%P0, %Q1, %R1" 2716 [(set_attr "predicable" "yes") 2717 (set_attr "neon_type" "neon_bp_simple")] 2718) 2719 2720(define_insn "neon_vdup_nv2di" 2721 [(set (match_operand:V2DI 0 "s_register_operand" "=w") 2722 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "r")] 2723 UNSPEC_VDUP_N))] 2724 "TARGET_NEON" 2725 "vmov%?\t%e0, %Q1, %R1\;vmov%?\t%f0, %Q1, %R1" 2726 [(set_attr "predicable" "yes") 2727 (set_attr "length" "8") 2728 (set_attr "neon_type" "neon_bp_simple")] 2729) 2730 2731(define_insn "neon_vdup_lane<mode>" 2732 [(set (match_operand:VD 0 "s_register_operand" "=w") 2733 (unspec:VD [(match_operand:VD 1 "s_register_operand" "w") 2734 (match_operand:SI 2 "immediate_operand" "i")] 2735 UNSPEC_VDUP_LANE))] 2736 "TARGET_NEON" 2737{ 2738 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<MODE>mode)); 2739 return "vdup.<V_sz_elem>\t%P0, %P1[%c2]"; 2740} 2741 ;; Assume this schedules like vmov. 2742 [(set_attr "neon_type" "neon_bp_simple")] 2743) 2744 2745(define_insn "neon_vdup_lane<mode>" 2746 [(set (match_operand:VQ 0 "s_register_operand" "=w") 2747 (unspec:VQ [(match_operand:<V_HALF> 1 "s_register_operand" "w") 2748 (match_operand:SI 2 "immediate_operand" "i")] 2749 UNSPEC_VDUP_LANE))] 2750 "TARGET_NEON" 2751{ 2752 neon_lane_bounds (operands[2], 0, GET_MODE_NUNITS (<V_HALF>mode)); 2753 return "vdup.<V_sz_elem>\t%q0, %P1[%c2]"; 2754} 2755 ;; Assume this schedules like vmov. 2756 [(set_attr "neon_type" "neon_bp_simple")] 2757) 2758 2759; Scalar index is ignored, since only zero is valid here. 2760(define_expand "neon_vdup_lanedi" 2761 [(set (match_operand:DI 0 "s_register_operand" "=w") 2762 (unspec:DI [(match_operand:DI 1 "s_register_operand" "w") 2763 (match_operand:SI 2 "immediate_operand" "i")] 2764 UNSPEC_VDUP_LANE))] 2765 "TARGET_NEON" 2766{ 2767 neon_lane_bounds (operands[2], 0, 1); 2768 emit_move_insn (operands[0], operands[1]); 2769 DONE; 2770}) 2771 2772; Likewise. 2773(define_insn "neon_vdup_lanev2di" 2774 [(set (match_operand:V2DI 0 "s_register_operand" "=w") 2775 (unspec:V2DI [(match_operand:DI 1 "s_register_operand" "w") 2776 (match_operand:SI 2 "immediate_operand" "i")] 2777 UNSPEC_VDUP_LANE))] 2778 "TARGET_NEON" 2779{ 2780 neon_lane_bounds (operands[2], 0, 1); 2781 return "vmov\t%e0, %P1\;vmov\t%f0, %P1"; 2782} 2783 [(set_attr "length" "8") 2784 (set_attr "neon_type" "neon_bp_simple")] 2785) 2786 2787;; In this insn, operand 1 should be low, and operand 2 the high part of the 2788;; dest vector. 2789;; FIXME: A different implementation of this builtin could make it much 2790;; more likely that we wouldn't actually need to output anything (we could make 2791;; it so that the reg allocator puts things in the right places magically 2792;; instead). Lack of subregs for vectors makes that tricky though, I think. 2793 2794(define_insn "neon_vcombine<mode>" 2795 [(set (match_operand:<V_DOUBLE> 0 "s_register_operand" "=w") 2796 (unspec:<V_DOUBLE> [(match_operand:VDX 1 "s_register_operand" "w") 2797 (match_operand:VDX 2 "s_register_operand" "w")] 2798 UNSPEC_VCOMBINE))] 2799 "TARGET_NEON" 2800{ 2801 int dest = REGNO (operands[0]); 2802 int src1 = REGNO (operands[1]); 2803 int src2 = REGNO (operands[2]); 2804 rtx destlo; 2805 2806 if (src1 == dest && src2 == dest + 2) 2807 return ""; 2808 else if (src2 == dest && src1 == dest + 2) 2809 /* Special case of reversed high/low parts. */ 2810 return "vswp\t%P1, %P2"; 2811 2812 destlo = gen_rtx_REG (<MODE>mode, dest); 2813 2814 if (!reg_overlap_mentioned_p (operands[2], destlo)) 2815 { 2816 /* Try to avoid unnecessary moves if part of the result is in the right 2817 place already. */ 2818 if (src1 != dest) 2819 output_asm_insn ("vmov\t%e0, %P1", operands); 2820 if (src2 != dest + 2) 2821 output_asm_insn ("vmov\t%f0, %P2", operands); 2822 } 2823 else 2824 { 2825 if (src2 != dest + 2) 2826 output_asm_insn ("vmov\t%f0, %P2", operands); 2827 if (src1 != dest) 2828 output_asm_insn ("vmov\t%e0, %P1", operands); 2829 } 2830 2831 return ""; 2832} 2833 ;; We set the neon_type attribute based on the vmov instructions above. 2834 [(set_attr "length" "8") 2835 (set_attr "neon_type" "neon_bp_simple")] 2836) 2837 2838(define_insn "neon_vget_high<mode>" 2839 [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w") 2840 (unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")] 2841 UNSPEC_VGET_HIGH))] 2842 "TARGET_NEON" 2843{ 2844 int dest = REGNO (operands[0]); 2845 int src = REGNO (operands[1]); 2846 2847 if (dest != src + 2) 2848 return "vmov\t%P0, %f1"; 2849 else 2850 return ""; 2851} 2852 [(set_attr "neon_type" "neon_bp_simple")] 2853) 2854 2855(define_insn "neon_vget_low<mode>" 2856 [(set (match_operand:<V_HALF> 0 "s_register_operand" "=w") 2857 (unspec:<V_HALF> [(match_operand:VQX 1 "s_register_operand" "w")] 2858 UNSPEC_VGET_LOW))] 2859 "TARGET_NEON" 2860{ 2861 int dest = REGNO (operands[0]); 2862 int src = REGNO (operands[1]); 2863 2864 if (dest != src) 2865 return "vmov\t%P0, %e1"; 2866 else 2867 return ""; 2868} 2869 [(set_attr "neon_type" "neon_bp_simple")] 2870) 2871 2872(define_insn "neon_vcvt<mode>" 2873 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w") 2874 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w") 2875 (match_operand:SI 2 "immediate_operand" "i")] 2876 UNSPEC_VCVT))] 2877 "TARGET_NEON" 2878 "vcvt.%T2%#32.f32\t%<V_reg>0, %<V_reg>1" 2879 [(set (attr "neon_type") 2880 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2881 (const_string "neon_fp_vadd_ddd_vabs_dd") 2882 (const_string "neon_fp_vadd_qqq_vabs_qq")))] 2883) 2884 2885(define_insn "neon_vcvt<mode>" 2886 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w") 2887 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w") 2888 (match_operand:SI 2 "immediate_operand" "i")] 2889 UNSPEC_VCVT))] 2890 "TARGET_NEON" 2891 "vcvt.f32.%T2%#32\t%<V_reg>0, %<V_reg>1" 2892 [(set (attr "neon_type") 2893 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2894 (const_string "neon_fp_vadd_ddd_vabs_dd") 2895 (const_string "neon_fp_vadd_qqq_vabs_qq")))] 2896) 2897 2898(define_insn "neon_vcvt_n<mode>" 2899 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w") 2900 (unspec:<V_CVTTO> [(match_operand:VCVTF 1 "s_register_operand" "w") 2901 (match_operand:SI 2 "immediate_operand" "i") 2902 (match_operand:SI 3 "immediate_operand" "i")] 2903 UNSPEC_VCVT_N))] 2904 "TARGET_NEON" 2905{ 2906 neon_const_bounds (operands[2], 1, 33); 2907 return "vcvt.%T3%#32.f32\t%<V_reg>0, %<V_reg>1, %2"; 2908} 2909 [(set (attr "neon_type") 2910 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2911 (const_string "neon_fp_vadd_ddd_vabs_dd") 2912 (const_string "neon_fp_vadd_qqq_vabs_qq")))] 2913) 2914 2915(define_insn "neon_vcvt_n<mode>" 2916 [(set (match_operand:<V_CVTTO> 0 "s_register_operand" "=w") 2917 (unspec:<V_CVTTO> [(match_operand:VCVTI 1 "s_register_operand" "w") 2918 (match_operand:SI 2 "immediate_operand" "i") 2919 (match_operand:SI 3 "immediate_operand" "i")] 2920 UNSPEC_VCVT_N))] 2921 "TARGET_NEON" 2922{ 2923 neon_const_bounds (operands[2], 1, 33); 2924 return "vcvt.f32.%T3%#32\t%<V_reg>0, %<V_reg>1, %2"; 2925} 2926 [(set (attr "neon_type") 2927 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 2928 (const_string "neon_fp_vadd_ddd_vabs_dd") 2929 (const_string "neon_fp_vadd_qqq_vabs_qq")))] 2930) 2931 2932(define_insn "neon_vmovn<mode>" 2933 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") 2934 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") 2935 (match_operand:SI 2 "immediate_operand" "i")] 2936 UNSPEC_VMOVN))] 2937 "TARGET_NEON" 2938 "vmovn.<V_if_elem>\t%P0, %q1" 2939 [(set_attr "neon_type" "neon_bp_simple")] 2940) 2941 2942(define_insn "neon_vqmovn<mode>" 2943 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") 2944 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") 2945 (match_operand:SI 2 "immediate_operand" "i")] 2946 UNSPEC_VQMOVN))] 2947 "TARGET_NEON" 2948 "vqmovn.%T2%#<V_sz_elem>\t%P0, %q1" 2949 [(set_attr "neon_type" "neon_shift_2")] 2950) 2951 2952(define_insn "neon_vqmovun<mode>" 2953 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") 2954 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") 2955 (match_operand:SI 2 "immediate_operand" "i")] 2956 UNSPEC_VQMOVUN))] 2957 "TARGET_NEON" 2958 "vqmovun.<V_s_elem>\t%P0, %q1" 2959 [(set_attr "neon_type" "neon_shift_2")] 2960) 2961 2962(define_insn "neon_vmovl<mode>" 2963 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 2964 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w") 2965 (match_operand:SI 2 "immediate_operand" "i")] 2966 UNSPEC_VMOVL))] 2967 "TARGET_NEON" 2968 "vmovl.%T2%#<V_sz_elem>\t%q0, %P1" 2969 [(set_attr "neon_type" "neon_shift_1")] 2970) 2971 2972(define_insn "neon_vmul_lane<mode>" 2973 [(set (match_operand:VMD 0 "s_register_operand" "=w") 2974 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "w") 2975 (match_operand:VMD 2 "s_register_operand" 2976 "<scalar_mul_constraint>") 2977 (match_operand:SI 3 "immediate_operand" "i") 2978 (match_operand:SI 4 "immediate_operand" "i")] 2979 UNSPEC_VMUL_LANE))] 2980 "TARGET_NEON" 2981{ 2982 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); 2983 return "vmul.<V_if_elem>\t%P0, %P1, %P2[%c3]"; 2984} 2985 [(set (attr "neon_type") 2986 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 2987 (const_string "neon_fp_vmul_ddd") 2988 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 2989 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar") 2990 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar"))))] 2991) 2992 2993(define_insn "neon_vmul_lane<mode>" 2994 [(set (match_operand:VMQ 0 "s_register_operand" "=w") 2995 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "w") 2996 (match_operand:<V_HALF> 2 "s_register_operand" 2997 "<scalar_mul_constraint>") 2998 (match_operand:SI 3 "immediate_operand" "i") 2999 (match_operand:SI 4 "immediate_operand" "i")] 3000 UNSPEC_VMUL_LANE))] 3001 "TARGET_NEON" 3002{ 3003 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<V_HALF>mode)); 3004 return "vmul.<V_if_elem>\t%q0, %q1, %P2[%c3]"; 3005} 3006 [(set (attr "neon_type") 3007 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 3008 (const_string "neon_fp_vmul_qqd") 3009 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3010 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar") 3011 (const_string "neon_mul_qqd_32_scalar"))))] 3012) 3013 3014(define_insn "neon_vmull_lane<mode>" 3015 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 3016 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w") 3017 (match_operand:VMDI 2 "s_register_operand" 3018 "<scalar_mul_constraint>") 3019 (match_operand:SI 3 "immediate_operand" "i") 3020 (match_operand:SI 4 "immediate_operand" "i")] 3021 UNSPEC_VMULL_LANE))] 3022 "TARGET_NEON" 3023{ 3024 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); 3025 return "vmull.%T4%#<V_sz_elem>\t%q0, %P1, %P2[%c3]"; 3026} 3027 [(set (attr "neon_type") 3028 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3029 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar") 3030 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] 3031) 3032 3033(define_insn "neon_vqdmull_lane<mode>" 3034 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 3035 (unspec:<V_widen> [(match_operand:VMDI 1 "s_register_operand" "w") 3036 (match_operand:VMDI 2 "s_register_operand" 3037 "<scalar_mul_constraint>") 3038 (match_operand:SI 3 "immediate_operand" "i") 3039 (match_operand:SI 4 "immediate_operand" "i")] 3040 UNSPEC_VQDMULL_LANE))] 3041 "TARGET_NEON" 3042{ 3043 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); 3044 return "vqdmull.<V_s_elem>\t%q0, %P1, %P2[%c3]"; 3045} 3046 [(set (attr "neon_type") 3047 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3048 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar") 3049 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] 3050) 3051 3052(define_insn "neon_vqdmulh_lane<mode>" 3053 [(set (match_operand:VMQI 0 "s_register_operand" "=w") 3054 (unspec:VMQI [(match_operand:VMQI 1 "s_register_operand" "w") 3055 (match_operand:<V_HALF> 2 "s_register_operand" 3056 "<scalar_mul_constraint>") 3057 (match_operand:SI 3 "immediate_operand" "i") 3058 (match_operand:SI 4 "immediate_operand" "i")] 3059 UNSPEC_VQDMULH_LANE))] 3060 "TARGET_NEON" 3061{ 3062 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); 3063 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%q0, %q1, %P2[%c3]"; 3064} 3065 [(set (attr "neon_type") 3066 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3067 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar") 3068 (const_string "neon_mul_qqd_32_scalar")))] 3069) 3070 3071(define_insn "neon_vqdmulh_lane<mode>" 3072 [(set (match_operand:VMDI 0 "s_register_operand" "=w") 3073 (unspec:VMDI [(match_operand:VMDI 1 "s_register_operand" "w") 3074 (match_operand:VMDI 2 "s_register_operand" 3075 "<scalar_mul_constraint>") 3076 (match_operand:SI 3 "immediate_operand" "i") 3077 (match_operand:SI 4 "immediate_operand" "i")] 3078 UNSPEC_VQDMULH_LANE))] 3079 "TARGET_NEON" 3080{ 3081 neon_lane_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); 3082 return "vq%O4dmulh.%T4%#<V_sz_elem>\t%P0, %P1, %P2[%c3]"; 3083} 3084 [(set (attr "neon_type") 3085 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3086 (const_string "neon_mul_ddd_16_scalar_32_16_long_scalar") 3087 (const_string "neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar")))] 3088) 3089 3090(define_insn "neon_vmla_lane<mode>" 3091 [(set (match_operand:VMD 0 "s_register_operand" "=w") 3092 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0") 3093 (match_operand:VMD 2 "s_register_operand" "w") 3094 (match_operand:VMD 3 "s_register_operand" 3095 "<scalar_mul_constraint>") 3096 (match_operand:SI 4 "immediate_operand" "i") 3097 (match_operand:SI 5 "immediate_operand" "i")] 3098 UNSPEC_VMLA_LANE))] 3099 "TARGET_NEON" 3100{ 3101 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); 3102 return "vmla.<V_if_elem>\t%P0, %P2, %P3[%c4]"; 3103} 3104 [(set (attr "neon_type") 3105 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 3106 (const_string "neon_fp_vmla_ddd_scalar") 3107 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3108 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") 3109 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))] 3110) 3111 3112(define_insn "neon_vmla_lane<mode>" 3113 [(set (match_operand:VMQ 0 "s_register_operand" "=w") 3114 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0") 3115 (match_operand:VMQ 2 "s_register_operand" "w") 3116 (match_operand:<V_HALF> 3 "s_register_operand" 3117 "<scalar_mul_constraint>") 3118 (match_operand:SI 4 "immediate_operand" "i") 3119 (match_operand:SI 5 "immediate_operand" "i")] 3120 UNSPEC_VMLA_LANE))] 3121 "TARGET_NEON" 3122{ 3123 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); 3124 return "vmla.<V_if_elem>\t%q0, %q2, %P3[%c4]"; 3125} 3126 [(set (attr "neon_type") 3127 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 3128 (const_string "neon_fp_vmla_qqq_scalar") 3129 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3130 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long") 3131 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))] 3132) 3133 3134(define_insn "neon_vmlal_lane<mode>" 3135 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 3136 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 3137 (match_operand:VMDI 2 "s_register_operand" "w") 3138 (match_operand:VMDI 3 "s_register_operand" 3139 "<scalar_mul_constraint>") 3140 (match_operand:SI 4 "immediate_operand" "i") 3141 (match_operand:SI 5 "immediate_operand" "i")] 3142 UNSPEC_VMLAL_LANE))] 3143 "TARGET_NEON" 3144{ 3145 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); 3146 return "vmlal.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]"; 3147} 3148 [(set (attr "neon_type") 3149 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3150 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") 3151 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] 3152) 3153 3154(define_insn "neon_vqdmlal_lane<mode>" 3155 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 3156 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 3157 (match_operand:VMDI 2 "s_register_operand" "w") 3158 (match_operand:VMDI 3 "s_register_operand" 3159 "<scalar_mul_constraint>") 3160 (match_operand:SI 4 "immediate_operand" "i") 3161 (match_operand:SI 5 "immediate_operand" "i")] 3162 UNSPEC_VQDMLAL_LANE))] 3163 "TARGET_NEON" 3164{ 3165 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); 3166 return "vqdmlal.<V_s_elem>\t%q0, %P2, %P3[%c4]"; 3167} 3168 [(set (attr "neon_type") 3169 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3170 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") 3171 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] 3172) 3173 3174(define_insn "neon_vmls_lane<mode>" 3175 [(set (match_operand:VMD 0 "s_register_operand" "=w") 3176 (unspec:VMD [(match_operand:VMD 1 "s_register_operand" "0") 3177 (match_operand:VMD 2 "s_register_operand" "w") 3178 (match_operand:VMD 3 "s_register_operand" 3179 "<scalar_mul_constraint>") 3180 (match_operand:SI 4 "immediate_operand" "i") 3181 (match_operand:SI 5 "immediate_operand" "i")] 3182 UNSPEC_VMLS_LANE))] 3183 "TARGET_NEON" 3184{ 3185 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); 3186 return "vmls.<V_if_elem>\t%P0, %P2, %P3[%c4]"; 3187} 3188 [(set (attr "neon_type") 3189 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 3190 (const_string "neon_fp_vmla_ddd_scalar") 3191 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3192 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") 3193 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))))] 3194) 3195 3196(define_insn "neon_vmls_lane<mode>" 3197 [(set (match_operand:VMQ 0 "s_register_operand" "=w") 3198 (unspec:VMQ [(match_operand:VMQ 1 "s_register_operand" "0") 3199 (match_operand:VMQ 2 "s_register_operand" "w") 3200 (match_operand:<V_HALF> 3 "s_register_operand" 3201 "<scalar_mul_constraint>") 3202 (match_operand:SI 4 "immediate_operand" "i") 3203 (match_operand:SI 5 "immediate_operand" "i")] 3204 UNSPEC_VMLS_LANE))] 3205 "TARGET_NEON" 3206{ 3207 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); 3208 return "vmls.<V_if_elem>\t%q0, %q2, %P3[%c4]"; 3209} 3210 [(set (attr "neon_type") 3211 (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0)) 3212 (const_string "neon_fp_vmla_qqq_scalar") 3213 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3214 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long") 3215 (const_string "neon_mla_qqq_32_qqd_32_scalar"))))] 3216) 3217 3218(define_insn "neon_vmlsl_lane<mode>" 3219 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 3220 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 3221 (match_operand:VMDI 2 "s_register_operand" "w") 3222 (match_operand:VMDI 3 "s_register_operand" 3223 "<scalar_mul_constraint>") 3224 (match_operand:SI 4 "immediate_operand" "i") 3225 (match_operand:SI 5 "immediate_operand" "i")] 3226 UNSPEC_VMLSL_LANE))] 3227 "TARGET_NEON" 3228{ 3229 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); 3230 return "vmlsl.%T5%#<V_sz_elem>\t%q0, %P2, %P3[%c4]"; 3231} 3232 [(set (attr "neon_type") 3233 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3234 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") 3235 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] 3236) 3237 3238(define_insn "neon_vqdmlsl_lane<mode>" 3239 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 3240 (unspec:<V_widen> [(match_operand:<V_widen> 1 "s_register_operand" "0") 3241 (match_operand:VMDI 2 "s_register_operand" "w") 3242 (match_operand:VMDI 3 "s_register_operand" 3243 "<scalar_mul_constraint>") 3244 (match_operand:SI 4 "immediate_operand" "i") 3245 (match_operand:SI 5 "immediate_operand" "i")] 3246 UNSPEC_VQDMLSL_LANE))] 3247 "TARGET_NEON" 3248{ 3249 neon_lane_bounds (operands[4], 0, GET_MODE_NUNITS (<MODE>mode)); 3250 return "vqdmlsl.<V_s_elem>\t%q0, %P2, %P3[%c4]"; 3251} 3252 [(set (attr "neon_type") 3253 (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0)) 3254 (const_string "neon_mla_ddd_16_scalar_qdd_32_16_long_scalar") 3255 (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long")))] 3256) 3257 3258; FIXME: For the "_n" multiply/multiply-accumulate insns, we copy a value in a 3259; core register into a temp register, then use a scalar taken from that. This 3260; isn't an optimal solution if e.g. the scalar has just been read from memory 3261; or extracted from another vector. The latter case it's currently better to 3262; use the "_lane" variant, and the former case can probably be implemented 3263; using vld1_lane, but that hasn't been done yet. 3264 3265(define_expand "neon_vmul_n<mode>" 3266 [(match_operand:VMD 0 "s_register_operand" "") 3267 (match_operand:VMD 1 "s_register_operand" "") 3268 (match_operand:<V_elem> 2 "s_register_operand" "") 3269 (match_operand:SI 3 "immediate_operand" "")] 3270 "TARGET_NEON" 3271{ 3272 rtx tmp = gen_reg_rtx (<MODE>mode); 3273 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx)); 3274 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp, 3275 const0_rtx, const0_rtx)); 3276 DONE; 3277}) 3278 3279(define_expand "neon_vmul_n<mode>" 3280 [(match_operand:VMQ 0 "s_register_operand" "") 3281 (match_operand:VMQ 1 "s_register_operand" "") 3282 (match_operand:<V_elem> 2 "s_register_operand" "") 3283 (match_operand:SI 3 "immediate_operand" "")] 3284 "TARGET_NEON" 3285{ 3286 rtx tmp = gen_reg_rtx (<V_HALF>mode); 3287 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx)); 3288 emit_insn (gen_neon_vmul_lane<mode> (operands[0], operands[1], tmp, 3289 const0_rtx, const0_rtx)); 3290 DONE; 3291}) 3292 3293(define_expand "neon_vmull_n<mode>" 3294 [(match_operand:<V_widen> 0 "s_register_operand" "") 3295 (match_operand:VMDI 1 "s_register_operand" "") 3296 (match_operand:<V_elem> 2 "s_register_operand" "") 3297 (match_operand:SI 3 "immediate_operand" "")] 3298 "TARGET_NEON" 3299{ 3300 rtx tmp = gen_reg_rtx (<MODE>mode); 3301 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx)); 3302 emit_insn (gen_neon_vmull_lane<mode> (operands[0], operands[1], tmp, 3303 const0_rtx, operands[3])); 3304 DONE; 3305}) 3306 3307(define_expand "neon_vqdmull_n<mode>" 3308 [(match_operand:<V_widen> 0 "s_register_operand" "") 3309 (match_operand:VMDI 1 "s_register_operand" "") 3310 (match_operand:<V_elem> 2 "s_register_operand" "") 3311 (match_operand:SI 3 "immediate_operand" "")] 3312 "TARGET_NEON" 3313{ 3314 rtx tmp = gen_reg_rtx (<MODE>mode); 3315 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx)); 3316 emit_insn (gen_neon_vqdmull_lane<mode> (operands[0], operands[1], tmp, 3317 const0_rtx, const0_rtx)); 3318 DONE; 3319}) 3320 3321(define_expand "neon_vqdmulh_n<mode>" 3322 [(match_operand:VMDI 0 "s_register_operand" "") 3323 (match_operand:VMDI 1 "s_register_operand" "") 3324 (match_operand:<V_elem> 2 "s_register_operand" "") 3325 (match_operand:SI 3 "immediate_operand" "")] 3326 "TARGET_NEON" 3327{ 3328 rtx tmp = gen_reg_rtx (<MODE>mode); 3329 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[2], tmp, const0_rtx)); 3330 emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp, 3331 const0_rtx, operands[3])); 3332 DONE; 3333}) 3334 3335(define_expand "neon_vqdmulh_n<mode>" 3336 [(match_operand:VMQI 0 "s_register_operand" "") 3337 (match_operand:VMQI 1 "s_register_operand" "") 3338 (match_operand:<V_elem> 2 "s_register_operand" "") 3339 (match_operand:SI 3 "immediate_operand" "")] 3340 "TARGET_NEON" 3341{ 3342 rtx tmp = gen_reg_rtx (<V_HALF>mode); 3343 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[2], tmp, const0_rtx)); 3344 emit_insn (gen_neon_vqdmulh_lane<mode> (operands[0], operands[1], tmp, 3345 const0_rtx, operands[3])); 3346 DONE; 3347}) 3348 3349(define_expand "neon_vmla_n<mode>" 3350 [(match_operand:VMD 0 "s_register_operand" "") 3351 (match_operand:VMD 1 "s_register_operand" "") 3352 (match_operand:VMD 2 "s_register_operand" "") 3353 (match_operand:<V_elem> 3 "s_register_operand" "") 3354 (match_operand:SI 4 "immediate_operand" "")] 3355 "TARGET_NEON" 3356{ 3357 rtx tmp = gen_reg_rtx (<MODE>mode); 3358 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); 3359 emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2], 3360 tmp, const0_rtx, operands[4])); 3361 DONE; 3362}) 3363 3364(define_expand "neon_vmla_n<mode>" 3365 [(match_operand:VMQ 0 "s_register_operand" "") 3366 (match_operand:VMQ 1 "s_register_operand" "") 3367 (match_operand:VMQ 2 "s_register_operand" "") 3368 (match_operand:<V_elem> 3 "s_register_operand" "") 3369 (match_operand:SI 4 "immediate_operand" "")] 3370 "TARGET_NEON" 3371{ 3372 rtx tmp = gen_reg_rtx (<V_HALF>mode); 3373 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx)); 3374 emit_insn (gen_neon_vmla_lane<mode> (operands[0], operands[1], operands[2], 3375 tmp, const0_rtx, operands[4])); 3376 DONE; 3377}) 3378 3379(define_expand "neon_vmlal_n<mode>" 3380 [(match_operand:<V_widen> 0 "s_register_operand" "") 3381 (match_operand:<V_widen> 1 "s_register_operand" "") 3382 (match_operand:VMDI 2 "s_register_operand" "") 3383 (match_operand:<V_elem> 3 "s_register_operand" "") 3384 (match_operand:SI 4 "immediate_operand" "")] 3385 "TARGET_NEON" 3386{ 3387 rtx tmp = gen_reg_rtx (<MODE>mode); 3388 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); 3389 emit_insn (gen_neon_vmlal_lane<mode> (operands[0], operands[1], operands[2], 3390 tmp, const0_rtx, operands[4])); 3391 DONE; 3392}) 3393 3394(define_expand "neon_vqdmlal_n<mode>" 3395 [(match_operand:<V_widen> 0 "s_register_operand" "") 3396 (match_operand:<V_widen> 1 "s_register_operand" "") 3397 (match_operand:VMDI 2 "s_register_operand" "") 3398 (match_operand:<V_elem> 3 "s_register_operand" "") 3399 (match_operand:SI 4 "immediate_operand" "")] 3400 "TARGET_NEON" 3401{ 3402 rtx tmp = gen_reg_rtx (<MODE>mode); 3403 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); 3404 emit_insn (gen_neon_vqdmlal_lane<mode> (operands[0], operands[1], operands[2], 3405 tmp, const0_rtx, operands[4])); 3406 DONE; 3407}) 3408 3409(define_expand "neon_vmls_n<mode>" 3410 [(match_operand:VMD 0 "s_register_operand" "") 3411 (match_operand:VMD 1 "s_register_operand" "") 3412 (match_operand:VMD 2 "s_register_operand" "") 3413 (match_operand:<V_elem> 3 "s_register_operand" "") 3414 (match_operand:SI 4 "immediate_operand" "")] 3415 "TARGET_NEON" 3416{ 3417 rtx tmp = gen_reg_rtx (<MODE>mode); 3418 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); 3419 emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2], 3420 tmp, const0_rtx, operands[4])); 3421 DONE; 3422}) 3423 3424(define_expand "neon_vmls_n<mode>" 3425 [(match_operand:VMQ 0 "s_register_operand" "") 3426 (match_operand:VMQ 1 "s_register_operand" "") 3427 (match_operand:VMQ 2 "s_register_operand" "") 3428 (match_operand:<V_elem> 3 "s_register_operand" "") 3429 (match_operand:SI 4 "immediate_operand" "")] 3430 "TARGET_NEON" 3431{ 3432 rtx tmp = gen_reg_rtx (<V_HALF>mode); 3433 emit_insn (gen_neon_vset_lane<V_half> (tmp, operands[3], tmp, const0_rtx)); 3434 emit_insn (gen_neon_vmls_lane<mode> (operands[0], operands[1], operands[2], 3435 tmp, const0_rtx, operands[4])); 3436 DONE; 3437}) 3438 3439(define_expand "neon_vmlsl_n<mode>" 3440 [(match_operand:<V_widen> 0 "s_register_operand" "") 3441 (match_operand:<V_widen> 1 "s_register_operand" "") 3442 (match_operand:VMDI 2 "s_register_operand" "") 3443 (match_operand:<V_elem> 3 "s_register_operand" "") 3444 (match_operand:SI 4 "immediate_operand" "")] 3445 "TARGET_NEON" 3446{ 3447 rtx tmp = gen_reg_rtx (<MODE>mode); 3448 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); 3449 emit_insn (gen_neon_vmlsl_lane<mode> (operands[0], operands[1], operands[2], 3450 tmp, const0_rtx, operands[4])); 3451 DONE; 3452}) 3453 3454(define_expand "neon_vqdmlsl_n<mode>" 3455 [(match_operand:<V_widen> 0 "s_register_operand" "") 3456 (match_operand:<V_widen> 1 "s_register_operand" "") 3457 (match_operand:VMDI 2 "s_register_operand" "") 3458 (match_operand:<V_elem> 3 "s_register_operand" "") 3459 (match_operand:SI 4 "immediate_operand" "")] 3460 "TARGET_NEON" 3461{ 3462 rtx tmp = gen_reg_rtx (<MODE>mode); 3463 emit_insn (gen_neon_vset_lane<mode> (tmp, operands[3], tmp, const0_rtx)); 3464 emit_insn (gen_neon_vqdmlsl_lane<mode> (operands[0], operands[1], operands[2], 3465 tmp, const0_rtx, operands[4])); 3466 DONE; 3467}) 3468 3469(define_insn "neon_vext<mode>" 3470 [(set (match_operand:VDQX 0 "s_register_operand" "=w") 3471 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w") 3472 (match_operand:VDQX 2 "s_register_operand" "w") 3473 (match_operand:SI 3 "immediate_operand" "i")] 3474 UNSPEC_VEXT))] 3475 "TARGET_NEON" 3476{ 3477 neon_const_bounds (operands[3], 0, GET_MODE_NUNITS (<MODE>mode)); 3478 return "vext.<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2, %3"; 3479} 3480 [(set (attr "neon_type") 3481 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 3482 (const_string "neon_bp_simple") 3483 (const_string "neon_bp_2cycle")))] 3484) 3485 3486(define_insn "neon_vrev64<mode>" 3487 [(set (match_operand:VDQ 0 "s_register_operand" "=w") 3488 (unspec:VDQ [(match_operand:VDQ 1 "s_register_operand" "w") 3489 (match_operand:SI 2 "immediate_operand" "i")] 3490 UNSPEC_VREV64))] 3491 "TARGET_NEON" 3492 "vrev64.<V_sz_elem>\t%<V_reg>0, %<V_reg>1" 3493 [(set_attr "neon_type" "neon_bp_simple")] 3494) 3495 3496(define_insn "neon_vrev32<mode>" 3497 [(set (match_operand:VX 0 "s_register_operand" "=w") 3498 (unspec:VX [(match_operand:VX 1 "s_register_operand" "w") 3499 (match_operand:SI 2 "immediate_operand" "i")] 3500 UNSPEC_VREV32))] 3501 "TARGET_NEON" 3502 "vrev32.<V_sz_elem>\t%<V_reg>0, %<V_reg>1" 3503 [(set_attr "neon_type" "neon_bp_simple")] 3504) 3505 3506(define_insn "neon_vrev16<mode>" 3507 [(set (match_operand:VE 0 "s_register_operand" "=w") 3508 (unspec:VE [(match_operand:VE 1 "s_register_operand" "w") 3509 (match_operand:SI 2 "immediate_operand" "i")] 3510 UNSPEC_VREV16))] 3511 "TARGET_NEON" 3512 "vrev16.<V_sz_elem>\t%<V_reg>0, %<V_reg>1" 3513 [(set_attr "neon_type" "neon_bp_simple")] 3514) 3515 3516; vbsl_* intrinsics may compile to any of vbsl/vbif/vbit depending on register 3517; allocation. For an intrinsic of form: 3518; rD = vbsl_* (rS, rN, rM) 3519; We can use any of: 3520; vbsl rS, rN, rM (if D = S) 3521; vbit rD, rN, rS (if D = M, so 1-bits in rS choose bits from rN, else rM) 3522; vbif rD, rM, rS (if D = N, so 0-bits in rS choose bits from rM, else rN) 3523 3524(define_insn "neon_vbsl<mode>_internal" 3525 [(set (match_operand:VDQX 0 "s_register_operand" "=w,w,w") 3526 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" " 0,w,w") 3527 (match_operand:VDQX 2 "s_register_operand" " w,w,0") 3528 (match_operand:VDQX 3 "s_register_operand" " w,0,w")] 3529 UNSPEC_VBSL))] 3530 "TARGET_NEON" 3531 "@ 3532 vbsl\t%<V_reg>0, %<V_reg>2, %<V_reg>3 3533 vbit\t%<V_reg>0, %<V_reg>2, %<V_reg>1 3534 vbif\t%<V_reg>0, %<V_reg>3, %<V_reg>1" 3535 [(set_attr "neon_type" "neon_int_1")] 3536) 3537 3538(define_expand "neon_vbsl<mode>" 3539 [(set (match_operand:VDQX 0 "s_register_operand" "") 3540 (unspec:VDQX [(match_operand:<V_cmp_result> 1 "s_register_operand" "") 3541 (match_operand:VDQX 2 "s_register_operand" "") 3542 (match_operand:VDQX 3 "s_register_operand" "")] 3543 UNSPEC_VBSL))] 3544 "TARGET_NEON" 3545{ 3546 /* We can't alias operands together if they have different modes. */ 3547 operands[1] = gen_lowpart (<MODE>mode, operands[1]); 3548}) 3549 3550(define_insn "neon_vshl<mode>" 3551 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3552 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") 3553 (match_operand:VDQIX 2 "s_register_operand" "w") 3554 (match_operand:SI 3 "immediate_operand" "i")] 3555 UNSPEC_VSHL))] 3556 "TARGET_NEON" 3557 "v%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 3558 [(set (attr "neon_type") 3559 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 3560 (const_string "neon_vshl_ddd") 3561 (const_string "neon_shift_3")))] 3562) 3563 3564(define_insn "neon_vqshl<mode>" 3565 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3566 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") 3567 (match_operand:VDQIX 2 "s_register_operand" "w") 3568 (match_operand:SI 3 "immediate_operand" "i")] 3569 UNSPEC_VQSHL))] 3570 "TARGET_NEON" 3571 "vq%O3shl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2" 3572 [(set (attr "neon_type") 3573 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 3574 (const_string "neon_shift_2") 3575 (const_string "neon_vqshl_vrshl_vqrshl_qqq")))] 3576) 3577 3578(define_insn "neon_vshr_n<mode>" 3579 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3580 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") 3581 (match_operand:SI 2 "immediate_operand" "i") 3582 (match_operand:SI 3 "immediate_operand" "i")] 3583 UNSPEC_VSHR_N))] 3584 "TARGET_NEON" 3585{ 3586 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) + 1); 3587 return "v%O3shr.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"; 3588} 3589 [(set_attr "neon_type" "neon_shift_1")] 3590) 3591 3592(define_insn "neon_vshrn_n<mode>" 3593 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") 3594 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") 3595 (match_operand:SI 2 "immediate_operand" "i") 3596 (match_operand:SI 3 "immediate_operand" "i")] 3597 UNSPEC_VSHRN_N))] 3598 "TARGET_NEON" 3599{ 3600 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1); 3601 return "v%O3shrn.<V_if_elem>\t%P0, %q1, %2"; 3602} 3603 [(set_attr "neon_type" "neon_shift_1")] 3604) 3605 3606(define_insn "neon_vqshrn_n<mode>" 3607 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") 3608 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") 3609 (match_operand:SI 2 "immediate_operand" "i") 3610 (match_operand:SI 3 "immediate_operand" "i")] 3611 UNSPEC_VQSHRN_N))] 3612 "TARGET_NEON" 3613{ 3614 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1); 3615 return "vq%O3shrn.%T3%#<V_sz_elem>\t%P0, %q1, %2"; 3616} 3617 [(set_attr "neon_type" "neon_shift_2")] 3618) 3619 3620(define_insn "neon_vqshrun_n<mode>" 3621 [(set (match_operand:<V_narrow> 0 "s_register_operand" "=w") 3622 (unspec:<V_narrow> [(match_operand:VN 1 "s_register_operand" "w") 3623 (match_operand:SI 2 "immediate_operand" "i") 3624 (match_operand:SI 3 "immediate_operand" "i")] 3625 UNSPEC_VQSHRUN_N))] 3626 "TARGET_NEON" 3627{ 3628 neon_const_bounds (operands[2], 1, neon_element_bits (<MODE>mode) / 2 + 1); 3629 return "vq%O3shrun.%T3%#<V_sz_elem>\t%P0, %q1, %2"; 3630} 3631 [(set_attr "neon_type" "neon_shift_2")] 3632) 3633 3634(define_insn "neon_vshl_n<mode>" 3635 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3636 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") 3637 (match_operand:SI 2 "immediate_operand" "i") 3638 (match_operand:SI 3 "immediate_operand" "i")] 3639 UNSPEC_VSHL_N))] 3640 "TARGET_NEON" 3641{ 3642 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode)); 3643 return "vshl.<V_if_elem>\t%<V_reg>0, %<V_reg>1, %2"; 3644} 3645 [(set_attr "neon_type" "neon_shift_1")] 3646) 3647 3648(define_insn "neon_vqshl_n<mode>" 3649 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3650 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") 3651 (match_operand:SI 2 "immediate_operand" "i") 3652 (match_operand:SI 3 "immediate_operand" "i")] 3653 UNSPEC_VQSHL_N))] 3654 "TARGET_NEON" 3655{ 3656 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode)); 3657 return "vqshl.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"; 3658} 3659 [(set_attr "neon_type" "neon_shift_2")] 3660) 3661 3662(define_insn "neon_vqshlu_n<mode>" 3663 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3664 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "w") 3665 (match_operand:SI 2 "immediate_operand" "i") 3666 (match_operand:SI 3 "immediate_operand" "i")] 3667 UNSPEC_VQSHLU_N))] 3668 "TARGET_NEON" 3669{ 3670 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode)); 3671 return "vqshlu.%T3%#<V_sz_elem>\t%<V_reg>0, %<V_reg>1, %2"; 3672} 3673 [(set_attr "neon_type" "neon_shift_2")] 3674) 3675 3676(define_insn "neon_vshll_n<mode>" 3677 [(set (match_operand:<V_widen> 0 "s_register_operand" "=w") 3678 (unspec:<V_widen> [(match_operand:VW 1 "s_register_operand" "w") 3679 (match_operand:SI 2 "immediate_operand" "i") 3680 (match_operand:SI 3 "immediate_operand" "i")] 3681 UNSPEC_VSHLL_N))] 3682 "TARGET_NEON" 3683{ 3684 /* The boundaries are: 0 < imm <= size. */ 3685 neon_const_bounds (operands[2], 0, neon_element_bits (<MODE>mode) + 1); 3686 return "vshll.%T3%#<V_sz_elem>\t%q0, %P1, %2"; 3687} 3688 [(set_attr "neon_type" "neon_shift_1")] 3689) 3690 3691(define_insn "neon_vsra_n<mode>" 3692 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3693 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0") 3694 (match_operand:VDQIX 2 "s_register_operand" "w") 3695 (match_operand:SI 3 "immediate_operand" "i") 3696 (match_operand:SI 4 "immediate_operand" "i")] 3697 UNSPEC_VSRA_N))] 3698 "TARGET_NEON" 3699{ 3700 neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1); 3701 return "v%O4sra.%T4%#<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"; 3702} 3703 [(set_attr "neon_type" "neon_vsra_vrsra")] 3704) 3705 3706(define_insn "neon_vsri_n<mode>" 3707 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3708 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0") 3709 (match_operand:VDQIX 2 "s_register_operand" "w") 3710 (match_operand:SI 3 "immediate_operand" "i")] 3711 UNSPEC_VSRI))] 3712 "TARGET_NEON" 3713{ 3714 neon_const_bounds (operands[3], 1, neon_element_bits (<MODE>mode) + 1); 3715 return "vsri.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"; 3716} 3717 [(set (attr "neon_type") 3718 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 3719 (const_string "neon_shift_1") 3720 (const_string "neon_shift_3")))] 3721) 3722 3723(define_insn "neon_vsli_n<mode>" 3724 [(set (match_operand:VDQIX 0 "s_register_operand" "=w") 3725 (unspec:VDQIX [(match_operand:VDQIX 1 "s_register_operand" "0") 3726 (match_operand:VDQIX 2 "s_register_operand" "w") 3727 (match_operand:SI 3 "immediate_operand" "i")] 3728 UNSPEC_VSLI))] 3729 "TARGET_NEON" 3730{ 3731 neon_const_bounds (operands[3], 0, neon_element_bits (<MODE>mode)); 3732 return "vsli.<V_sz_elem>\t%<V_reg>0, %<V_reg>2, %3"; 3733} 3734 [(set (attr "neon_type") 3735 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 3736 (const_string "neon_shift_1") 3737 (const_string "neon_shift_3")))] 3738) 3739 3740(define_insn "neon_vtbl1v8qi" 3741 [(set (match_operand:V8QI 0 "s_register_operand" "=w") 3742 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "w") 3743 (match_operand:V8QI 2 "s_register_operand" "w")] 3744 UNSPEC_VTBL))] 3745 "TARGET_NEON" 3746 "vtbl.8\t%P0, {%P1}, %P2" 3747 [(set_attr "neon_type" "neon_bp_2cycle")] 3748) 3749 3750(define_insn "neon_vtbl2v8qi" 3751 [(set (match_operand:V8QI 0 "s_register_operand" "=w") 3752 (unspec:V8QI [(match_operand:TI 1 "s_register_operand" "w") 3753 (match_operand:V8QI 2 "s_register_operand" "w")] 3754 UNSPEC_VTBL))] 3755 "TARGET_NEON" 3756{ 3757 rtx ops[4]; 3758 int tabbase = REGNO (operands[1]); 3759 3760 ops[0] = operands[0]; 3761 ops[1] = gen_rtx_REG (V8QImode, tabbase); 3762 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); 3763 ops[3] = operands[2]; 3764 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2}, %P3", ops); 3765 3766 return ""; 3767} 3768 [(set_attr "neon_type" "neon_bp_2cycle")] 3769) 3770 3771(define_insn "neon_vtbl3v8qi" 3772 [(set (match_operand:V8QI 0 "s_register_operand" "=w") 3773 (unspec:V8QI [(match_operand:EI 1 "s_register_operand" "w") 3774 (match_operand:V8QI 2 "s_register_operand" "w")] 3775 UNSPEC_VTBL))] 3776 "TARGET_NEON" 3777{ 3778 rtx ops[5]; 3779 int tabbase = REGNO (operands[1]); 3780 3781 ops[0] = operands[0]; 3782 ops[1] = gen_rtx_REG (V8QImode, tabbase); 3783 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); 3784 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4); 3785 ops[4] = operands[2]; 3786 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3}, %P4", ops); 3787 3788 return ""; 3789} 3790 [(set_attr "neon_type" "neon_bp_3cycle")] 3791) 3792 3793(define_insn "neon_vtbl4v8qi" 3794 [(set (match_operand:V8QI 0 "s_register_operand" "=w") 3795 (unspec:V8QI [(match_operand:OI 1 "s_register_operand" "w") 3796 (match_operand:V8QI 2 "s_register_operand" "w")] 3797 UNSPEC_VTBL))] 3798 "TARGET_NEON" 3799{ 3800 rtx ops[6]; 3801 int tabbase = REGNO (operands[1]); 3802 3803 ops[0] = operands[0]; 3804 ops[1] = gen_rtx_REG (V8QImode, tabbase); 3805 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); 3806 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4); 3807 ops[4] = gen_rtx_REG (V8QImode, tabbase + 6); 3808 ops[5] = operands[2]; 3809 output_asm_insn ("vtbl.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops); 3810 3811 return ""; 3812} 3813 [(set_attr "neon_type" "neon_bp_3cycle")] 3814) 3815 3816(define_insn "neon_vtbx1v8qi" 3817 [(set (match_operand:V8QI 0 "s_register_operand" "=w") 3818 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0") 3819 (match_operand:V8QI 2 "s_register_operand" "w") 3820 (match_operand:V8QI 3 "s_register_operand" "w")] 3821 UNSPEC_VTBX))] 3822 "TARGET_NEON" 3823 "vtbx.8\t%P0, {%P2}, %P3" 3824 [(set_attr "neon_type" "neon_bp_2cycle")] 3825) 3826 3827(define_insn "neon_vtbx2v8qi" 3828 [(set (match_operand:V8QI 0 "s_register_operand" "=w") 3829 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0") 3830 (match_operand:TI 2 "s_register_operand" "w") 3831 (match_operand:V8QI 3 "s_register_operand" "w")] 3832 UNSPEC_VTBX))] 3833 "TARGET_NEON" 3834{ 3835 rtx ops[4]; 3836 int tabbase = REGNO (operands[2]); 3837 3838 ops[0] = operands[0]; 3839 ops[1] = gen_rtx_REG (V8QImode, tabbase); 3840 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); 3841 ops[3] = operands[3]; 3842 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2}, %P3", ops); 3843 3844 return ""; 3845} 3846 [(set_attr "neon_type" "neon_bp_2cycle")] 3847) 3848 3849(define_insn "neon_vtbx3v8qi" 3850 [(set (match_operand:V8QI 0 "s_register_operand" "=w") 3851 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0") 3852 (match_operand:EI 2 "s_register_operand" "w") 3853 (match_operand:V8QI 3 "s_register_operand" "w")] 3854 UNSPEC_VTBX))] 3855 "TARGET_NEON" 3856{ 3857 rtx ops[5]; 3858 int tabbase = REGNO (operands[2]); 3859 3860 ops[0] = operands[0]; 3861 ops[1] = gen_rtx_REG (V8QImode, tabbase); 3862 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); 3863 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4); 3864 ops[4] = operands[3]; 3865 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3}, %P4", ops); 3866 3867 return ""; 3868} 3869 [(set_attr "neon_type" "neon_bp_3cycle")] 3870) 3871 3872(define_insn "neon_vtbx4v8qi" 3873 [(set (match_operand:V8QI 0 "s_register_operand" "=w") 3874 (unspec:V8QI [(match_operand:V8QI 1 "s_register_operand" "0") 3875 (match_operand:OI 2 "s_register_operand" "w") 3876 (match_operand:V8QI 3 "s_register_operand" "w")] 3877 UNSPEC_VTBX))] 3878 "TARGET_NEON" 3879{ 3880 rtx ops[6]; 3881 int tabbase = REGNO (operands[2]); 3882 3883 ops[0] = operands[0]; 3884 ops[1] = gen_rtx_REG (V8QImode, tabbase); 3885 ops[2] = gen_rtx_REG (V8QImode, tabbase + 2); 3886 ops[3] = gen_rtx_REG (V8QImode, tabbase + 4); 3887 ops[4] = gen_rtx_REG (V8QImode, tabbase + 6); 3888 ops[5] = operands[3]; 3889 output_asm_insn ("vtbx.8\t%P0, {%P1, %P2, %P3, %P4}, %P5", ops); 3890 3891 return ""; 3892} 3893 [(set_attr "neon_type" "neon_bp_3cycle")] 3894) 3895 3896(define_insn "neon_vtrn<mode>_internal" 3897 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 3898 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0") 3899 (match_operand:VDQW 2 "s_register_operand" "w")] 3900 UNSPEC_VTRN1)) 3901 (set (match_operand:VDQW 3 "s_register_operand" "=2") 3902 (unspec:VDQW [(match_dup 1) (match_dup 2)] 3903 UNSPEC_VTRN2))] 3904 "TARGET_NEON" 3905 "vtrn.<V_sz_elem>\t%<V_reg>0, %<V_reg>3" 3906 [(set (attr "neon_type") 3907 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 3908 (const_string "neon_bp_simple") 3909 (const_string "neon_bp_3cycle")))] 3910) 3911 3912(define_expand "neon_vtrn<mode>" 3913 [(match_operand:SI 0 "s_register_operand" "r") 3914 (match_operand:VDQW 1 "s_register_operand" "w") 3915 (match_operand:VDQW 2 "s_register_operand" "w")] 3916 "TARGET_NEON" 3917{ 3918 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vtrn<mode>_internal, 3919 operands[0], operands[1], operands[2]); 3920 DONE; 3921}) 3922 3923(define_insn "neon_vzip<mode>_internal" 3924 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 3925 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0") 3926 (match_operand:VDQW 2 "s_register_operand" "w")] 3927 UNSPEC_VZIP1)) 3928 (set (match_operand:VDQW 3 "s_register_operand" "=2") 3929 (unspec:VDQW [(match_dup 1) (match_dup 2)] 3930 UNSPEC_VZIP2))] 3931 "TARGET_NEON" 3932 "vzip.<V_sz_elem>\t%<V_reg>0, %<V_reg>3" 3933 [(set (attr "neon_type") 3934 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 3935 (const_string "neon_bp_simple") 3936 (const_string "neon_bp_3cycle")))] 3937) 3938 3939(define_expand "neon_vzip<mode>" 3940 [(match_operand:SI 0 "s_register_operand" "r") 3941 (match_operand:VDQW 1 "s_register_operand" "w") 3942 (match_operand:VDQW 2 "s_register_operand" "w")] 3943 "TARGET_NEON" 3944{ 3945 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vzip<mode>_internal, 3946 operands[0], operands[1], operands[2]); 3947 DONE; 3948}) 3949 3950(define_insn "neon_vuzp<mode>_internal" 3951 [(set (match_operand:VDQW 0 "s_register_operand" "=w") 3952 (unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0") 3953 (match_operand:VDQW 2 "s_register_operand" "w")] 3954 UNSPEC_VUZP1)) 3955 (set (match_operand:VDQW 3 "s_register_operand" "=2") 3956 (unspec:VDQW [(match_dup 1) (match_dup 2)] 3957 UNSPEC_VUZP2))] 3958 "TARGET_NEON" 3959 "vuzp.<V_sz_elem>\t%<V_reg>0, %<V_reg>3" 3960 [(set (attr "neon_type") 3961 (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0)) 3962 (const_string "neon_bp_simple") 3963 (const_string "neon_bp_3cycle")))] 3964) 3965 3966(define_expand "neon_vuzp<mode>" 3967 [(match_operand:SI 0 "s_register_operand" "r") 3968 (match_operand:VDQW 1 "s_register_operand" "w") 3969 (match_operand:VDQW 2 "s_register_operand" "w")] 3970 "TARGET_NEON" 3971{ 3972 neon_emit_pair_result_insn (<MODE>mode, gen_neon_vuzp<mode>_internal, 3973 operands[0], operands[1], operands[2]); 3974 DONE; 3975}) 3976 3977(define_expand "neon_vreinterpretv8qi<mode>" 3978 [(match_operand:V8QI 0 "s_register_operand" "") 3979 (match_operand:VDX 1 "s_register_operand" "")] 3980 "TARGET_NEON" 3981{ 3982 neon_reinterpret (operands[0], operands[1]); 3983 DONE; 3984}) 3985 3986(define_expand "neon_vreinterpretv4hi<mode>" 3987 [(match_operand:V4HI 0 "s_register_operand" "") 3988 (match_operand:VDX 1 "s_register_operand" "")] 3989 "TARGET_NEON" 3990{ 3991 neon_reinterpret (operands[0], operands[1]); 3992 DONE; 3993}) 3994 3995(define_expand "neon_vreinterpretv2si<mode>" 3996 [(match_operand:V2SI 0 "s_register_operand" "") 3997 (match_operand:VDX 1 "s_register_operand" "")] 3998 "TARGET_NEON" 3999{ 4000 neon_reinterpret (operands[0], operands[1]); 4001 DONE; 4002}) 4003 4004(define_expand "neon_vreinterpretv2sf<mode>" 4005 [(match_operand:V2SF 0 "s_register_operand" "") 4006 (match_operand:VDX 1 "s_register_operand" "")] 4007 "TARGET_NEON" 4008{ 4009 neon_reinterpret (operands[0], operands[1]); 4010 DONE; 4011}) 4012 4013(define_expand "neon_vreinterpretdi<mode>" 4014 [(match_operand:DI 0 "s_register_operand" "") 4015 (match_operand:VDX 1 "s_register_operand" "")] 4016 "TARGET_NEON" 4017{ 4018 neon_reinterpret (operands[0], operands[1]); 4019 DONE; 4020}) 4021 4022(define_expand "neon_vreinterpretv16qi<mode>" 4023 [(match_operand:V16QI 0 "s_register_operand" "") 4024 (match_operand:VQX 1 "s_register_operand" "")] 4025 "TARGET_NEON" 4026{ 4027 neon_reinterpret (operands[0], operands[1]); 4028 DONE; 4029}) 4030 4031(define_expand "neon_vreinterpretv8hi<mode>" 4032 [(match_operand:V8HI 0 "s_register_operand" "") 4033 (match_operand:VQX 1 "s_register_operand" "")] 4034 "TARGET_NEON" 4035{ 4036 neon_reinterpret (operands[0], operands[1]); 4037 DONE; 4038}) 4039 4040(define_expand "neon_vreinterpretv4si<mode>" 4041 [(match_operand:V4SI 0 "s_register_operand" "") 4042 (match_operand:VQX 1 "s_register_operand" "")] 4043 "TARGET_NEON" 4044{ 4045 neon_reinterpret (operands[0], operands[1]); 4046 DONE; 4047}) 4048 4049(define_expand "neon_vreinterpretv4sf<mode>" 4050 [(match_operand:V4SF 0 "s_register_operand" "") 4051 (match_operand:VQX 1 "s_register_operand" "")] 4052 "TARGET_NEON" 4053{ 4054 neon_reinterpret (operands[0], operands[1]); 4055 DONE; 4056}) 4057 4058(define_expand "neon_vreinterpretv2di<mode>" 4059 [(match_operand:V2DI 0 "s_register_operand" "") 4060 (match_operand:VQX 1 "s_register_operand" "")] 4061 "TARGET_NEON" 4062{ 4063 neon_reinterpret (operands[0], operands[1]); 4064 DONE; 4065}) 4066 4067(define_insn "neon_vld1<mode>" 4068 [(set (match_operand:VDQX 0 "s_register_operand" "=w") 4069 (unspec:VDQX [(mem:VDQX (match_operand:SI 1 "s_register_operand" "r"))] 4070 UNSPEC_VLD1))] 4071 "TARGET_NEON" 4072 "vld1.<V_sz_elem>\t%h0, [%1]" 4073 [(set_attr "neon_type" "neon_vld1_1_2_regs")] 4074) 4075 4076(define_insn "neon_vld1_lane<mode>" 4077 [(set (match_operand:VDX 0 "s_register_operand" "=w") 4078 (unspec:VDX [(mem:<V_elem> (match_operand:SI 1 "s_register_operand" "r")) 4079 (match_operand:VDX 2 "s_register_operand" "0") 4080 (match_operand:SI 3 "immediate_operand" "i")] 4081 UNSPEC_VLD1_LANE))] 4082 "TARGET_NEON" 4083{ 4084 HOST_WIDE_INT lane = INTVAL (operands[3]); 4085 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4086 if (lane < 0 || lane >= max) 4087 error ("lane out of range"); 4088 if (max == 1) 4089 return "vld1.<V_sz_elem>\t%P0, [%1]"; 4090 else 4091 return "vld1.<V_sz_elem>\t{%P0[%c3]}, [%1]"; 4092} 4093 [(set (attr "neon_type") 4094 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2)) 4095 (const_string "neon_vld1_1_2_regs") 4096 (const_string "neon_vld1_vld2_lane")))] 4097) 4098 4099(define_insn "neon_vld1_lane<mode>" 4100 [(set (match_operand:VQX 0 "s_register_operand" "=w") 4101 (unspec:VQX [(mem:<V_elem> (match_operand:SI 1 "s_register_operand" "r")) 4102 (match_operand:VQX 2 "s_register_operand" "0") 4103 (match_operand:SI 3 "immediate_operand" "i")] 4104 UNSPEC_VLD1_LANE))] 4105 "TARGET_NEON" 4106{ 4107 HOST_WIDE_INT lane = INTVAL (operands[3]); 4108 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4109 int regno = REGNO (operands[0]); 4110 if (lane < 0 || lane >= max) 4111 error ("lane out of range"); 4112 else if (lane >= max / 2) 4113 { 4114 lane -= max / 2; 4115 regno += 2; 4116 operands[3] = GEN_INT (lane); 4117 } 4118 operands[0] = gen_rtx_REG (<V_HALF>mode, regno); 4119 if (max == 2) 4120 return "vld1.<V_sz_elem>\t%P0, [%1]"; 4121 else 4122 return "vld1.<V_sz_elem>\t{%P0[%c3]}, [%1]"; 4123} 4124 [(set (attr "neon_type") 4125 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 2)) 4126 (const_string "neon_vld1_1_2_regs") 4127 (const_string "neon_vld1_vld2_lane")))] 4128) 4129 4130(define_insn "neon_vld1_dup<mode>" 4131 [(set (match_operand:VDX 0 "s_register_operand" "=w") 4132 (unspec:VDX [(mem:<V_elem> (match_operand:SI 1 "s_register_operand" "r"))] 4133 UNSPEC_VLD1_DUP))] 4134 "TARGET_NEON" 4135{ 4136 if (GET_MODE_NUNITS (<MODE>mode) > 1) 4137 return "vld1.<V_sz_elem>\t{%P0[]}, [%1]"; 4138 else 4139 return "vld1.<V_sz_elem>\t%h0, [%1]"; 4140} 4141 [(set (attr "neon_type") 4142 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) 4143 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes") 4144 (const_string "neon_vld1_1_2_regs")))] 4145) 4146 4147(define_insn "neon_vld1_dup<mode>" 4148 [(set (match_operand:VQX 0 "s_register_operand" "=w") 4149 (unspec:VQX [(mem:<V_elem> (match_operand:SI 1 "s_register_operand" "r"))] 4150 UNSPEC_VLD1_DUP))] 4151 "TARGET_NEON" 4152{ 4153 if (GET_MODE_NUNITS (<MODE>mode) > 2) 4154 return "vld1.<V_sz_elem>\t{%e0[], %f0[]}, [%1]"; 4155 else 4156 return "vld1.<V_sz_elem>\t%h0, [%1]"; 4157} 4158 [(set (attr "neon_type") 4159 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) 4160 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes") 4161 (const_string "neon_vld1_1_2_regs")))] 4162) 4163 4164(define_insn "neon_vst1<mode>" 4165 [(set (mem:VDQX (match_operand:SI 0 "s_register_operand" "r")) 4166 (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")] 4167 UNSPEC_VST1))] 4168 "TARGET_NEON" 4169 "vst1.<V_sz_elem>\t%h1, [%0]" 4170 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")]) 4171 4172(define_insn "neon_vst1_lane<mode>" 4173 [(set (mem:<V_elem> (match_operand:SI 0 "s_register_operand" "r")) 4174 (vec_select:<V_elem> 4175 (match_operand:VDX 1 "s_register_operand" "w") 4176 (parallel [(match_operand:SI 2 "neon_lane_number" "i")])))] 4177 "TARGET_NEON" 4178{ 4179 HOST_WIDE_INT lane = INTVAL (operands[2]); 4180 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4181 if (lane < 0 || lane >= max) 4182 error ("lane out of range"); 4183 if (max == 1) 4184 return "vst1.<V_sz_elem>\t{%P1}, [%0]"; 4185 else 4186 return "vst1.<V_sz_elem>\t{%P1[%c2]}, [%0]"; 4187} 4188 [(set (attr "neon_type") 4189 (if_then_else (eq (const_string "<V_mode_nunits>") (const_int 1)) 4190 (const_string "neon_vst1_1_2_regs_vst2_2_regs") 4191 (const_string "neon_vst1_vst2_lane")))]) 4192 4193(define_insn "neon_vst1_lane<mode>" 4194 [(set (mem:<V_elem> (match_operand:SI 0 "s_register_operand" "r")) 4195 (vec_select:<V_elem> 4196 (match_operand:VQX 1 "s_register_operand" "w") 4197 (parallel [(match_operand:SI 2 "neon_lane_number" "i")])))] 4198 "TARGET_NEON" 4199{ 4200 HOST_WIDE_INT lane = INTVAL (operands[2]); 4201 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4202 int regno = REGNO (operands[1]); 4203 if (lane < 0 || lane >= max) 4204 error ("lane out of range"); 4205 else if (lane >= max / 2) 4206 { 4207 lane -= max / 2; 4208 regno += 2; 4209 operands[2] = GEN_INT (lane); 4210 } 4211 operands[1] = gen_rtx_REG (<V_HALF>mode, regno); 4212 if (max == 2) 4213 return "vst1.<V_sz_elem>\t{%P1}, [%0]"; 4214 else 4215 return "vst1.<V_sz_elem>\t{%P1[%c2]}, [%0]"; 4216} 4217 [(set_attr "neon_type" "neon_vst1_vst2_lane")] 4218) 4219 4220(define_insn "neon_vld2<mode>" 4221 [(set (match_operand:TI 0 "s_register_operand" "=w") 4222 (unspec:TI [(mem:TI (match_operand:SI 1 "s_register_operand" "r")) 4223 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4224 UNSPEC_VLD2))] 4225 "TARGET_NEON" 4226{ 4227 if (<V_sz_elem> == 64) 4228 return "vld1.64\t%h0, [%1]"; 4229 else 4230 return "vld2.<V_sz_elem>\t%h0, [%1]"; 4231} 4232 [(set (attr "neon_type") 4233 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) 4234 (const_string "neon_vld1_1_2_regs") 4235 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")))] 4236) 4237 4238(define_insn "neon_vld2<mode>" 4239 [(set (match_operand:OI 0 "s_register_operand" "=w") 4240 (unspec:OI [(mem:OI (match_operand:SI 1 "s_register_operand" "r")) 4241 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4242 UNSPEC_VLD2))] 4243 "TARGET_NEON" 4244 "vld2.<V_sz_elem>\t%h0, [%1]" 4245 [(set_attr "neon_type" "neon_vld2_2_regs_vld1_vld2_all_lanes")]) 4246 4247(define_insn "neon_vld2_lane<mode>" 4248 [(set (match_operand:TI 0 "s_register_operand" "=w") 4249 (unspec:TI [(mem:<V_two_elem> (match_operand:SI 1 "s_register_operand" "r")) 4250 (match_operand:TI 2 "s_register_operand" "0") 4251 (match_operand:SI 3 "immediate_operand" "i") 4252 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4253 UNSPEC_VLD2_LANE))] 4254 "TARGET_NEON" 4255{ 4256 HOST_WIDE_INT lane = INTVAL (operands[3]); 4257 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4258 int regno = REGNO (operands[0]); 4259 rtx ops[4]; 4260 if (lane < 0 || lane >= max) 4261 error ("lane out of range"); 4262 ops[0] = gen_rtx_REG (DImode, regno); 4263 ops[1] = gen_rtx_REG (DImode, regno + 2); 4264 ops[2] = operands[1]; 4265 ops[3] = operands[3]; 4266 output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, [%2]", ops); 4267 return ""; 4268} 4269 [(set_attr "neon_type" "neon_vld1_vld2_lane")] 4270) 4271 4272(define_insn "neon_vld2_lane<mode>" 4273 [(set (match_operand:OI 0 "s_register_operand" "=w") 4274 (unspec:OI [(mem:<V_two_elem> (match_operand:SI 1 "s_register_operand" "r")) 4275 (match_operand:OI 2 "s_register_operand" "0") 4276 (match_operand:SI 3 "immediate_operand" "i") 4277 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4278 UNSPEC_VLD2_LANE))] 4279 "TARGET_NEON" 4280{ 4281 HOST_WIDE_INT lane = INTVAL (operands[3]); 4282 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4283 int regno = REGNO (operands[0]); 4284 rtx ops[4]; 4285 if (lane < 0 || lane >= max) 4286 error ("lane out of range"); 4287 else if (lane >= max / 2) 4288 { 4289 lane -= max / 2; 4290 regno += 2; 4291 } 4292 ops[0] = gen_rtx_REG (DImode, regno); 4293 ops[1] = gen_rtx_REG (DImode, regno + 4); 4294 ops[2] = operands[1]; 4295 ops[3] = GEN_INT (lane); 4296 output_asm_insn ("vld2.<V_sz_elem>\t{%P0[%c3], %P1[%c3]}, [%2]", ops); 4297 return ""; 4298} 4299 [(set_attr "neon_type" "neon_vld1_vld2_lane")] 4300) 4301 4302(define_insn "neon_vld2_dup<mode>" 4303 [(set (match_operand:TI 0 "s_register_operand" "=w") 4304 (unspec:TI [(mem:<V_two_elem> (match_operand:SI 1 "s_register_operand" "r")) 4305 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4306 UNSPEC_VLD2_DUP))] 4307 "TARGET_NEON" 4308{ 4309 if (GET_MODE_NUNITS (<MODE>mode) > 1) 4310 return "vld2.<V_sz_elem>\t{%e0[], %f0[]}, [%1]"; 4311 else 4312 return "vld1.<V_sz_elem>\t%h0, [%1]"; 4313} 4314 [(set (attr "neon_type") 4315 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) 4316 (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes") 4317 (const_string "neon_vld1_1_2_regs")))] 4318) 4319 4320(define_insn "neon_vst2<mode>" 4321 [(set (mem:TI (match_operand:SI 0 "s_register_operand" "r")) 4322 (unspec:TI [(match_operand:TI 1 "s_register_operand" "w") 4323 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4324 UNSPEC_VST2))] 4325 "TARGET_NEON" 4326{ 4327 if (<V_sz_elem> == 64) 4328 return "vst1.64\t%h1, [%0]"; 4329 else 4330 return "vst2.<V_sz_elem>\t%h1, [%0]"; 4331} 4332 [(set (attr "neon_type") 4333 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) 4334 (const_string "neon_vst1_1_2_regs_vst2_2_regs") 4335 (const_string "neon_vst1_1_2_regs_vst2_2_regs")))] 4336) 4337 4338(define_insn "neon_vst2<mode>" 4339 [(set (mem:OI (match_operand:SI 0 "s_register_operand" "r")) 4340 (unspec:OI [(match_operand:OI 1 "s_register_operand" "w") 4341 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4342 UNSPEC_VST2))] 4343 "TARGET_NEON" 4344 "vst2.<V_sz_elem>\t%h1, [%0]" 4345 [(set_attr "neon_type" "neon_vst1_1_2_regs_vst2_2_regs")] 4346) 4347 4348(define_insn "neon_vst2_lane<mode>" 4349 [(set (mem:<V_two_elem> (match_operand:SI 0 "s_register_operand" "r")) 4350 (unspec:<V_two_elem> 4351 [(match_operand:TI 1 "s_register_operand" "w") 4352 (match_operand:SI 2 "immediate_operand" "i") 4353 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4354 UNSPEC_VST2_LANE))] 4355 "TARGET_NEON" 4356{ 4357 HOST_WIDE_INT lane = INTVAL (operands[2]); 4358 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4359 int regno = REGNO (operands[1]); 4360 rtx ops[4]; 4361 if (lane < 0 || lane >= max) 4362 error ("lane out of range"); 4363 ops[0] = operands[0]; 4364 ops[1] = gen_rtx_REG (DImode, regno); 4365 ops[2] = gen_rtx_REG (DImode, regno + 2); 4366 ops[3] = operands[2]; 4367 output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, [%0]", ops); 4368 return ""; 4369} 4370 [(set_attr "neon_type" "neon_vst1_vst2_lane")] 4371) 4372 4373(define_insn "neon_vst2_lane<mode>" 4374 [(set (mem:<V_two_elem> (match_operand:SI 0 "s_register_operand" "r")) 4375 (unspec:<V_two_elem> 4376 [(match_operand:OI 1 "s_register_operand" "w") 4377 (match_operand:SI 2 "immediate_operand" "i") 4378 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4379 UNSPEC_VST2_LANE))] 4380 "TARGET_NEON" 4381{ 4382 HOST_WIDE_INT lane = INTVAL (operands[2]); 4383 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4384 int regno = REGNO (operands[1]); 4385 rtx ops[4]; 4386 if (lane < 0 || lane >= max) 4387 error ("lane out of range"); 4388 else if (lane >= max / 2) 4389 { 4390 lane -= max / 2; 4391 regno += 2; 4392 } 4393 ops[0] = operands[0]; 4394 ops[1] = gen_rtx_REG (DImode, regno); 4395 ops[2] = gen_rtx_REG (DImode, regno + 4); 4396 ops[3] = GEN_INT (lane); 4397 output_asm_insn ("vst2.<V_sz_elem>\t{%P1[%c3], %P2[%c3]}, [%0]", ops); 4398 return ""; 4399} 4400 [(set_attr "neon_type" "neon_vst1_vst2_lane")] 4401) 4402 4403(define_insn "neon_vld3<mode>" 4404 [(set (match_operand:EI 0 "s_register_operand" "=w") 4405 (unspec:EI [(mem:EI (match_operand:SI 1 "s_register_operand" "r")) 4406 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4407 UNSPEC_VLD3))] 4408 "TARGET_NEON" 4409{ 4410 if (<V_sz_elem> == 64) 4411 return "vld1.64\t%h0, [%1]"; 4412 else 4413 return "vld3.<V_sz_elem>\t%h0, [%1]"; 4414} 4415 [(set (attr "neon_type") 4416 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) 4417 (const_string "neon_vld1_1_2_regs") 4418 (const_string "neon_vld3_vld4")))] 4419) 4420 4421(define_expand "neon_vld3<mode>" 4422 [(match_operand:CI 0 "s_register_operand" "=w") 4423 (match_operand:SI 1 "s_register_operand" "+r") 4424 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4425 "TARGET_NEON" 4426{ 4427 emit_insn (gen_neon_vld3qa<mode> (operands[0], operands[0], 4428 operands[1], operands[1])); 4429 emit_insn (gen_neon_vld3qb<mode> (operands[0], operands[0], 4430 operands[1], operands[1])); 4431 DONE; 4432}) 4433 4434(define_insn "neon_vld3qa<mode>" 4435 [(set (match_operand:CI 0 "s_register_operand" "=w") 4436 (unspec:CI [(mem:CI (match_operand:SI 3 "s_register_operand" "2")) 4437 (match_operand:CI 1 "s_register_operand" "0") 4438 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4439 UNSPEC_VLD3A)) 4440 (set (match_operand:SI 2 "s_register_operand" "=r") 4441 (plus:SI (match_dup 3) 4442 (const_int 24)))] 4443 "TARGET_NEON" 4444{ 4445 int regno = REGNO (operands[0]); 4446 rtx ops[4]; 4447 ops[0] = gen_rtx_REG (DImode, regno); 4448 ops[1] = gen_rtx_REG (DImode, regno + 4); 4449 ops[2] = gen_rtx_REG (DImode, regno + 8); 4450 ops[3] = operands[2]; 4451 output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, [%3]!", ops); 4452 return ""; 4453} 4454 [(set_attr "neon_type" "neon_vld3_vld4")] 4455) 4456 4457(define_insn "neon_vld3qb<mode>" 4458 [(set (match_operand:CI 0 "s_register_operand" "=w") 4459 (unspec:CI [(mem:CI (match_operand:SI 3 "s_register_operand" "2")) 4460 (match_operand:CI 1 "s_register_operand" "0") 4461 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4462 UNSPEC_VLD3B)) 4463 (set (match_operand:SI 2 "s_register_operand" "=r") 4464 (plus:SI (match_dup 3) 4465 (const_int 24)))] 4466 "TARGET_NEON" 4467{ 4468 int regno = REGNO (operands[0]); 4469 rtx ops[4]; 4470 ops[0] = gen_rtx_REG (DImode, regno + 2); 4471 ops[1] = gen_rtx_REG (DImode, regno + 6); 4472 ops[2] = gen_rtx_REG (DImode, regno + 10); 4473 ops[3] = operands[2]; 4474 output_asm_insn ("vld3.<V_sz_elem>\t{%P0, %P1, %P2}, [%3]!", ops); 4475 return ""; 4476} 4477 [(set_attr "neon_type" "neon_vld3_vld4")] 4478) 4479 4480(define_insn "neon_vld3_lane<mode>" 4481 [(set (match_operand:EI 0 "s_register_operand" "=w") 4482 (unspec:EI [(mem:<V_three_elem> (match_operand:SI 1 "s_register_operand" "r")) 4483 (match_operand:EI 2 "s_register_operand" "0") 4484 (match_operand:SI 3 "immediate_operand" "i") 4485 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4486 UNSPEC_VLD3_LANE))] 4487 "TARGET_NEON" 4488{ 4489 HOST_WIDE_INT lane = INTVAL (operands[3]); 4490 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4491 int regno = REGNO (operands[0]); 4492 rtx ops[5]; 4493 if (lane < 0 || lane >= max) 4494 error ("lane out of range"); 4495 ops[0] = gen_rtx_REG (DImode, regno); 4496 ops[1] = gen_rtx_REG (DImode, regno + 2); 4497 ops[2] = gen_rtx_REG (DImode, regno + 4); 4498 ops[3] = operands[1]; 4499 ops[4] = operands[3]; 4500 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, [%3]", 4501 ops); 4502 return ""; 4503} 4504 [(set_attr "neon_type" "neon_vld3_vld4_lane")] 4505) 4506 4507(define_insn "neon_vld3_lane<mode>" 4508 [(set (match_operand:CI 0 "s_register_operand" "=w") 4509 (unspec:CI [(mem:<V_three_elem> (match_operand:SI 1 "s_register_operand" "r")) 4510 (match_operand:CI 2 "s_register_operand" "0") 4511 (match_operand:SI 3 "immediate_operand" "i") 4512 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4513 UNSPEC_VLD3_LANE))] 4514 "TARGET_NEON" 4515{ 4516 HOST_WIDE_INT lane = INTVAL (operands[3]); 4517 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4518 int regno = REGNO (operands[0]); 4519 rtx ops[5]; 4520 if (lane < 0 || lane >= max) 4521 error ("lane out of range"); 4522 else if (lane >= max / 2) 4523 { 4524 lane -= max / 2; 4525 regno += 2; 4526 } 4527 ops[0] = gen_rtx_REG (DImode, regno); 4528 ops[1] = gen_rtx_REG (DImode, regno + 4); 4529 ops[2] = gen_rtx_REG (DImode, regno + 8); 4530 ops[3] = operands[1]; 4531 ops[4] = GEN_INT (lane); 4532 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[%c4], %P1[%c4], %P2[%c4]}, [%3]", 4533 ops); 4534 return ""; 4535} 4536 [(set_attr "neon_type" "neon_vld3_vld4_lane")] 4537) 4538 4539(define_insn "neon_vld3_dup<mode>" 4540 [(set (match_operand:EI 0 "s_register_operand" "=w") 4541 (unspec:EI [(mem:<V_three_elem> (match_operand:SI 1 "s_register_operand" "r")) 4542 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4543 UNSPEC_VLD3_DUP))] 4544 "TARGET_NEON" 4545{ 4546 if (GET_MODE_NUNITS (<MODE>mode) > 1) 4547 { 4548 int regno = REGNO (operands[0]); 4549 rtx ops[4]; 4550 ops[0] = gen_rtx_REG (DImode, regno); 4551 ops[1] = gen_rtx_REG (DImode, regno + 2); 4552 ops[2] = gen_rtx_REG (DImode, regno + 4); 4553 ops[3] = operands[1]; 4554 output_asm_insn ("vld3.<V_sz_elem>\t{%P0[], %P1[], %P2[]}, [%3]", ops); 4555 return ""; 4556 } 4557 else 4558 return "vld1.<V_sz_elem>\t%h0, [%1]"; 4559} 4560 [(set (attr "neon_type") 4561 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) 4562 (const_string "neon_vld3_vld4_all_lanes") 4563 (const_string "neon_vld1_1_2_regs")))]) 4564 4565(define_insn "neon_vst3<mode>" 4566 [(set (mem:EI (match_operand:SI 0 "s_register_operand" "r")) 4567 (unspec:EI [(match_operand:EI 1 "s_register_operand" "w") 4568 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4569 UNSPEC_VST3))] 4570 "TARGET_NEON" 4571{ 4572 if (<V_sz_elem> == 64) 4573 return "vst1.64\t%h1, [%0]"; 4574 else 4575 return "vst3.<V_sz_elem>\t%h1, [%0]"; 4576} 4577 [(set (attr "neon_type") 4578 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) 4579 (const_string "neon_vst1_1_2_regs_vst2_2_regs") 4580 (const_string "neon_vst2_4_regs_vst3_vst4")))]) 4581 4582(define_expand "neon_vst3<mode>" 4583 [(match_operand:SI 0 "s_register_operand" "+r") 4584 (match_operand:CI 1 "s_register_operand" "w") 4585 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4586 "TARGET_NEON" 4587{ 4588 emit_insn (gen_neon_vst3qa<mode> (operands[0], operands[0], operands[1])); 4589 emit_insn (gen_neon_vst3qb<mode> (operands[0], operands[0], operands[1])); 4590 DONE; 4591}) 4592 4593(define_insn "neon_vst3qa<mode>" 4594 [(set (mem:EI (match_operand:SI 1 "s_register_operand" "0")) 4595 (unspec:EI [(match_operand:CI 2 "s_register_operand" "w") 4596 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4597 UNSPEC_VST3A)) 4598 (set (match_operand:SI 0 "s_register_operand" "=r") 4599 (plus:SI (match_dup 1) 4600 (const_int 24)))] 4601 "TARGET_NEON" 4602{ 4603 int regno = REGNO (operands[2]); 4604 rtx ops[4]; 4605 ops[0] = operands[0]; 4606 ops[1] = gen_rtx_REG (DImode, regno); 4607 ops[2] = gen_rtx_REG (DImode, regno + 4); 4608 ops[3] = gen_rtx_REG (DImode, regno + 8); 4609 output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, [%0]!", ops); 4610 return ""; 4611} 4612 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")] 4613) 4614 4615(define_insn "neon_vst3qb<mode>" 4616 [(set (mem:EI (match_operand:SI 1 "s_register_operand" "0")) 4617 (unspec:EI [(match_operand:CI 2 "s_register_operand" "w") 4618 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4619 UNSPEC_VST3B)) 4620 (set (match_operand:SI 0 "s_register_operand" "=r") 4621 (plus:SI (match_dup 1) 4622 (const_int 24)))] 4623 "TARGET_NEON" 4624{ 4625 int regno = REGNO (operands[2]); 4626 rtx ops[4]; 4627 ops[0] = operands[0]; 4628 ops[1] = gen_rtx_REG (DImode, regno + 2); 4629 ops[2] = gen_rtx_REG (DImode, regno + 6); 4630 ops[3] = gen_rtx_REG (DImode, regno + 10); 4631 output_asm_insn ("vst3.<V_sz_elem>\t{%P1, %P2, %P3}, [%0]!", ops); 4632 return ""; 4633} 4634 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")] 4635) 4636 4637(define_insn "neon_vst3_lane<mode>" 4638 [(set (mem:<V_three_elem> (match_operand:SI 0 "s_register_operand" "r")) 4639 (unspec:<V_three_elem> 4640 [(match_operand:EI 1 "s_register_operand" "w") 4641 (match_operand:SI 2 "immediate_operand" "i") 4642 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4643 UNSPEC_VST3_LANE))] 4644 "TARGET_NEON" 4645{ 4646 HOST_WIDE_INT lane = INTVAL (operands[2]); 4647 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4648 int regno = REGNO (operands[1]); 4649 rtx ops[5]; 4650 if (lane < 0 || lane >= max) 4651 error ("lane out of range"); 4652 ops[0] = operands[0]; 4653 ops[1] = gen_rtx_REG (DImode, regno); 4654 ops[2] = gen_rtx_REG (DImode, regno + 2); 4655 ops[3] = gen_rtx_REG (DImode, regno + 4); 4656 ops[4] = operands[2]; 4657 output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, [%0]", 4658 ops); 4659 return ""; 4660} 4661 [(set_attr "neon_type" "neon_vst3_vst4_lane")] 4662) 4663 4664(define_insn "neon_vst3_lane<mode>" 4665 [(set (mem:<V_three_elem> (match_operand:SI 0 "s_register_operand" "r")) 4666 (unspec:<V_three_elem> 4667 [(match_operand:CI 1 "s_register_operand" "w") 4668 (match_operand:SI 2 "immediate_operand" "i") 4669 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4670 UNSPEC_VST3_LANE))] 4671 "TARGET_NEON" 4672{ 4673 HOST_WIDE_INT lane = INTVAL (operands[2]); 4674 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4675 int regno = REGNO (operands[1]); 4676 rtx ops[5]; 4677 if (lane < 0 || lane >= max) 4678 error ("lane out of range"); 4679 else if (lane >= max / 2) 4680 { 4681 lane -= max / 2; 4682 regno += 2; 4683 } 4684 ops[0] = operands[0]; 4685 ops[1] = gen_rtx_REG (DImode, regno); 4686 ops[2] = gen_rtx_REG (DImode, regno + 4); 4687 ops[3] = gen_rtx_REG (DImode, regno + 8); 4688 ops[4] = GEN_INT (lane); 4689 output_asm_insn ("vst3.<V_sz_elem>\t{%P1[%c4], %P2[%c4], %P3[%c4]}, [%0]", 4690 ops); 4691 return ""; 4692} 4693[(set_attr "neon_type" "neon_vst3_vst4_lane")]) 4694 4695(define_insn "neon_vld4<mode>" 4696 [(set (match_operand:OI 0 "s_register_operand" "=w") 4697 (unspec:OI [(mem:OI (match_operand:SI 1 "s_register_operand" "r")) 4698 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4699 UNSPEC_VLD4))] 4700 "TARGET_NEON" 4701{ 4702 if (<V_sz_elem> == 64) 4703 return "vld1.64\t%h0, [%1]"; 4704 else 4705 return "vld4.<V_sz_elem>\t%h0, [%1]"; 4706} 4707 [(set (attr "neon_type") 4708 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) 4709 (const_string "neon_vld1_1_2_regs") 4710 (const_string "neon_vld3_vld4")))] 4711) 4712 4713(define_expand "neon_vld4<mode>" 4714 [(match_operand:XI 0 "s_register_operand" "=w") 4715 (match_operand:SI 1 "s_register_operand" "+r") 4716 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4717 "TARGET_NEON" 4718{ 4719 emit_insn (gen_neon_vld4qa<mode> (operands[0], operands[0], 4720 operands[1], operands[1])); 4721 emit_insn (gen_neon_vld4qb<mode> (operands[0], operands[0], 4722 operands[1], operands[1])); 4723 DONE; 4724}) 4725 4726(define_insn "neon_vld4qa<mode>" 4727 [(set (match_operand:XI 0 "s_register_operand" "=w") 4728 (unspec:XI [(mem:XI (match_operand:SI 3 "s_register_operand" "2")) 4729 (match_operand:XI 1 "s_register_operand" "0") 4730 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4731 UNSPEC_VLD4A)) 4732 (set (match_operand:SI 2 "s_register_operand" "=r") 4733 (plus:SI (match_dup 3) 4734 (const_int 32)))] 4735 "TARGET_NEON" 4736{ 4737 int regno = REGNO (operands[0]); 4738 rtx ops[5]; 4739 ops[0] = gen_rtx_REG (DImode, regno); 4740 ops[1] = gen_rtx_REG (DImode, regno + 4); 4741 ops[2] = gen_rtx_REG (DImode, regno + 8); 4742 ops[3] = gen_rtx_REG (DImode, regno + 12); 4743 ops[4] = operands[2]; 4744 output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, [%4]!", ops); 4745 return ""; 4746} 4747 [(set_attr "neon_type" "neon_vld3_vld4")] 4748) 4749 4750(define_insn "neon_vld4qb<mode>" 4751 [(set (match_operand:XI 0 "s_register_operand" "=w") 4752 (unspec:XI [(mem:XI (match_operand:SI 3 "s_register_operand" "2")) 4753 (match_operand:XI 1 "s_register_operand" "0") 4754 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4755 UNSPEC_VLD4B)) 4756 (set (match_operand:SI 2 "s_register_operand" "=r") 4757 (plus:SI (match_dup 3) 4758 (const_int 32)))] 4759 "TARGET_NEON" 4760{ 4761 int regno = REGNO (operands[0]); 4762 rtx ops[5]; 4763 ops[0] = gen_rtx_REG (DImode, regno + 2); 4764 ops[1] = gen_rtx_REG (DImode, regno + 6); 4765 ops[2] = gen_rtx_REG (DImode, regno + 10); 4766 ops[3] = gen_rtx_REG (DImode, regno + 14); 4767 ops[4] = operands[2]; 4768 output_asm_insn ("vld4.<V_sz_elem>\t{%P0, %P1, %P2, %P3}, [%4]!", ops); 4769 return ""; 4770} 4771 [(set_attr "neon_type" "neon_vld3_vld4")] 4772) 4773 4774(define_insn "neon_vld4_lane<mode>" 4775 [(set (match_operand:OI 0 "s_register_operand" "=w") 4776 (unspec:OI [(mem:<V_four_elem> (match_operand:SI 1 "s_register_operand" "r")) 4777 (match_operand:OI 2 "s_register_operand" "0") 4778 (match_operand:SI 3 "immediate_operand" "i") 4779 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4780 UNSPEC_VLD4_LANE))] 4781 "TARGET_NEON" 4782{ 4783 HOST_WIDE_INT lane = INTVAL (operands[3]); 4784 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4785 int regno = REGNO (operands[0]); 4786 rtx ops[6]; 4787 if (lane < 0 || lane >= max) 4788 error ("lane out of range"); 4789 ops[0] = gen_rtx_REG (DImode, regno); 4790 ops[1] = gen_rtx_REG (DImode, regno + 2); 4791 ops[2] = gen_rtx_REG (DImode, regno + 4); 4792 ops[3] = gen_rtx_REG (DImode, regno + 6); 4793 ops[4] = operands[1]; 4794 ops[5] = operands[3]; 4795 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, [%4]", 4796 ops); 4797 return ""; 4798} 4799 [(set_attr "neon_type" "neon_vld3_vld4_lane")] 4800) 4801 4802(define_insn "neon_vld4_lane<mode>" 4803 [(set (match_operand:XI 0 "s_register_operand" "=w") 4804 (unspec:XI [(mem:<V_four_elem> (match_operand:SI 1 "s_register_operand" "r")) 4805 (match_operand:XI 2 "s_register_operand" "0") 4806 (match_operand:SI 3 "immediate_operand" "i") 4807 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4808 UNSPEC_VLD4_LANE))] 4809 "TARGET_NEON" 4810{ 4811 HOST_WIDE_INT lane = INTVAL (operands[3]); 4812 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4813 int regno = REGNO (operands[0]); 4814 rtx ops[6]; 4815 if (lane < 0 || lane >= max) 4816 error ("lane out of range"); 4817 else if (lane >= max / 2) 4818 { 4819 lane -= max / 2; 4820 regno += 2; 4821 } 4822 ops[0] = gen_rtx_REG (DImode, regno); 4823 ops[1] = gen_rtx_REG (DImode, regno + 4); 4824 ops[2] = gen_rtx_REG (DImode, regno + 8); 4825 ops[3] = gen_rtx_REG (DImode, regno + 12); 4826 ops[4] = operands[1]; 4827 ops[5] = GEN_INT (lane); 4828 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[%c5], %P1[%c5], %P2[%c5], %P3[%c5]}, [%4]", 4829 ops); 4830 return ""; 4831} 4832 [(set_attr "neon_type" "neon_vld3_vld4_lane")] 4833) 4834 4835(define_insn "neon_vld4_dup<mode>" 4836 [(set (match_operand:OI 0 "s_register_operand" "=w") 4837 (unspec:OI [(mem:<V_four_elem> (match_operand:SI 1 "s_register_operand" "r")) 4838 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4839 UNSPEC_VLD4_DUP))] 4840 "TARGET_NEON" 4841{ 4842 if (GET_MODE_NUNITS (<MODE>mode) > 1) 4843 { 4844 int regno = REGNO (operands[0]); 4845 rtx ops[5]; 4846 ops[0] = gen_rtx_REG (DImode, regno); 4847 ops[1] = gen_rtx_REG (DImode, regno + 2); 4848 ops[2] = gen_rtx_REG (DImode, regno + 4); 4849 ops[3] = gen_rtx_REG (DImode, regno + 6); 4850 ops[4] = operands[1]; 4851 output_asm_insn ("vld4.<V_sz_elem>\t{%P0[], %P1[], %P2[], %P3[]}, [%4]", 4852 ops); 4853 return ""; 4854 } 4855 else 4856 return "vld1.<V_sz_elem>\t%h0, [%1]"; 4857} 4858 [(set (attr "neon_type") 4859 (if_then_else (gt (const_string "<V_mode_nunits>") (const_string "1")) 4860 (const_string "neon_vld3_vld4_all_lanes") 4861 (const_string "neon_vld1_1_2_regs")))] 4862) 4863 4864(define_insn "neon_vst4<mode>" 4865 [(set (mem:OI (match_operand:SI 0 "s_register_operand" "r")) 4866 (unspec:OI [(match_operand:OI 1 "s_register_operand" "w") 4867 (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4868 UNSPEC_VST4))] 4869 "TARGET_NEON" 4870{ 4871 if (<V_sz_elem> == 64) 4872 return "vst1.64\t%h1, [%0]"; 4873 else 4874 return "vst4.<V_sz_elem>\t%h1, [%0]"; 4875} 4876 [(set (attr "neon_type") 4877 (if_then_else (eq (const_string "<V_sz_elem>") (const_string "64")) 4878 (const_string "neon_vst1_1_2_regs_vst2_2_regs") 4879 (const_string "neon_vst2_4_regs_vst3_vst4")))] 4880) 4881 4882(define_expand "neon_vst4<mode>" 4883 [(match_operand:SI 0 "s_register_operand" "+r") 4884 (match_operand:XI 1 "s_register_operand" "w") 4885 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4886 "TARGET_NEON" 4887{ 4888 emit_insn (gen_neon_vst4qa<mode> (operands[0], operands[0], operands[1])); 4889 emit_insn (gen_neon_vst4qb<mode> (operands[0], operands[0], operands[1])); 4890 DONE; 4891}) 4892 4893(define_insn "neon_vst4qa<mode>" 4894 [(set (mem:OI (match_operand:SI 1 "s_register_operand" "0")) 4895 (unspec:OI [(match_operand:XI 2 "s_register_operand" "w") 4896 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4897 UNSPEC_VST4A)) 4898 (set (match_operand:SI 0 "s_register_operand" "=r") 4899 (plus:SI (match_dup 1) 4900 (const_int 32)))] 4901 "TARGET_NEON" 4902{ 4903 int regno = REGNO (operands[2]); 4904 rtx ops[5]; 4905 ops[0] = operands[0]; 4906 ops[1] = gen_rtx_REG (DImode, regno); 4907 ops[2] = gen_rtx_REG (DImode, regno + 4); 4908 ops[3] = gen_rtx_REG (DImode, regno + 8); 4909 ops[4] = gen_rtx_REG (DImode, regno + 12); 4910 output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, [%0]!", ops); 4911 return ""; 4912} 4913 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")] 4914) 4915 4916(define_insn "neon_vst4qb<mode>" 4917 [(set (mem:OI (match_operand:SI 1 "s_register_operand" "0")) 4918 (unspec:OI [(match_operand:XI 2 "s_register_operand" "w") 4919 (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4920 UNSPEC_VST4B)) 4921 (set (match_operand:SI 0 "s_register_operand" "=r") 4922 (plus:SI (match_dup 1) 4923 (const_int 32)))] 4924 "TARGET_NEON" 4925{ 4926 int regno = REGNO (operands[2]); 4927 rtx ops[5]; 4928 ops[0] = operands[0]; 4929 ops[1] = gen_rtx_REG (DImode, regno + 2); 4930 ops[2] = gen_rtx_REG (DImode, regno + 6); 4931 ops[3] = gen_rtx_REG (DImode, regno + 10); 4932 ops[4] = gen_rtx_REG (DImode, regno + 14); 4933 output_asm_insn ("vst4.<V_sz_elem>\t{%P1, %P2, %P3, %P4}, [%0]!", ops); 4934 return ""; 4935} 4936 [(set_attr "neon_type" "neon_vst2_4_regs_vst3_vst4")] 4937) 4938 4939(define_insn "neon_vst4_lane<mode>" 4940 [(set (mem:<V_four_elem> (match_operand:SI 0 "s_register_operand" "r")) 4941 (unspec:<V_four_elem> 4942 [(match_operand:OI 1 "s_register_operand" "w") 4943 (match_operand:SI 2 "immediate_operand" "i") 4944 (unspec:VD [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4945 UNSPEC_VST4_LANE))] 4946 "TARGET_NEON" 4947{ 4948 HOST_WIDE_INT lane = INTVAL (operands[2]); 4949 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4950 int regno = REGNO (operands[1]); 4951 rtx ops[6]; 4952 if (lane < 0 || lane >= max) 4953 error ("lane out of range"); 4954 ops[0] = operands[0]; 4955 ops[1] = gen_rtx_REG (DImode, regno); 4956 ops[2] = gen_rtx_REG (DImode, regno + 2); 4957 ops[3] = gen_rtx_REG (DImode, regno + 4); 4958 ops[4] = gen_rtx_REG (DImode, regno + 6); 4959 ops[5] = operands[2]; 4960 output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, [%0]", 4961 ops); 4962 return ""; 4963} 4964 [(set_attr "neon_type" "neon_vst3_vst4_lane")] 4965) 4966 4967(define_insn "neon_vst4_lane<mode>" 4968 [(set (mem:<V_four_elem> (match_operand:SI 0 "s_register_operand" "r")) 4969 (unspec:<V_four_elem> 4970 [(match_operand:XI 1 "s_register_operand" "w") 4971 (match_operand:SI 2 "immediate_operand" "i") 4972 (unspec:VMQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] 4973 UNSPEC_VST4_LANE))] 4974 "TARGET_NEON" 4975{ 4976 HOST_WIDE_INT lane = INTVAL (operands[2]); 4977 HOST_WIDE_INT max = GET_MODE_NUNITS (<MODE>mode); 4978 int regno = REGNO (operands[1]); 4979 rtx ops[6]; 4980 if (lane < 0 || lane >= max) 4981 error ("lane out of range"); 4982 else if (lane >= max / 2) 4983 { 4984 lane -= max / 2; 4985 regno += 2; 4986 } 4987 ops[0] = operands[0]; 4988 ops[1] = gen_rtx_REG (DImode, regno); 4989 ops[2] = gen_rtx_REG (DImode, regno + 4); 4990 ops[3] = gen_rtx_REG (DImode, regno + 8); 4991 ops[4] = gen_rtx_REG (DImode, regno + 12); 4992 ops[5] = GEN_INT (lane); 4993 output_asm_insn ("vst4.<V_sz_elem>\t{%P1[%c5], %P2[%c5], %P3[%c5], %P4[%c5]}, [%0]", 4994 ops); 4995 return ""; 4996} 4997 [(set_attr "neon_type" "neon_vst3_vst4_lane")] 4998) 4999 5000(define_expand "neon_vand<mode>" 5001 [(match_operand:VDQX 0 "s_register_operand" "") 5002 (match_operand:VDQX 1 "s_register_operand" "") 5003 (match_operand:VDQX 2 "neon_inv_logic_op2" "") 5004 (match_operand:SI 3 "immediate_operand" "")] 5005 "TARGET_NEON" 5006{ 5007 emit_insn (gen_and<mode>3<V_suf64> (operands[0], operands[1], operands[2])); 5008 DONE; 5009}) 5010 5011(define_expand "neon_vorr<mode>" 5012 [(match_operand:VDQX 0 "s_register_operand" "") 5013 (match_operand:VDQX 1 "s_register_operand" "") 5014 (match_operand:VDQX 2 "neon_logic_op2" "") 5015 (match_operand:SI 3 "immediate_operand" "")] 5016 "TARGET_NEON" 5017{ 5018 emit_insn (gen_ior<mode>3<V_suf64> (operands[0], operands[1], operands[2])); 5019 DONE; 5020}) 5021 5022(define_expand "neon_veor<mode>" 5023 [(match_operand:VDQX 0 "s_register_operand" "") 5024 (match_operand:VDQX 1 "s_register_operand" "") 5025 (match_operand:VDQX 2 "s_register_operand" "") 5026 (match_operand:SI 3 "immediate_operand" "")] 5027 "TARGET_NEON" 5028{ 5029 emit_insn (gen_xor<mode>3<V_suf64> (operands[0], operands[1], operands[2])); 5030 DONE; 5031}) 5032 5033(define_expand "neon_vbic<mode>" 5034 [(match_operand:VDQX 0 "s_register_operand" "") 5035 (match_operand:VDQX 1 "s_register_operand" "") 5036 (match_operand:VDQX 2 "neon_logic_op2" "") 5037 (match_operand:SI 3 "immediate_operand" "")] 5038 "TARGET_NEON" 5039{ 5040 emit_insn (gen_bic<mode>3_neon (operands[0], operands[1], operands[2])); 5041 DONE; 5042}) 5043 5044(define_expand "neon_vorn<mode>" 5045 [(match_operand:VDQX 0 "s_register_operand" "") 5046 (match_operand:VDQX 1 "s_register_operand" "") 5047 (match_operand:VDQX 2 "neon_inv_logic_op2" "") 5048 (match_operand:SI 3 "immediate_operand" "")] 5049 "TARGET_NEON" 5050{ 5051 emit_insn (gen_orn<mode>3_neon (operands[0], operands[1], operands[2])); 5052 DONE; 5053}) 5054