1;; Machine description for AArch64 architecture. 2;; Copyright (C) 2009-2018 Free Software Foundation, Inc. 3;; Contributed by ARM Ltd. 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;; Register numbers 22(define_constants 23 [ 24 (R0_REGNUM 0) 25 (R1_REGNUM 1) 26 (R2_REGNUM 2) 27 (R3_REGNUM 3) 28 (R4_REGNUM 4) 29 (R5_REGNUM 5) 30 (R6_REGNUM 6) 31 (R7_REGNUM 7) 32 (R8_REGNUM 8) 33 (R9_REGNUM 9) 34 (R10_REGNUM 10) 35 (R11_REGNUM 11) 36 (R12_REGNUM 12) 37 (R13_REGNUM 13) 38 (R14_REGNUM 14) 39 (R15_REGNUM 15) 40 (R16_REGNUM 16) 41 (IP0_REGNUM 16) 42 (R17_REGNUM 17) 43 (IP1_REGNUM 17) 44 (R18_REGNUM 18) 45 (R19_REGNUM 19) 46 (R20_REGNUM 20) 47 (R21_REGNUM 21) 48 (R22_REGNUM 22) 49 (R23_REGNUM 23) 50 (R24_REGNUM 24) 51 (R25_REGNUM 25) 52 (R26_REGNUM 26) 53 (R27_REGNUM 27) 54 (R28_REGNUM 28) 55 (R29_REGNUM 29) 56 (R30_REGNUM 30) 57 (LR_REGNUM 30) 58 (SP_REGNUM 31) 59 (V0_REGNUM 32) 60 (V4_REGNUM 36) 61 (V8_REGNUM 40) 62 (V12_REGNUM 44) 63 (V15_REGNUM 47) 64 (V16_REGNUM 48) 65 (V20_REGNUM 52) 66 (V24_REGNUM 56) 67 (V28_REGNUM 60) 68 (V31_REGNUM 63) 69 (LAST_SAVED_REGNUM 63) 70 (SFP_REGNUM 64) 71 (AP_REGNUM 65) 72 (CC_REGNUM 66) 73 ;; Defined only to make the DWARF description simpler. 74 (VG_REGNUM 67) 75 (P0_REGNUM 68) 76 (P1_REGNUM 69) 77 (P2_REGNUM 70) 78 (P3_REGNUM 71) 79 (P4_REGNUM 72) 80 (P5_REGNUM 73) 81 (P6_REGNUM 74) 82 (P7_REGNUM 75) 83 (P8_REGNUM 76) 84 (P9_REGNUM 77) 85 (P10_REGNUM 78) 86 (P11_REGNUM 79) 87 (P12_REGNUM 80) 88 (P13_REGNUM 81) 89 (P14_REGNUM 82) 90 (P15_REGNUM 83) 91 ] 92) 93 94(define_c_enum "unspec" [ 95 UNSPEC_AUTI1716 96 UNSPEC_AUTISP 97 UNSPEC_CASESI 98 UNSPEC_CRC32B 99 UNSPEC_CRC32CB 100 UNSPEC_CRC32CH 101 UNSPEC_CRC32CW 102 UNSPEC_CRC32CX 103 UNSPEC_CRC32H 104 UNSPEC_CRC32W 105 UNSPEC_CRC32X 106 UNSPEC_FCVTZS 107 UNSPEC_FCVTZU 108 UNSPEC_URECPE 109 UNSPEC_FRECPE 110 UNSPEC_FRECPS 111 UNSPEC_FRECPX 112 UNSPEC_FRINTA 113 UNSPEC_FRINTI 114 UNSPEC_FRINTM 115 UNSPEC_FRINTN 116 UNSPEC_FRINTP 117 UNSPEC_FRINTX 118 UNSPEC_FRINTZ 119 UNSPEC_GOTSMALLPIC 120 UNSPEC_GOTSMALLPIC28K 121 UNSPEC_GOTSMALLTLS 122 UNSPEC_GOTTINYPIC 123 UNSPEC_GOTTINYTLS 124 UNSPEC_LD1 125 UNSPEC_LD2 126 UNSPEC_LD2_DREG 127 UNSPEC_LD2_DUP 128 UNSPEC_LD3 129 UNSPEC_LD3_DREG 130 UNSPEC_LD3_DUP 131 UNSPEC_LD4 132 UNSPEC_LD4_DREG 133 UNSPEC_LD4_DUP 134 UNSPEC_LD2_LANE 135 UNSPEC_LD3_LANE 136 UNSPEC_LD4_LANE 137 UNSPEC_MB 138 UNSPEC_NOP 139 UNSPEC_PACI1716 140 UNSPEC_PACISP 141 UNSPEC_PRLG_STK 142 UNSPEC_REV 143 UNSPEC_RBIT 144 UNSPEC_SCVTF 145 UNSPEC_SISD_NEG 146 UNSPEC_SISD_SSHL 147 UNSPEC_SISD_USHL 148 UNSPEC_SSHL_2S 149 UNSPEC_ST1 150 UNSPEC_ST2 151 UNSPEC_ST3 152 UNSPEC_ST4 153 UNSPEC_ST2_LANE 154 UNSPEC_ST3_LANE 155 UNSPEC_ST4_LANE 156 UNSPEC_TLS 157 UNSPEC_TLSDESC 158 UNSPEC_TLSLE12 159 UNSPEC_TLSLE24 160 UNSPEC_TLSLE32 161 UNSPEC_TLSLE48 162 UNSPEC_UCVTF 163 UNSPEC_USHL_2S 164 UNSPEC_VSTRUCTDUMMY 165 UNSPEC_SP_SET 166 UNSPEC_SP_TEST 167 UNSPEC_RSQRT 168 UNSPEC_RSQRTE 169 UNSPEC_RSQRTS 170 UNSPEC_NZCV 171 UNSPEC_XPACLRI 172 UNSPEC_LD1_SVE 173 UNSPEC_ST1_SVE 174 UNSPEC_LD1RQ 175 UNSPEC_LD1_GATHER 176 UNSPEC_ST1_SCATTER 177 UNSPEC_MERGE_PTRUE 178 UNSPEC_PTEST_PTRUE 179 UNSPEC_UNPACKSHI 180 UNSPEC_UNPACKUHI 181 UNSPEC_UNPACKSLO 182 UNSPEC_UNPACKULO 183 UNSPEC_PACK 184 UNSPEC_FLOAT_CONVERT 185 UNSPEC_WHILE_LO 186 UNSPEC_LDN 187 UNSPEC_STN 188 UNSPEC_INSR 189 UNSPEC_CLASTB 190 UNSPEC_FADDA 191 UNSPEC_REV_SUBREG 192 UNSPEC_COPYSIGN 193]) 194 195(define_c_enum "unspecv" [ 196 UNSPECV_EH_RETURN ; Represent EH_RETURN 197 UNSPECV_GET_FPCR ; Represent fetch of FPCR content. 198 UNSPECV_SET_FPCR ; Represent assign of FPCR content. 199 UNSPECV_GET_FPSR ; Represent fetch of FPSR content. 200 UNSPECV_SET_FPSR ; Represent assign of FPSR content. 201 UNSPECV_BLOCKAGE ; Represent a blockage 202 UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing. 203 ] 204) 205 206;; If further include files are added the defintion of MD_INCLUDES 207;; must be updated. 208 209(include "constraints.md") 210(include "predicates.md") 211(include "iterators.md") 212 213;; ------------------------------------------------------------------- 214;; Instruction types and attributes 215;; ------------------------------------------------------------------- 216 217; The "type" attribute is included here from AArch32 backend to be able 218; to share pipeline descriptions. 219(include "../arm/types.md") 220 221;; It is important to set the fp or simd attributes to yes when a pattern 222;; alternative uses the FP or SIMD register files, usually signified by use of 223;; the 'w' constraint. This will ensure that the alternative will be 224;; disabled when compiling with -mgeneral-regs-only or with the +nofp/+nosimd 225;; architecture extensions. If all the alternatives in a pattern use the 226;; FP or SIMD registers then the pattern predicate should include TARGET_FLOAT 227;; or TARGET_SIMD. 228 229;; Attribute that specifies whether or not the instruction touches fp 230;; registers. When this is set to yes for an alternative, that alternative 231;; will be disabled when !TARGET_FLOAT. 232(define_attr "fp" "no,yes" (const_string "no")) 233 234;; Attribute that specifies whether or not the instruction touches half 235;; precision fp registers. When this is set to yes for an alternative, 236;; that alternative will be disabled when !TARGET_FP_F16INST. 237(define_attr "fp16" "no,yes" (const_string "no")) 238 239;; Attribute that specifies whether or not the instruction touches simd 240;; registers. When this is set to yes for an alternative, that alternative 241;; will be disabled when !TARGET_SIMD. 242(define_attr "simd" "no,yes" (const_string "no")) 243 244;; Attribute that specifies whether or not the instruction uses SVE. 245;; When this is set to yes for an alternative, that alternative 246;; will be disabled when !TARGET_SVE. 247(define_attr "sve" "no,yes" (const_string "no")) 248 249(define_attr "length" "" 250 (const_int 4)) 251 252;; Attribute that controls whether an alternative is enabled or not. 253;; Currently it is only used to disable alternatives which touch fp or simd 254;; registers when -mgeneral-regs-only is specified. 255(define_attr "enabled" "no,yes" 256 (cond [(ior 257 (and (eq_attr "fp" "yes") 258 (eq (symbol_ref "TARGET_FLOAT") (const_int 0))) 259 (and (eq_attr "simd" "yes") 260 (eq (symbol_ref "TARGET_SIMD") (const_int 0))) 261 (and (eq_attr "fp16" "yes") 262 (eq (symbol_ref "TARGET_FP_F16INST") (const_int 0))) 263 (and (eq_attr "sve" "yes") 264 (eq (symbol_ref "TARGET_SVE") (const_int 0)))) 265 (const_string "no") 266 ] (const_string "yes"))) 267 268;; Attribute that specifies whether we are dealing with a branch to a 269;; label that is far away, i.e. further away than the maximum/minimum 270;; representable in a signed 21-bits number. 271;; 0 :=: no 272;; 1 :=: yes 273(define_attr "far_branch" "" (const_int 0)) 274 275;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has 276;; no predicated insns. 277(define_attr "predicated" "yes,no" (const_string "no")) 278 279;; ------------------------------------------------------------------- 280;; Pipeline descriptions and scheduling 281;; ------------------------------------------------------------------- 282 283;; Processor types. 284(include "aarch64-tune.md") 285 286;; Scheduling 287(include "../arm/cortex-a53.md") 288(include "../arm/cortex-a57.md") 289(include "../arm/exynos-m1.md") 290(include "falkor.md") 291(include "thunderx.md") 292(include "../arm/xgene1.md") 293(include "thunderx2t99.md") 294 295;; ------------------------------------------------------------------- 296;; Jumps and other miscellaneous insns 297;; ------------------------------------------------------------------- 298 299(define_insn "indirect_jump" 300 [(set (pc) (match_operand:DI 0 "register_operand" "r"))] 301 "" 302 "br\\t%0" 303 [(set_attr "type" "branch")] 304) 305 306(define_insn "jump" 307 [(set (pc) (label_ref (match_operand 0 "" "")))] 308 "" 309 "b\\t%l0" 310 [(set_attr "type" "branch")] 311) 312 313(define_expand "cbranch<mode>4" 314 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" 315 [(match_operand:GPI 1 "register_operand" "") 316 (match_operand:GPI 2 "aarch64_plus_operand" "")]) 317 (label_ref (match_operand 3 "" "")) 318 (pc)))] 319 "" 320 " 321 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1], 322 operands[2]); 323 operands[2] = const0_rtx; 324 " 325) 326 327(define_expand "cbranch<mode>4" 328 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" 329 [(match_operand:GPF 1 "register_operand" "") 330 (match_operand:GPF 2 "aarch64_fp_compare_operand" "")]) 331 (label_ref (match_operand 3 "" "")) 332 (pc)))] 333 "" 334 " 335 operands[1] = aarch64_gen_compare_reg (GET_CODE (operands[0]), operands[1], 336 operands[2]); 337 operands[2] = const0_rtx; 338 " 339) 340 341(define_expand "cbranchcc4" 342 [(set (pc) (if_then_else 343 (match_operator 0 "aarch64_comparison_operator" 344 [(match_operand 1 "cc_register" "") 345 (match_operand 2 "const0_operand")]) 346 (label_ref (match_operand 3 "" "")) 347 (pc)))] 348 "" 349 "") 350 351(define_insn "ccmp<mode>" 352 [(set (match_operand:CC 1 "cc_register" "") 353 (if_then_else:CC 354 (match_operator 4 "aarch64_comparison_operator" 355 [(match_operand 0 "cc_register" "") 356 (const_int 0)]) 357 (compare:CC 358 (match_operand:GPI 2 "register_operand" "r,r,r") 359 (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")) 360 (unspec:CC [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))] 361 "" 362 "@ 363 ccmp\\t%<w>2, %<w>3, %k5, %m4 364 ccmp\\t%<w>2, %3, %k5, %m4 365 ccmn\\t%<w>2, #%n3, %k5, %m4" 366 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] 367) 368 369(define_insn "fccmp<mode>" 370 [(set (match_operand:CCFP 1 "cc_register" "") 371 (if_then_else:CCFP 372 (match_operator 4 "aarch64_comparison_operator" 373 [(match_operand 0 "cc_register" "") 374 (const_int 0)]) 375 (compare:CCFP 376 (match_operand:GPF 2 "register_operand" "w") 377 (match_operand:GPF 3 "register_operand" "w")) 378 (unspec:CCFP [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))] 379 "TARGET_FLOAT" 380 "fccmp\\t%<s>2, %<s>3, %k5, %m4" 381 [(set_attr "type" "fccmp<s>")] 382) 383 384(define_insn "fccmpe<mode>" 385 [(set (match_operand:CCFPE 1 "cc_register" "") 386 (if_then_else:CCFPE 387 (match_operator 4 "aarch64_comparison_operator" 388 [(match_operand 0 "cc_register" "") 389 (const_int 0)]) 390 (compare:CCFPE 391 (match_operand:GPF 2 "register_operand" "w") 392 (match_operand:GPF 3 "register_operand" "w")) 393 (unspec:CCFPE [(match_operand 5 "immediate_operand")] UNSPEC_NZCV)))] 394 "TARGET_FLOAT" 395 "fccmpe\\t%<s>2, %<s>3, %k5, %m4" 396 [(set_attr "type" "fccmp<s>")] 397) 398 399;; Expansion of signed mod by a power of 2 using CSNEG. 400;; For x0 % n where n is a power of 2 produce: 401;; negs x1, x0 402;; and x0, x0, #(n - 1) 403;; and x1, x1, #(n - 1) 404;; csneg x0, x0, x1, mi 405 406(define_expand "mod<mode>3" 407 [(match_operand:GPI 0 "register_operand" "") 408 (match_operand:GPI 1 "register_operand" "") 409 (match_operand:GPI 2 "const_int_operand" "")] 410 "" 411 { 412 HOST_WIDE_INT val = INTVAL (operands[2]); 413 414 if (val <= 0 415 || exact_log2 (val) <= 0 416 || !aarch64_bitmask_imm (val - 1, <MODE>mode)) 417 FAIL; 418 419 rtx mask = GEN_INT (val - 1); 420 421 /* In the special case of x0 % 2 we can do the even shorter: 422 cmp x0, xzr 423 and x0, x0, 1 424 cneg x0, x0, lt. */ 425 if (val == 2) 426 { 427 rtx masked = gen_reg_rtx (<MODE>mode); 428 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx); 429 emit_insn (gen_and<mode>3 (masked, operands[1], mask)); 430 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx); 431 emit_insn (gen_csneg3<mode>_insn (operands[0], x, masked, masked)); 432 DONE; 433 } 434 435 rtx neg_op = gen_reg_rtx (<MODE>mode); 436 rtx_insn *insn = emit_insn (gen_neg<mode>2_compare0 (neg_op, operands[1])); 437 438 /* Extract the condition register and mode. */ 439 rtx cmp = XVECEXP (PATTERN (insn), 0, 0); 440 rtx cc_reg = SET_DEST (cmp); 441 rtx cond = gen_rtx_GE (VOIDmode, cc_reg, const0_rtx); 442 443 rtx masked_pos = gen_reg_rtx (<MODE>mode); 444 emit_insn (gen_and<mode>3 (masked_pos, operands[1], mask)); 445 446 rtx masked_neg = gen_reg_rtx (<MODE>mode); 447 emit_insn (gen_and<mode>3 (masked_neg, neg_op, mask)); 448 449 emit_insn (gen_csneg3<mode>_insn (operands[0], cond, 450 masked_neg, masked_pos)); 451 DONE; 452 } 453) 454 455(define_insn "condjump" 456 [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" 457 [(match_operand 1 "cc_register" "") (const_int 0)]) 458 (label_ref (match_operand 2 "" "")) 459 (pc)))] 460 "" 461 { 462 if (get_attr_length (insn) == 8) 463 return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t"); 464 else 465 return "b%m0\\t%l2"; 466 } 467 [(set_attr "type" "branch") 468 (set (attr "length") 469 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576)) 470 (lt (minus (match_dup 2) (pc)) (const_int 1048572))) 471 (const_int 4) 472 (const_int 8))) 473 (set (attr "far_branch") 474 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576)) 475 (lt (minus (match_dup 2) (pc)) (const_int 1048572))) 476 (const_int 0) 477 (const_int 1)))] 478) 479 480;; For a 24-bit immediate CST we can optimize the compare for equality 481;; and branch sequence from: 482;; mov x0, #imm1 483;; movk x0, #imm2, lsl 16 /* x0 contains CST. */ 484;; cmp x1, x0 485;; b<ne,eq> .Label 486;; into the shorter: 487;; sub x0, x1, #(CST & 0xfff000) 488;; subs x0, x0, #(CST & 0x000fff) 489;; b<ne,eq> .Label 490(define_insn_and_split "*compare_condjump<mode>" 491 [(set (pc) (if_then_else (EQL 492 (match_operand:GPI 0 "register_operand" "r") 493 (match_operand:GPI 1 "aarch64_imm24" "n")) 494 (label_ref:P (match_operand 2 "" "")) 495 (pc)))] 496 "!aarch64_move_imm (INTVAL (operands[1]), <MODE>mode) 497 && !aarch64_plus_operand (operands[1], <MODE>mode) 498 && !reload_completed" 499 "#" 500 "&& true" 501 [(const_int 0)] 502 { 503 HOST_WIDE_INT lo_imm = UINTVAL (operands[1]) & 0xfff; 504 HOST_WIDE_INT hi_imm = UINTVAL (operands[1]) & 0xfff000; 505 rtx tmp = gen_reg_rtx (<MODE>mode); 506 emit_insn (gen_add<mode>3 (tmp, operands[0], GEN_INT (-hi_imm))); 507 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm))); 508 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM); 509 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx); 510 emit_jump_insn (gen_condjump (cmp_rtx, cc_reg, operands[2])); 511 DONE; 512 } 513) 514 515(define_expand "casesi" 516 [(match_operand:SI 0 "register_operand" "") ; Index 517 (match_operand:SI 1 "const_int_operand" "") ; Lower bound 518 (match_operand:SI 2 "const_int_operand" "") ; Total range 519 (match_operand:DI 3 "" "") ; Table label 520 (match_operand:DI 4 "" "")] ; Out of range label 521 "" 522 { 523 if (operands[1] != const0_rtx) 524 { 525 rtx reg = gen_reg_rtx (SImode); 526 527 /* Canonical RTL says that if you have: 528 529 (minus (X) (CONST)) 530 531 then this should be emitted as: 532 533 (plus (X) (-CONST)) 534 535 The use of trunc_int_for_mode ensures that the resulting 536 constant can be represented in SImode, this is important 537 for the corner case where operand[1] is INT_MIN. */ 538 539 operands[1] = GEN_INT (trunc_int_for_mode (-INTVAL (operands[1]), SImode)); 540 541 if (!(*insn_data[CODE_FOR_addsi3].operand[2].predicate) 542 (operands[1], SImode)) 543 operands[1] = force_reg (SImode, operands[1]); 544 emit_insn (gen_addsi3 (reg, operands[0], operands[1])); 545 operands[0] = reg; 546 } 547 548 if (!aarch64_plus_operand (operands[2], SImode)) 549 operands[2] = force_reg (SImode, operands[2]); 550 emit_jump_insn (gen_cbranchsi4 (gen_rtx_GTU (SImode, const0_rtx, 551 const0_rtx), 552 operands[0], operands[2], operands[4])); 553 554 operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[3])); 555 emit_jump_insn (gen_casesi_dispatch (operands[2], operands[0], 556 operands[3])); 557 DONE; 558 } 559) 560 561(define_insn "casesi_dispatch" 562 [(parallel 563 [(set (pc) 564 (mem:DI (unspec [(match_operand:DI 0 "register_operand" "r") 565 (match_operand:SI 1 "register_operand" "r")] 566 UNSPEC_CASESI))) 567 (clobber (reg:CC CC_REGNUM)) 568 (clobber (match_scratch:DI 3 "=r")) 569 (clobber (match_scratch:DI 4 "=r")) 570 (use (label_ref (match_operand 2 "" "")))])] 571 "" 572 "* 573 return aarch64_output_casesi (operands); 574 " 575 [(set_attr "length" "16") 576 (set_attr "type" "branch")] 577) 578 579(define_insn "nop" 580 [(unspec[(const_int 0)] UNSPEC_NOP)] 581 "" 582 "nop" 583 [(set_attr "type" "no_insn")] 584) 585 586(define_insn "prefetch" 587 [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp") 588 (match_operand:QI 1 "const_int_operand" "") 589 (match_operand:QI 2 "const_int_operand" ""))] 590 "" 591 { 592 const char * pftype[2][4] = 593 { 594 {"prfm\\tPLDL1STRM, %0", 595 "prfm\\tPLDL3KEEP, %0", 596 "prfm\\tPLDL2KEEP, %0", 597 "prfm\\tPLDL1KEEP, %0"}, 598 {"prfm\\tPSTL1STRM, %0", 599 "prfm\\tPSTL3KEEP, %0", 600 "prfm\\tPSTL2KEEP, %0", 601 "prfm\\tPSTL1KEEP, %0"}, 602 }; 603 604 int locality = INTVAL (operands[2]); 605 606 gcc_assert (IN_RANGE (locality, 0, 3)); 607 608 /* PRFM accepts the same addresses as a 64-bit LDR so wrap 609 the address into a DImode MEM so that aarch64_print_operand knows 610 how to print it. */ 611 operands[0] = gen_rtx_MEM (DImode, operands[0]); 612 return pftype[INTVAL(operands[1])][locality]; 613 } 614 [(set_attr "type" "load_4")] 615) 616 617(define_insn "trap" 618 [(trap_if (const_int 1) (const_int 8))] 619 "" 620 "brk #1000" 621 [(set_attr "type" "trap")]) 622 623(define_expand "prologue" 624 [(clobber (const_int 0))] 625 "" 626 " 627 aarch64_expand_prologue (); 628 DONE; 629 " 630) 631 632(define_expand "epilogue" 633 [(clobber (const_int 0))] 634 "" 635 " 636 aarch64_expand_epilogue (false); 637 DONE; 638 " 639) 640 641(define_expand "sibcall_epilogue" 642 [(clobber (const_int 0))] 643 "" 644 " 645 aarch64_expand_epilogue (true); 646 DONE; 647 " 648) 649 650(define_insn "*do_return" 651 [(return)] 652 "" 653 { 654 if (aarch64_return_address_signing_enabled () 655 && TARGET_ARMV8_3 656 && !crtl->calls_eh_return) 657 return "retaa"; 658 659 return "ret"; 660 } 661 [(set_attr "type" "branch")] 662) 663 664(define_expand "return" 665 [(simple_return)] 666 "aarch64_use_return_insn_p ()" 667 "" 668) 669 670(define_insn "simple_return" 671 [(simple_return)] 672 "" 673 "ret" 674 [(set_attr "type" "branch")] 675) 676 677(define_insn "*cb<optab><mode>1" 678 [(set (pc) (if_then_else (EQL (match_operand:GPI 0 "register_operand" "r") 679 (const_int 0)) 680 (label_ref (match_operand 1 "" "")) 681 (pc)))] 682 "" 683 { 684 if (get_attr_length (insn) == 8) 685 return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, "); 686 else 687 return "<cbz>\\t%<w>0, %l1"; 688 } 689 [(set_attr "type" "branch") 690 (set (attr "length") 691 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576)) 692 (lt (minus (match_dup 1) (pc)) (const_int 1048572))) 693 (const_int 4) 694 (const_int 8))) 695 (set (attr "far_branch") 696 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576)) 697 (lt (minus (match_dup 2) (pc)) (const_int 1048572))) 698 (const_int 0) 699 (const_int 1)))] 700) 701 702(define_insn "*tb<optab><mode>1" 703 [(set (pc) (if_then_else 704 (EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r") 705 (const_int 1) 706 (match_operand 1 707 "aarch64_simd_shift_imm_<mode>" "n")) 708 (const_int 0)) 709 (label_ref (match_operand 2 "" "")) 710 (pc))) 711 (clobber (reg:CC CC_REGNUM))] 712 "" 713 { 714 if (get_attr_length (insn) == 8) 715 { 716 if (get_attr_far_branch (insn) == 1) 717 return aarch64_gen_far_branch (operands, 2, "Ltb", 718 "<inv_tb>\\t%<w>0, %1, "); 719 else 720 { 721 operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1])); 722 return "tst\t%<w>0, %1\;<bcond>\t%l2"; 723 } 724 } 725 else 726 return "<tbz>\t%<w>0, %1, %l2"; 727 } 728 [(set_attr "type" "branch") 729 (set (attr "length") 730 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) 731 (lt (minus (match_dup 2) (pc)) (const_int 32764))) 732 (const_int 4) 733 (const_int 8))) 734 (set (attr "far_branch") 735 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576)) 736 (lt (minus (match_dup 2) (pc)) (const_int 1048572))) 737 (const_int 0) 738 (const_int 1)))] 739 740) 741 742(define_insn "*cb<optab><mode>1" 743 [(set (pc) (if_then_else (LTGE (match_operand:ALLI 0 "register_operand" "r") 744 (const_int 0)) 745 (label_ref (match_operand 1 "" "")) 746 (pc))) 747 (clobber (reg:CC CC_REGNUM))] 748 "" 749 { 750 if (get_attr_length (insn) == 8) 751 { 752 if (get_attr_far_branch (insn) == 1) 753 return aarch64_gen_far_branch (operands, 1, "Ltb", 754 "<inv_tb>\\t%<w>0, <sizem1>, "); 755 else 756 { 757 char buf[64]; 758 uint64_t val = ((uint64_t) 1) 759 << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1); 760 sprintf (buf, "tst\t%%<w>0, %" PRId64, val); 761 output_asm_insn (buf, operands); 762 return "<bcond>\t%l1"; 763 } 764 } 765 else 766 return "<tbz>\t%<w>0, <sizem1>, %l1"; 767 } 768 [(set_attr "type" "branch") 769 (set (attr "length") 770 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768)) 771 (lt (minus (match_dup 1) (pc)) (const_int 32764))) 772 (const_int 4) 773 (const_int 8))) 774 (set (attr "far_branch") 775 (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576)) 776 (lt (minus (match_dup 1) (pc)) (const_int 1048572))) 777 (const_int 0) 778 (const_int 1)))] 779) 780 781;; ------------------------------------------------------------------- 782;; Subroutine calls and sibcalls 783;; ------------------------------------------------------------------- 784 785(define_expand "call" 786 [(parallel [(call (match_operand 0 "memory_operand" "") 787 (match_operand 1 "general_operand" "")) 788 (use (match_operand 2 "" "")) 789 (clobber (reg:DI LR_REGNUM))])] 790 "" 791 " 792 { 793 aarch64_expand_call (NULL_RTX, operands[0], false); 794 DONE; 795 }" 796) 797 798(define_insn "*call_insn" 799 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf")) 800 (match_operand 1 "" "")) 801 (clobber (reg:DI LR_REGNUM))] 802 "" 803 "@ 804 blr\\t%0 805 bl\\t%c0" 806 [(set_attr "type" "call, call")] 807) 808 809(define_expand "call_value" 810 [(parallel [(set (match_operand 0 "" "") 811 (call (match_operand 1 "memory_operand" "") 812 (match_operand 2 "general_operand" ""))) 813 (use (match_operand 3 "" "")) 814 (clobber (reg:DI LR_REGNUM))])] 815 "" 816 " 817 { 818 aarch64_expand_call (operands[0], operands[1], false); 819 DONE; 820 }" 821) 822 823(define_insn "*call_value_insn" 824 [(set (match_operand 0 "" "") 825 (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf")) 826 (match_operand 2 "" ""))) 827 (clobber (reg:DI LR_REGNUM))] 828 "" 829 "@ 830 blr\\t%1 831 bl\\t%c1" 832 [(set_attr "type" "call, call")] 833) 834 835(define_expand "sibcall" 836 [(parallel [(call (match_operand 0 "memory_operand" "") 837 (match_operand 1 "general_operand" "")) 838 (return) 839 (use (match_operand 2 "" ""))])] 840 "" 841 { 842 aarch64_expand_call (NULL_RTX, operands[0], true); 843 DONE; 844 } 845) 846 847(define_expand "sibcall_value" 848 [(parallel [(set (match_operand 0 "" "") 849 (call (match_operand 1 "memory_operand" "") 850 (match_operand 2 "general_operand" ""))) 851 (return) 852 (use (match_operand 3 "" ""))])] 853 "" 854 { 855 aarch64_expand_call (operands[0], operands[1], true); 856 DONE; 857 } 858) 859 860(define_insn "*sibcall_insn" 861 [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucs, Usf")) 862 (match_operand 1 "" "")) 863 (return)] 864 "SIBLING_CALL_P (insn)" 865 "@ 866 br\\t%0 867 b\\t%c0" 868 [(set_attr "type" "branch, branch")] 869) 870 871(define_insn "*sibcall_value_insn" 872 [(set (match_operand 0 "" "") 873 (call (mem:DI 874 (match_operand:DI 1 "aarch64_call_insn_operand" "Ucs, Usf")) 875 (match_operand 2 "" ""))) 876 (return)] 877 "SIBLING_CALL_P (insn)" 878 "@ 879 br\\t%1 880 b\\t%c1" 881 [(set_attr "type" "branch, branch")] 882) 883 884;; Call subroutine returning any type. 885 886(define_expand "untyped_call" 887 [(parallel [(call (match_operand 0 "") 888 (const_int 0)) 889 (match_operand 1 "") 890 (match_operand 2 "")])] 891 "" 892{ 893 int i; 894 895 emit_call_insn (gen_call (operands[0], const0_rtx, NULL)); 896 897 for (i = 0; i < XVECLEN (operands[2], 0); i++) 898 { 899 rtx set = XVECEXP (operands[2], 0, i); 900 emit_move_insn (SET_DEST (set), SET_SRC (set)); 901 } 902 903 /* The optimizer does not know that the call sets the function value 904 registers we stored in the result block. We avoid problems by 905 claiming that all hard registers are used and clobbered at this 906 point. */ 907 emit_insn (gen_blockage ()); 908 DONE; 909}) 910 911;; ------------------------------------------------------------------- 912;; Moves 913;; ------------------------------------------------------------------- 914 915(define_expand "mov<mode>" 916 [(set (match_operand:SHORT 0 "nonimmediate_operand" "") 917 (match_operand:SHORT 1 "general_operand" ""))] 918 "" 919 " 920 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx) 921 operands[1] = force_reg (<MODE>mode, operands[1]); 922 923 if (GET_CODE (operands[1]) == CONST_POLY_INT) 924 { 925 aarch64_expand_mov_immediate (operands[0], operands[1]); 926 DONE; 927 } 928 " 929) 930 931(define_insn "*mov<mode>_aarch64" 932 [(set (match_operand:SHORT 0 "nonimmediate_operand" "=r,r, *w,r ,r,*w, m, m, r,*w,*w") 933 (match_operand:SHORT 1 "aarch64_mov_operand" " r,M,D<hq>,Usv,m, m,rZ,*w,*w, r,*w"))] 934 "(register_operand (operands[0], <MODE>mode) 935 || aarch64_reg_or_zero (operands[1], <MODE>mode))" 936{ 937 switch (which_alternative) 938 { 939 case 0: 940 return "mov\t%w0, %w1"; 941 case 1: 942 return "mov\t%w0, %1"; 943 case 2: 944 return aarch64_output_scalar_simd_mov_immediate (operands[1], 945 <MODE>mode); 946 case 3: 947 return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]); 948 case 4: 949 return "ldr<size>\t%w0, %1"; 950 case 5: 951 return "ldr\t%<size>0, %1"; 952 case 6: 953 return "str<size>\t%w1, %0"; 954 case 7: 955 return "str\t%<size>1, %0"; 956 case 8: 957 return "umov\t%w0, %1.<v>[0]"; 958 case 9: 959 return "dup\t%0.<Vallxd>, %w1"; 960 case 10: 961 return "dup\t%<Vetype>0, %1.<v>[0]"; 962 default: 963 gcc_unreachable (); 964 } 965} 966 ;; The "mov_imm" type for CNT is just a placeholder. 967 [(set_attr "type" "mov_reg,mov_imm,neon_move,mov_imm,load_4,load_4,store_4, 968 store_4,neon_to_gp<q>,neon_from_gp<q>,neon_dup") 969 (set_attr "simd" "*,*,yes,*,*,*,*,*,yes,yes,yes") 970 (set_attr "sve" "*,*,*,yes,*,*,*,*,*,*,*")] 971) 972 973(define_expand "mov<mode>" 974 [(set (match_operand:GPI 0 "nonimmediate_operand" "") 975 (match_operand:GPI 1 "general_operand" ""))] 976 "" 977 " 978 if (MEM_P (operands[0]) && !MEM_VOLATILE_P (operands[0]) 979 && CONST_INT_P (operands[1]) && <MODE>mode == DImode 980 && aarch64_split_dimode_const_store (operands[0], operands[1])) 981 DONE; 982 983 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx) 984 operands[1] = force_reg (<MODE>mode, operands[1]); 985 986 /* FIXME: RR we still need to fix up what we are doing with 987 symbol_refs and other types of constants. */ 988 if (CONSTANT_P (operands[1]) 989 && !CONST_INT_P (operands[1])) 990 { 991 aarch64_expand_mov_immediate (operands[0], operands[1]); 992 DONE; 993 } 994 " 995) 996 997(define_insn_and_split "*movsi_aarch64" 998 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,k,r,r,r,r, r,w, m, m, r, r, w,r,w, w") 999 (match_operand:SI 1 "aarch64_mov_operand" " r,r,k,M,n,Usv,m,m,rZ,*w,Usa,Ush,rZ,w,w,Ds"))] 1000 "(register_operand (operands[0], SImode) 1001 || aarch64_reg_or_zero (operands[1], SImode))" 1002 "@ 1003 mov\\t%w0, %w1 1004 mov\\t%w0, %w1 1005 mov\\t%w0, %w1 1006 mov\\t%w0, %1 1007 # 1008 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]); 1009 ldr\\t%w0, %1 1010 ldr\\t%s0, %1 1011 str\\t%w1, %0 1012 str\\t%s1, %0 1013 adr\\t%x0, %c1 1014 adrp\\t%x0, %A1 1015 fmov\\t%s0, %w1 1016 fmov\\t%w0, %s1 1017 fmov\\t%s0, %s1 1018 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode);" 1019 "CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), SImode) 1020 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))" 1021 [(const_int 0)] 1022 "{ 1023 aarch64_expand_mov_immediate (operands[0], operands[1]); 1024 DONE; 1025 }" 1026 ;; The "mov_imm" type for CNT is just a placeholder. 1027 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,load_4, 1028 load_4,store_4,store_4,adr,adr,f_mcr,f_mrc,fmov,neon_move") 1029 (set_attr "fp" "*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*") 1030 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes") 1031 (set_attr "sve" "*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")] 1032) 1033 1034(define_insn_and_split "*movdi_aarch64" 1035 [(set (match_operand:DI 0 "nonimmediate_operand" "=r,k,r,r,r,r,r, r,w, m,m, r, r, w,r,w, w") 1036 (match_operand:DI 1 "aarch64_mov_operand" " r,r,k,N,M,n,Usv,m,m,rZ,w,Usa,Ush,rZ,w,w,Dd"))] 1037 "(register_operand (operands[0], DImode) 1038 || aarch64_reg_or_zero (operands[1], DImode))" 1039 "@ 1040 mov\\t%x0, %x1 1041 mov\\t%0, %x1 1042 mov\\t%x0, %1 1043 mov\\t%x0, %1 1044 mov\\t%w0, %1 1045 # 1046 * return aarch64_output_sve_cnt_immediate (\"cnt\", \"%x0\", operands[1]); 1047 ldr\\t%x0, %1 1048 ldr\\t%d0, %1 1049 str\\t%x1, %0 1050 str\\t%d1, %0 1051 adr\\t%x0, %c1 1052 adrp\\t%x0, %A1 1053 fmov\\t%d0, %x1 1054 fmov\\t%x0, %d1 1055 fmov\\t%d0, %d1 1056 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode);" 1057 "(CONST_INT_P (operands[1]) && !aarch64_move_imm (INTVAL (operands[1]), DImode)) 1058 && REG_P (operands[0]) && GP_REGNUM_P (REGNO (operands[0]))" 1059 [(const_int 0)] 1060 "{ 1061 aarch64_expand_mov_immediate (operands[0], operands[1]); 1062 DONE; 1063 }" 1064 ;; The "mov_imm" type for CNTD is just a placeholder. 1065 [(set_attr "type" "mov_reg,mov_reg,mov_reg,mov_imm,mov_imm,mov_imm,mov_imm, 1066 load_8,load_8,store_8,store_8,adr,adr,f_mcr,f_mrc,fmov, 1067 neon_move") 1068 (set_attr "fp" "*,*,*,*,*,*,*,*,yes,*,yes,*,*,yes,yes,yes,*") 1069 (set_attr "simd" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,yes") 1070 (set_attr "sve" "*,*,*,*,*,*,yes,*,*,*,*,*,*,*,*,*,*")] 1071) 1072 1073(define_insn "insv_imm<mode>" 1074 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r") 1075 (const_int 16) 1076 (match_operand:GPI 1 "const_int_operand" "n")) 1077 (match_operand:GPI 2 "const_int_operand" "n"))] 1078 "UINTVAL (operands[1]) < GET_MODE_BITSIZE (<MODE>mode) 1079 && UINTVAL (operands[1]) % 16 == 0" 1080 "movk\\t%<w>0, %X2, lsl %1" 1081 [(set_attr "type" "mov_imm")] 1082) 1083 1084(define_expand "movti" 1085 [(set (match_operand:TI 0 "nonimmediate_operand" "") 1086 (match_operand:TI 1 "general_operand" ""))] 1087 "" 1088 " 1089 if (GET_CODE (operands[0]) == MEM && operands[1] != const0_rtx) 1090 operands[1] = force_reg (TImode, operands[1]); 1091 1092 if (GET_CODE (operands[1]) == CONST_POLY_INT) 1093 { 1094 emit_move_insn (gen_lowpart (DImode, operands[0]), 1095 gen_lowpart (DImode, operands[1])); 1096 emit_move_insn (gen_highpart (DImode, operands[0]), const0_rtx); 1097 DONE; 1098 } 1099 " 1100) 1101 1102(define_insn "*movti_aarch64" 1103 [(set (match_operand:TI 0 1104 "nonimmediate_operand" "= r,w, r,w,r,m,m,w,m") 1105 (match_operand:TI 1 1106 "aarch64_movti_operand" " rUti,r, w,w,m,r,Z,m,w"))] 1107 "(register_operand (operands[0], TImode) 1108 || aarch64_reg_or_zero (operands[1], TImode))" 1109 "@ 1110 # 1111 # 1112 # 1113 mov\\t%0.16b, %1.16b 1114 ldp\\t%0, %H0, %1 1115 stp\\t%1, %H1, %0 1116 stp\\txzr, xzr, %0 1117 ldr\\t%q0, %1 1118 str\\t%q1, %0" 1119 [(set_attr "type" "multiple,f_mcr,f_mrc,neon_logic_q, \ 1120 load_16,store_16,store_16,\ 1121 load_16,store_16") 1122 (set_attr "length" "8,8,8,4,4,4,4,4,4") 1123 (set_attr "simd" "*,*,*,yes,*,*,*,*,*") 1124 (set_attr "fp" "*,*,*,*,*,*,*,yes,yes")] 1125) 1126 1127;; Split a TImode register-register or register-immediate move into 1128;; its component DImode pieces, taking care to handle overlapping 1129;; source and dest registers. 1130(define_split 1131 [(set (match_operand:TI 0 "register_operand" "") 1132 (match_operand:TI 1 "aarch64_reg_or_imm" ""))] 1133 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])" 1134 [(const_int 0)] 1135{ 1136 aarch64_split_128bit_move (operands[0], operands[1]); 1137 DONE; 1138}) 1139 1140(define_expand "mov<mode>" 1141 [(set (match_operand:GPF_TF_F16 0 "nonimmediate_operand" "") 1142 (match_operand:GPF_TF_F16 1 "general_operand" ""))] 1143 "" 1144 { 1145 if (!TARGET_FLOAT) 1146 { 1147 aarch64_err_no_fpadvsimd (<MODE>mode, "code"); 1148 FAIL; 1149 } 1150 1151 if (GET_CODE (operands[0]) == MEM 1152 && ! (GET_CODE (operands[1]) == CONST_DOUBLE 1153 && aarch64_float_const_zero_rtx_p (operands[1]))) 1154 operands[1] = force_reg (<MODE>mode, operands[1]); 1155 } 1156) 1157 1158(define_insn "*movhf_aarch64" 1159 [(set (match_operand:HF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r") 1160 (match_operand:HF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r"))] 1161 "TARGET_FLOAT && (register_operand (operands[0], HFmode) 1162 || aarch64_reg_or_fp_zero (operands[1], HFmode))" 1163 "@ 1164 movi\\t%0.4h, #0 1165 fmov\\t%h0, %w1 1166 umov\\t%w0, %1.h[0] 1167 mov\\t%0.h[0], %1.h[0] 1168 fmov\\t%h0, %1 1169 * return aarch64_output_scalar_simd_mov_immediate (operands[1], HImode); 1170 ldr\\t%h0, %1 1171 str\\t%h1, %0 1172 ldrh\\t%w0, %1 1173 strh\\t%w1, %0 1174 mov\\t%w0, %w1" 1175 [(set_attr "type" "neon_move,f_mcr,neon_to_gp,neon_move,fconsts, \ 1176 neon_move,f_loads,f_stores,load_4,store_4,mov_reg") 1177 (set_attr "simd" "yes,*,yes,yes,*,yes,*,*,*,*,*") 1178 (set_attr "fp16" "*,yes,*,*,yes,*,*,*,*,*,*")] 1179) 1180 1181(define_insn "*movsf_aarch64" 1182 [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w ,?r,w,w ,w ,w,m,r,m ,r,r") 1183 (match_operand:SF 1 "general_operand" "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))] 1184 "TARGET_FLOAT && (register_operand (operands[0], SFmode) 1185 || aarch64_reg_or_fp_zero (operands[1], SFmode))" 1186 "@ 1187 movi\\t%0.2s, #0 1188 fmov\\t%s0, %w1 1189 fmov\\t%w0, %s1 1190 fmov\\t%s0, %s1 1191 fmov\\t%s0, %1 1192 * return aarch64_output_scalar_simd_mov_immediate (operands[1], SImode); 1193 ldr\\t%s0, %1 1194 str\\t%s1, %0 1195 ldr\\t%w0, %1 1196 str\\t%w1, %0 1197 mov\\t%w0, %w1 1198 mov\\t%w0, %1" 1199 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconsts,neon_move,\ 1200 f_loads,f_stores,load_4,store_4,mov_reg,\ 1201 fconsts") 1202 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")] 1203) 1204 1205(define_insn "*movdf_aarch64" 1206 [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w ,?r,w,w ,w ,w,m,r,m ,r,r") 1207 (match_operand:DF 1 "general_operand" "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))] 1208 "TARGET_FLOAT && (register_operand (operands[0], DFmode) 1209 || aarch64_reg_or_fp_zero (operands[1], DFmode))" 1210 "@ 1211 movi\\t%d0, #0 1212 fmov\\t%d0, %x1 1213 fmov\\t%x0, %d1 1214 fmov\\t%d0, %d1 1215 fmov\\t%d0, %1 1216 * return aarch64_output_scalar_simd_mov_immediate (operands[1], DImode); 1217 ldr\\t%d0, %1 1218 str\\t%d1, %0 1219 ldr\\t%x0, %1 1220 str\\t%x1, %0 1221 mov\\t%x0, %x1 1222 mov\\t%x0, %1" 1223 [(set_attr "type" "neon_move,f_mcr,f_mrc,fmov,fconstd,neon_move,\ 1224 f_loadd,f_stored,load_8,store_8,mov_reg,\ 1225 fconstd") 1226 (set_attr "simd" "yes,*,*,*,*,yes,*,*,*,*,*,*")] 1227) 1228 1229(define_split 1230 [(set (match_operand:GPF_HF 0 "nonimmediate_operand") 1231 (match_operand:GPF_HF 1 "general_operand"))] 1232 "can_create_pseudo_p () 1233 && !aarch64_can_const_movi_rtx_p (operands[1], <MODE>mode) 1234 && !aarch64_float_const_representable_p (operands[1]) 1235 && aarch64_float_const_rtx_p (operands[1])" 1236 [(const_int 0)] 1237 { 1238 unsigned HOST_WIDE_INT ival; 1239 if (!aarch64_reinterpret_float_as_int (operands[1], &ival)) 1240 FAIL; 1241 1242 rtx tmp = gen_reg_rtx (<FCVT_TARGET>mode); 1243 emit_move_insn (tmp, gen_int_mode (ival, <FCVT_TARGET>mode)); 1244 emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp)); 1245 DONE; 1246 } 1247) 1248 1249(define_insn "*movtf_aarch64" 1250 [(set (match_operand:TF 0 1251 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r,m ,m") 1252 (match_operand:TF 1 1253 "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,m ,?r,Y"))] 1254 "TARGET_FLOAT && (register_operand (operands[0], TFmode) 1255 || aarch64_reg_or_fp_zero (operands[1], TFmode))" 1256 "@ 1257 mov\\t%0.16b, %1.16b 1258 # 1259 # 1260 # 1261 movi\\t%0.2d, #0 1262 fmov\\t%s0, wzr 1263 ldr\\t%q0, %1 1264 str\\t%q1, %0 1265 ldp\\t%0, %H0, %1 1266 stp\\t%1, %H1, %0 1267 stp\\txzr, xzr, %0" 1268 [(set_attr "type" "logic_reg,multiple,f_mcr,f_mrc,neon_move_q,f_mcr,\ 1269 f_loadd,f_stored,load_16,store_16,store_16") 1270 (set_attr "length" "4,8,8,8,4,4,4,4,4,4,4") 1271 (set_attr "simd" "yes,*,*,*,yes,*,*,*,*,*,*")] 1272) 1273 1274(define_split 1275 [(set (match_operand:TF 0 "register_operand" "") 1276 (match_operand:TF 1 "aarch64_reg_or_imm" ""))] 1277 "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])" 1278 [(const_int 0)] 1279 { 1280 aarch64_split_128bit_move (operands[0], operands[1]); 1281 DONE; 1282 } 1283) 1284 1285;; 0 is dst 1286;; 1 is src 1287;; 2 is size of move in bytes 1288;; 3 is alignment 1289 1290(define_expand "movmemdi" 1291 [(match_operand:BLK 0 "memory_operand") 1292 (match_operand:BLK 1 "memory_operand") 1293 (match_operand:DI 2 "immediate_operand") 1294 (match_operand:DI 3 "immediate_operand")] 1295 "!STRICT_ALIGNMENT" 1296{ 1297 if (aarch64_expand_movmem (operands)) 1298 DONE; 1299 FAIL; 1300} 1301) 1302 1303;; Operands 1 and 3 are tied together by the final condition; so we allow 1304;; fairly lax checking on the second memory operation. 1305(define_insn "load_pairsi" 1306 [(set (match_operand:SI 0 "register_operand" "=r,*w") 1307 (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump,Ump")) 1308 (set (match_operand:SI 2 "register_operand" "=r,*w") 1309 (match_operand:SI 3 "memory_operand" "m,m"))] 1310 "rtx_equal_p (XEXP (operands[3], 0), 1311 plus_constant (Pmode, 1312 XEXP (operands[1], 0), 1313 GET_MODE_SIZE (SImode)))" 1314 "@ 1315 ldp\\t%w0, %w2, %1 1316 ldp\\t%s0, %s2, %1" 1317 [(set_attr "type" "load_8,neon_load1_2reg") 1318 (set_attr "fp" "*,yes")] 1319) 1320 1321(define_insn "load_pairdi" 1322 [(set (match_operand:DI 0 "register_operand" "=r,*w") 1323 (match_operand:DI 1 "aarch64_mem_pair_operand" "Ump,Ump")) 1324 (set (match_operand:DI 2 "register_operand" "=r,*w") 1325 (match_operand:DI 3 "memory_operand" "m,m"))] 1326 "rtx_equal_p (XEXP (operands[3], 0), 1327 plus_constant (Pmode, 1328 XEXP (operands[1], 0), 1329 GET_MODE_SIZE (DImode)))" 1330 "@ 1331 ldp\\t%x0, %x2, %1 1332 ldp\\t%d0, %d2, %1" 1333 [(set_attr "type" "load_16,neon_load1_2reg") 1334 (set_attr "fp" "*,yes")] 1335) 1336 1337 1338;; Operands 0 and 2 are tied together by the final condition; so we allow 1339;; fairly lax checking on the second memory operation. 1340(define_insn "store_pairsi" 1341 [(set (match_operand:SI 0 "aarch64_mem_pair_operand" "=Ump,Ump") 1342 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ,*w")) 1343 (set (match_operand:SI 2 "memory_operand" "=m,m") 1344 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ,*w"))] 1345 "rtx_equal_p (XEXP (operands[2], 0), 1346 plus_constant (Pmode, 1347 XEXP (operands[0], 0), 1348 GET_MODE_SIZE (SImode)))" 1349 "@ 1350 stp\\t%w1, %w3, %0 1351 stp\\t%s1, %s3, %0" 1352 [(set_attr "type" "store_8,neon_store1_2reg") 1353 (set_attr "fp" "*,yes")] 1354) 1355 1356(define_insn "store_pairdi" 1357 [(set (match_operand:DI 0 "aarch64_mem_pair_operand" "=Ump,Ump") 1358 (match_operand:DI 1 "aarch64_reg_or_zero" "rZ,*w")) 1359 (set (match_operand:DI 2 "memory_operand" "=m,m") 1360 (match_operand:DI 3 "aarch64_reg_or_zero" "rZ,*w"))] 1361 "rtx_equal_p (XEXP (operands[2], 0), 1362 plus_constant (Pmode, 1363 XEXP (operands[0], 0), 1364 GET_MODE_SIZE (DImode)))" 1365 "@ 1366 stp\\t%x1, %x3, %0 1367 stp\\t%d1, %d3, %0" 1368 [(set_attr "type" "store_16,neon_store1_2reg") 1369 (set_attr "fp" "*,yes")] 1370) 1371 1372;; Operands 1 and 3 are tied together by the final condition; so we allow 1373;; fairly lax checking on the second memory operation. 1374(define_insn "load_pairsf" 1375 [(set (match_operand:SF 0 "register_operand" "=w,*r") 1376 (match_operand:SF 1 "aarch64_mem_pair_operand" "Ump,Ump")) 1377 (set (match_operand:SF 2 "register_operand" "=w,*r") 1378 (match_operand:SF 3 "memory_operand" "m,m"))] 1379 "rtx_equal_p (XEXP (operands[3], 0), 1380 plus_constant (Pmode, 1381 XEXP (operands[1], 0), 1382 GET_MODE_SIZE (SFmode)))" 1383 "@ 1384 ldp\\t%s0, %s2, %1 1385 ldp\\t%w0, %w2, %1" 1386 [(set_attr "type" "neon_load1_2reg,load_8") 1387 (set_attr "fp" "yes,*")] 1388) 1389 1390(define_insn "load_pairdf" 1391 [(set (match_operand:DF 0 "register_operand" "=w,*r") 1392 (match_operand:DF 1 "aarch64_mem_pair_operand" "Ump,Ump")) 1393 (set (match_operand:DF 2 "register_operand" "=w,*r") 1394 (match_operand:DF 3 "memory_operand" "m,m"))] 1395 "rtx_equal_p (XEXP (operands[3], 0), 1396 plus_constant (Pmode, 1397 XEXP (operands[1], 0), 1398 GET_MODE_SIZE (DFmode)))" 1399 "@ 1400 ldp\\t%d0, %d2, %1 1401 ldp\\t%x0, %x2, %1" 1402 [(set_attr "type" "neon_load1_2reg,load_16") 1403 (set_attr "fp" "yes,*")] 1404) 1405 1406;; Operands 0 and 2 are tied together by the final condition; so we allow 1407;; fairly lax checking on the second memory operation. 1408(define_insn "store_pairsf" 1409 [(set (match_operand:SF 0 "aarch64_mem_pair_operand" "=Ump,Ump") 1410 (match_operand:SF 1 "aarch64_reg_or_fp_zero" "w,*rY")) 1411 (set (match_operand:SF 2 "memory_operand" "=m,m") 1412 (match_operand:SF 3 "aarch64_reg_or_fp_zero" "w,*rY"))] 1413 "rtx_equal_p (XEXP (operands[2], 0), 1414 plus_constant (Pmode, 1415 XEXP (operands[0], 0), 1416 GET_MODE_SIZE (SFmode)))" 1417 "@ 1418 stp\\t%s1, %s3, %0 1419 stp\\t%w1, %w3, %0" 1420 [(set_attr "type" "neon_store1_2reg,store_8") 1421 (set_attr "fp" "yes,*")] 1422) 1423 1424(define_insn "store_pairdf" 1425 [(set (match_operand:DF 0 "aarch64_mem_pair_operand" "=Ump,Ump") 1426 (match_operand:DF 1 "aarch64_reg_or_fp_zero" "w,*rY")) 1427 (set (match_operand:DF 2 "memory_operand" "=m,m") 1428 (match_operand:DF 3 "aarch64_reg_or_fp_zero" "w,*rY"))] 1429 "rtx_equal_p (XEXP (operands[2], 0), 1430 plus_constant (Pmode, 1431 XEXP (operands[0], 0), 1432 GET_MODE_SIZE (DFmode)))" 1433 "@ 1434 stp\\t%d1, %d3, %0 1435 stp\\t%x1, %x3, %0" 1436 [(set_attr "type" "neon_store1_2reg,store_16") 1437 (set_attr "fp" "yes,*")] 1438) 1439 1440;; Load pair with post-index writeback. This is primarily used in function 1441;; epilogues. 1442(define_insn "loadwb_pair<GPI:mode>_<P:mode>" 1443 [(parallel 1444 [(set (match_operand:P 0 "register_operand" "=k") 1445 (plus:P (match_operand:P 1 "register_operand" "0") 1446 (match_operand:P 4 "aarch64_mem_pair_offset" "n"))) 1447 (set (match_operand:GPI 2 "register_operand" "=r") 1448 (mem:GPI (match_dup 1))) 1449 (set (match_operand:GPI 3 "register_operand" "=r") 1450 (mem:GPI (plus:P (match_dup 1) 1451 (match_operand:P 5 "const_int_operand" "n"))))])] 1452 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPI:MODE>mode)" 1453 "ldp\\t%<w>2, %<w>3, [%1], %4" 1454 [(set_attr "type" "load_<ldpstp_sz>")] 1455) 1456 1457(define_insn "loadwb_pair<GPF:mode>_<P:mode>" 1458 [(parallel 1459 [(set (match_operand:P 0 "register_operand" "=k") 1460 (plus:P (match_operand:P 1 "register_operand" "0") 1461 (match_operand:P 4 "aarch64_mem_pair_offset" "n"))) 1462 (set (match_operand:GPF 2 "register_operand" "=w") 1463 (mem:GPF (match_dup 1))) 1464 (set (match_operand:GPF 3 "register_operand" "=w") 1465 (mem:GPF (plus:P (match_dup 1) 1466 (match_operand:P 5 "const_int_operand" "n"))))])] 1467 "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)" 1468 "ldp\\t%<w>2, %<w>3, [%1], %4" 1469 [(set_attr "type" "neon_load1_2reg")] 1470) 1471 1472;; Store pair with pre-index writeback. This is primarily used in function 1473;; prologues. 1474(define_insn "storewb_pair<GPI:mode>_<P:mode>" 1475 [(parallel 1476 [(set (match_operand:P 0 "register_operand" "=&k") 1477 (plus:P (match_operand:P 1 "register_operand" "0") 1478 (match_operand:P 4 "aarch64_mem_pair_offset" "n"))) 1479 (set (mem:GPI (plus:P (match_dup 0) 1480 (match_dup 4))) 1481 (match_operand:GPI 2 "register_operand" "r")) 1482 (set (mem:GPI (plus:P (match_dup 0) 1483 (match_operand:P 5 "const_int_operand" "n"))) 1484 (match_operand:GPI 3 "register_operand" "r"))])] 1485 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPI:MODE>mode)" 1486 "stp\\t%<w>2, %<w>3, [%0, %4]!" 1487 [(set_attr "type" "store_<ldpstp_sz>")] 1488) 1489 1490(define_insn "storewb_pair<GPF:mode>_<P:mode>" 1491 [(parallel 1492 [(set (match_operand:P 0 "register_operand" "=&k") 1493 (plus:P (match_operand:P 1 "register_operand" "0") 1494 (match_operand:P 4 "aarch64_mem_pair_offset" "n"))) 1495 (set (mem:GPF (plus:P (match_dup 0) 1496 (match_dup 4))) 1497 (match_operand:GPF 2 "register_operand" "w")) 1498 (set (mem:GPF (plus:P (match_dup 0) 1499 (match_operand:P 5 "const_int_operand" "n"))) 1500 (match_operand:GPF 3 "register_operand" "w"))])] 1501 "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)" 1502 "stp\\t%<w>2, %<w>3, [%0, %4]!" 1503 [(set_attr "type" "neon_store1_2reg<q>")] 1504) 1505 1506;; ------------------------------------------------------------------- 1507;; Sign/Zero extension 1508;; ------------------------------------------------------------------- 1509 1510(define_expand "<optab>sidi2" 1511 [(set (match_operand:DI 0 "register_operand") 1512 (ANY_EXTEND:DI (match_operand:SI 1 "nonimmediate_operand")))] 1513 "" 1514) 1515 1516(define_insn "*extendsidi2_aarch64" 1517 [(set (match_operand:DI 0 "register_operand" "=r,r") 1518 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))] 1519 "" 1520 "@ 1521 sxtw\t%0, %w1 1522 ldrsw\t%0, %1" 1523 [(set_attr "type" "extend,load_4")] 1524) 1525 1526(define_insn "*load_pair_extendsidi2_aarch64" 1527 [(set (match_operand:DI 0 "register_operand" "=r") 1528 (sign_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump"))) 1529 (set (match_operand:DI 2 "register_operand" "=r") 1530 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))] 1531 "rtx_equal_p (XEXP (operands[3], 0), 1532 plus_constant (Pmode, 1533 XEXP (operands[1], 0), 1534 GET_MODE_SIZE (SImode)))" 1535 "ldpsw\\t%0, %2, %1" 1536 [(set_attr "type" "load_8")] 1537) 1538 1539(define_insn "*zero_extendsidi2_aarch64" 1540 [(set (match_operand:DI 0 "register_operand" "=r,r") 1541 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))] 1542 "" 1543 "@ 1544 uxtw\t%0, %w1 1545 ldr\t%w0, %1" 1546 [(set_attr "type" "extend,load_4")] 1547) 1548 1549(define_insn "*load_pair_zero_extendsidi2_aarch64" 1550 [(set (match_operand:DI 0 "register_operand" "=r") 1551 (zero_extend:DI (match_operand:SI 1 "aarch64_mem_pair_operand" "Ump"))) 1552 (set (match_operand:DI 2 "register_operand" "=r") 1553 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))] 1554 "rtx_equal_p (XEXP (operands[3], 0), 1555 plus_constant (Pmode, 1556 XEXP (operands[1], 0), 1557 GET_MODE_SIZE (SImode)))" 1558 "ldp\\t%w0, %w2, %1" 1559 [(set_attr "type" "load_8")] 1560) 1561 1562(define_expand "<ANY_EXTEND:optab><SHORT:mode><GPI:mode>2" 1563 [(set (match_operand:GPI 0 "register_operand") 1564 (ANY_EXTEND:GPI (match_operand:SHORT 1 "nonimmediate_operand")))] 1565 "" 1566) 1567 1568(define_insn "*extend<SHORT:mode><GPI:mode>2_aarch64" 1569 [(set (match_operand:GPI 0 "register_operand" "=r,r") 1570 (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m")))] 1571 "" 1572 "@ 1573 sxt<SHORT:size>\t%<GPI:w>0, %w1 1574 ldrs<SHORT:size>\t%<GPI:w>0, %1" 1575 [(set_attr "type" "extend,load_4")] 1576) 1577 1578(define_insn "*zero_extend<SHORT:mode><GPI:mode>2_aarch64" 1579 [(set (match_operand:GPI 0 "register_operand" "=r,r,*w") 1580 (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand" "r,m,m")))] 1581 "" 1582 "@ 1583 and\t%<GPI:w>0, %<GPI:w>1, <SHORT:short_mask> 1584 ldr<SHORT:size>\t%w0, %1 1585 ldr\t%<SHORT:size>0, %1" 1586 [(set_attr "type" "logic_imm,load_4,load_4")] 1587) 1588 1589(define_expand "<optab>qihi2" 1590 [(set (match_operand:HI 0 "register_operand") 1591 (ANY_EXTEND:HI (match_operand:QI 1 "nonimmediate_operand")))] 1592 "" 1593) 1594 1595(define_insn "*extendqihi2_aarch64" 1596 [(set (match_operand:HI 0 "register_operand" "=r,r") 1597 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 1598 "" 1599 "@ 1600 sxtb\t%w0, %w1 1601 ldrsb\t%w0, %1" 1602 [(set_attr "type" "extend,load_4")] 1603) 1604 1605(define_insn "*zero_extendqihi2_aarch64" 1606 [(set (match_operand:HI 0 "register_operand" "=r,r") 1607 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 1608 "" 1609 "@ 1610 and\t%w0, %w1, 255 1611 ldrb\t%w0, %1" 1612 [(set_attr "type" "logic_imm,load_4")] 1613) 1614 1615;; ------------------------------------------------------------------- 1616;; Simple arithmetic 1617;; ------------------------------------------------------------------- 1618 1619(define_expand "add<mode>3" 1620 [(set 1621 (match_operand:GPI 0 "register_operand" "") 1622 (plus:GPI (match_operand:GPI 1 "register_operand" "") 1623 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "")))] 1624 "" 1625{ 1626 /* If operands[1] is a subreg extract the inner RTX. */ 1627 rtx op1 = REG_P (operands[1]) ? operands[1] : SUBREG_REG (operands[1]); 1628 1629 /* If the constant is too large for a single instruction and isn't frame 1630 based, split off the immediate so it is available for CSE. */ 1631 if (!aarch64_plus_immediate (operands[2], <MODE>mode) 1632 && can_create_pseudo_p () 1633 && (!REG_P (op1) 1634 || !REGNO_PTR_FRAME_P (REGNO (op1)))) 1635 operands[2] = force_reg (<MODE>mode, operands[2]); 1636 /* Expand polynomial additions now if the destination is the stack 1637 pointer, since we don't want to use that as a temporary. */ 1638 else if (operands[0] == stack_pointer_rtx 1639 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)) 1640 { 1641 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1], 1642 operands[2], NULL_RTX, NULL_RTX); 1643 DONE; 1644 } 1645}) 1646 1647(define_insn "*add<mode>3_aarch64" 1648 [(set 1649 (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,rk") 1650 (plus:GPI 1651 (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,rk") 1652 (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uav")))] 1653 "" 1654 "@ 1655 add\\t%<w>0, %<w>1, %2 1656 add\\t%<w>0, %<w>1, %<w>2 1657 add\\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas> 1658 sub\\t%<w>0, %<w>1, #%n2 1659 # 1660 * return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]);" 1661 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder. 1662 [(set_attr "type" "alu_imm,alu_sreg,neon_add,alu_imm,multiple,alu_imm") 1663 (set_attr "simd" "*,*,yes,*,*,*")] 1664) 1665 1666;; zero_extend version of above 1667(define_insn "*addsi3_aarch64_uxtw" 1668 [(set 1669 (match_operand:DI 0 "register_operand" "=rk,rk,rk,r") 1670 (zero_extend:DI 1671 (plus:SI (match_operand:SI 1 "register_operand" "%rk,rk,rk,rk") 1672 (match_operand:SI 2 "aarch64_pluslong_operand" "I,r,J,Uaa"))))] 1673 "" 1674 "@ 1675 add\\t%w0, %w1, %2 1676 add\\t%w0, %w1, %w2 1677 sub\\t%w0, %w1, #%n2 1678 #" 1679 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple")] 1680) 1681 1682;; If there's a free register, and we can load the constant with a 1683;; single instruction, do so. This has a chance to improve scheduling. 1684(define_peephole2 1685 [(match_scratch:GPI 3 "r") 1686 (set (match_operand:GPI 0 "register_operand") 1687 (plus:GPI 1688 (match_operand:GPI 1 "register_operand") 1689 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))] 1690 "aarch64_move_imm (INTVAL (operands[2]), <MODE>mode)" 1691 [(set (match_dup 3) (match_dup 2)) 1692 (set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3)))] 1693) 1694 1695(define_peephole2 1696 [(match_scratch:SI 3 "r") 1697 (set (match_operand:DI 0 "register_operand") 1698 (zero_extend:DI 1699 (plus:SI 1700 (match_operand:SI 1 "register_operand") 1701 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))] 1702 "aarch64_move_imm (INTVAL (operands[2]), SImode)" 1703 [(set (match_dup 3) (match_dup 2)) 1704 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 1) (match_dup 3))))] 1705) 1706 1707;; After peephole2 has had a chance to run, split any remaining long 1708;; additions into two add immediates. 1709(define_split 1710 [(set (match_operand:GPI 0 "register_operand") 1711 (plus:GPI 1712 (match_operand:GPI 1 "register_operand") 1713 (match_operand:GPI 2 "aarch64_pluslong_strict_immedate")))] 1714 "epilogue_completed" 1715 [(set (match_dup 0) (plus:GPI (match_dup 1) (match_dup 3))) 1716 (set (match_dup 0) (plus:GPI (match_dup 0) (match_dup 4)))] 1717 { 1718 HOST_WIDE_INT i = INTVAL (operands[2]); 1719 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff)); 1720 operands[3] = GEN_INT (i - s); 1721 operands[4] = GEN_INT (s); 1722 } 1723) 1724 1725;; Match addition of polynomial offsets that require one temporary, for which 1726;; we can use the early-clobbered destination register. This is a separate 1727;; pattern so that the early clobber doesn't affect register allocation 1728;; for other forms of addition. However, we still need to provide an 1729;; all-register alternative, in case the offset goes out of range after 1730;; elimination. For completeness we might as well provide all GPR-based 1731;; alternatives from the main pattern. 1732;; 1733;; We don't have a pattern for additions requiring two temporaries since at 1734;; present LRA doesn't allow new scratches to be added during elimination. 1735;; Such offsets should be rare anyway. 1736;; 1737;; ??? But if we added LRA support for new scratches, much of the ugliness 1738;; here would go away. We could just handle all polynomial constants in 1739;; this pattern. 1740(define_insn_and_split "*add<mode>3_poly_1" 1741 [(set 1742 (match_operand:GPI 0 "register_operand" "=r,r,r,r,r,&r") 1743 (plus:GPI 1744 (match_operand:GPI 1 "register_operand" "%rk,rk,rk,rk,rk,rk") 1745 (match_operand:GPI 2 "aarch64_pluslong_or_poly_operand" "I,r,J,Uaa,Uav,Uat")))] 1746 "TARGET_SVE && operands[0] != stack_pointer_rtx" 1747 "@ 1748 add\\t%<w>0, %<w>1, %2 1749 add\\t%<w>0, %<w>1, %<w>2 1750 sub\\t%<w>0, %<w>1, #%n2 1751 # 1752 * return aarch64_output_sve_addvl_addpl (operands[0], operands[1], operands[2]); 1753 #" 1754 "&& epilogue_completed 1755 && !reg_overlap_mentioned_p (operands[0], operands[1]) 1756 && aarch64_split_add_offset_immediate (operands[2], <MODE>mode)" 1757 [(const_int 0)] 1758 { 1759 aarch64_split_add_offset (<MODE>mode, operands[0], operands[1], 1760 operands[2], operands[0], NULL_RTX); 1761 DONE; 1762 } 1763 ;; The "alu_imm" type for ADDVL/ADDPL is just a placeholder. 1764 [(set_attr "type" "alu_imm,alu_sreg,alu_imm,multiple,alu_imm,multiple")] 1765) 1766 1767(define_split 1768 [(set (match_operand:DI 0 "register_operand") 1769 (zero_extend:DI 1770 (plus:SI 1771 (match_operand:SI 1 "register_operand") 1772 (match_operand:SI 2 "aarch64_pluslong_strict_immedate"))))] 1773 "epilogue_completed" 1774 [(set (match_dup 5) (plus:SI (match_dup 1) (match_dup 3))) 1775 (set (match_dup 0) (zero_extend:DI (plus:SI (match_dup 5) (match_dup 4))))] 1776 { 1777 HOST_WIDE_INT i = INTVAL (operands[2]); 1778 HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff)); 1779 operands[3] = GEN_INT (i - s); 1780 operands[4] = GEN_INT (s); 1781 operands[5] = gen_lowpart (SImode, operands[0]); 1782 } 1783) 1784 1785(define_expand "addti3" 1786 [(set (match_operand:TI 0 "register_operand" "") 1787 (plus:TI (match_operand:TI 1 "register_operand" "") 1788 (match_operand:TI 2 "register_operand" "")))] 1789 "" 1790{ 1791 rtx low = gen_reg_rtx (DImode); 1792 emit_insn (gen_adddi3_compareC (low, gen_lowpart (DImode, operands[1]), 1793 gen_lowpart (DImode, operands[2]))); 1794 1795 rtx high = gen_reg_rtx (DImode); 1796 emit_insn (gen_adddi3_carryin (high, gen_highpart (DImode, operands[1]), 1797 gen_highpart (DImode, operands[2]))); 1798 1799 emit_move_insn (gen_lowpart (DImode, operands[0]), low); 1800 emit_move_insn (gen_highpart (DImode, operands[0]), high); 1801 DONE; 1802}) 1803 1804(define_insn "add<mode>3_compare0" 1805 [(set (reg:CC_NZ CC_REGNUM) 1806 (compare:CC_NZ 1807 (plus:GPI (match_operand:GPI 1 "register_operand" "%r,r,r") 1808 (match_operand:GPI 2 "aarch64_plus_operand" "r,I,J")) 1809 (const_int 0))) 1810 (set (match_operand:GPI 0 "register_operand" "=r,r,r") 1811 (plus:GPI (match_dup 1) (match_dup 2)))] 1812 "" 1813 "@ 1814 adds\\t%<w>0, %<w>1, %<w>2 1815 adds\\t%<w>0, %<w>1, %2 1816 subs\\t%<w>0, %<w>1, #%n2" 1817 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] 1818) 1819 1820;; zero_extend version of above 1821(define_insn "*addsi3_compare0_uxtw" 1822 [(set (reg:CC_NZ CC_REGNUM) 1823 (compare:CC_NZ 1824 (plus:SI (match_operand:SI 1 "register_operand" "%r,r,r") 1825 (match_operand:SI 2 "aarch64_plus_operand" "r,I,J")) 1826 (const_int 0))) 1827 (set (match_operand:DI 0 "register_operand" "=r,r,r") 1828 (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] 1829 "" 1830 "@ 1831 adds\\t%w0, %w1, %w2 1832 adds\\t%w0, %w1, %2 1833 subs\\t%w0, %w1, #%n2" 1834 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] 1835) 1836 1837(define_insn "*add<mode>3_compareC_cconly_imm" 1838 [(set (reg:CC_C CC_REGNUM) 1839 (ne:CC_C 1840 (plus:<DWI> 1841 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r,r")) 1842 (match_operand:<DWI> 2 "const_scalar_int_operand" "")) 1843 (zero_extend:<DWI> 1844 (plus:GPI 1845 (match_dup 0) 1846 (match_operand:GPI 1 "aarch64_plus_immediate" "I,J")))))] 1847 "aarch64_zero_extend_const_eq (<DWI>mode, operands[2], 1848 <MODE>mode, operands[1])" 1849 "@ 1850 cmn\\t%<w>0, %1 1851 cmp\\t%<w>0, #%n1" 1852 [(set_attr "type" "alus_imm")] 1853) 1854 1855(define_insn "*add<mode>3_compareC_cconly" 1856 [(set (reg:CC_C CC_REGNUM) 1857 (ne:CC_C 1858 (plus:<DWI> 1859 (zero_extend:<DWI> (match_operand:GPI 0 "register_operand" "r")) 1860 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r"))) 1861 (zero_extend:<DWI> (plus:GPI (match_dup 0) (match_dup 1)))))] 1862 "" 1863 "cmn\\t%<w>0, %<w>1" 1864 [(set_attr "type" "alus_sreg")] 1865) 1866 1867(define_insn "*add<mode>3_compareC_imm" 1868 [(set (reg:CC_C CC_REGNUM) 1869 (ne:CC_C 1870 (plus:<DWI> 1871 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r,r")) 1872 (match_operand:<DWI> 3 "const_scalar_int_operand" "")) 1873 (zero_extend:<DWI> 1874 (plus:GPI 1875 (match_dup 1) 1876 (match_operand:GPI 2 "aarch64_plus_immediate" "I,J"))))) 1877 (set (match_operand:GPI 0 "register_operand" "=r,r") 1878 (plus:GPI (match_dup 1) (match_dup 2)))] 1879 "aarch64_zero_extend_const_eq (<DWI>mode, operands[3], 1880 <MODE>mode, operands[2])" 1881 "@ 1882 adds\\t%<w>0, %<w>1, %2 1883 subs\\t%<w>0, %<w>1, #%n2" 1884 [(set_attr "type" "alus_imm")] 1885) 1886 1887(define_insn "add<mode>3_compareC" 1888 [(set (reg:CC_C CC_REGNUM) 1889 (ne:CC_C 1890 (plus:<DWI> 1891 (zero_extend:<DWI> (match_operand:GPI 1 "register_operand" "r")) 1892 (zero_extend:<DWI> (match_operand:GPI 2 "register_operand" "r"))) 1893 (zero_extend:<DWI> 1894 (plus:GPI (match_dup 1) (match_dup 2))))) 1895 (set (match_operand:GPI 0 "register_operand" "=r") 1896 (plus:GPI (match_dup 1) (match_dup 2)))] 1897 "" 1898 "adds\\t%<w>0, %<w>1, %<w>2" 1899 [(set_attr "type" "alus_sreg")] 1900) 1901 1902(define_insn "*adds_shift_imm_<mode>" 1903 [(set (reg:CC_NZ CC_REGNUM) 1904 (compare:CC_NZ 1905 (plus:GPI (ASHIFT:GPI 1906 (match_operand:GPI 1 "register_operand" "r") 1907 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")) 1908 (match_operand:GPI 3 "register_operand" "r")) 1909 (const_int 0))) 1910 (set (match_operand:GPI 0 "register_operand" "=r") 1911 (plus:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2)) 1912 (match_dup 3)))] 1913 "" 1914 "adds\\t%<w>0, %<w>3, %<w>1, <shift> %2" 1915 [(set_attr "type" "alus_shift_imm")] 1916) 1917 1918(define_insn "*subs_shift_imm_<mode>" 1919 [(set (reg:CC_NZ CC_REGNUM) 1920 (compare:CC_NZ 1921 (minus:GPI (match_operand:GPI 1 "register_operand" "r") 1922 (ASHIFT:GPI 1923 (match_operand:GPI 2 "register_operand" "r") 1924 (match_operand:QI 3 "aarch64_shift_imm_<mode>" "n"))) 1925 (const_int 0))) 1926 (set (match_operand:GPI 0 "register_operand" "=r") 1927 (minus:GPI (match_dup 1) 1928 (ASHIFT:GPI (match_dup 2) (match_dup 3))))] 1929 "" 1930 "subs\\t%<w>0, %<w>1, %<w>2, <shift> %3" 1931 [(set_attr "type" "alus_shift_imm")] 1932) 1933 1934(define_insn "*adds_mul_imm_<mode>" 1935 [(set (reg:CC_NZ CC_REGNUM) 1936 (compare:CC_NZ 1937 (plus:GPI (mult:GPI 1938 (match_operand:GPI 1 "register_operand" "r") 1939 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n")) 1940 (match_operand:GPI 3 "register_operand" "r")) 1941 (const_int 0))) 1942 (set (match_operand:GPI 0 "register_operand" "=r") 1943 (plus:GPI (mult:GPI (match_dup 1) (match_dup 2)) 1944 (match_dup 3)))] 1945 "" 1946 "adds\\t%<w>0, %<w>3, %<w>1, lsl %p2" 1947 [(set_attr "type" "alus_shift_imm")] 1948) 1949 1950(define_insn "*subs_mul_imm_<mode>" 1951 [(set (reg:CC_NZ CC_REGNUM) 1952 (compare:CC_NZ 1953 (minus:GPI (match_operand:GPI 1 "register_operand" "r") 1954 (mult:GPI 1955 (match_operand:GPI 2 "register_operand" "r") 1956 (match_operand:QI 3 "aarch64_pwr_2_<mode>" "n"))) 1957 (const_int 0))) 1958 (set (match_operand:GPI 0 "register_operand" "=r") 1959 (minus:GPI (match_dup 1) 1960 (mult:GPI (match_dup 2) (match_dup 3))))] 1961 "" 1962 "subs\\t%<w>0, %<w>1, %<w>2, lsl %p3" 1963 [(set_attr "type" "alus_shift_imm")] 1964) 1965 1966(define_insn "*adds_<optab><ALLX:mode>_<GPI:mode>" 1967 [(set (reg:CC_NZ CC_REGNUM) 1968 (compare:CC_NZ 1969 (plus:GPI 1970 (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r")) 1971 (match_operand:GPI 2 "register_operand" "r")) 1972 (const_int 0))) 1973 (set (match_operand:GPI 0 "register_operand" "=r") 1974 (plus:GPI (ANY_EXTEND:GPI (match_dup 1)) (match_dup 2)))] 1975 "" 1976 "adds\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>" 1977 [(set_attr "type" "alus_ext")] 1978) 1979 1980(define_insn "*subs_<optab><ALLX:mode>_<GPI:mode>" 1981 [(set (reg:CC_NZ CC_REGNUM) 1982 (compare:CC_NZ 1983 (minus:GPI (match_operand:GPI 1 "register_operand" "r") 1984 (ANY_EXTEND:GPI 1985 (match_operand:ALLX 2 "register_operand" "r"))) 1986 (const_int 0))) 1987 (set (match_operand:GPI 0 "register_operand" "=r") 1988 (minus:GPI (match_dup 1) (ANY_EXTEND:GPI (match_dup 2))))] 1989 "" 1990 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>" 1991 [(set_attr "type" "alus_ext")] 1992) 1993 1994(define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>" 1995 [(set (reg:CC_NZ CC_REGNUM) 1996 (compare:CC_NZ 1997 (plus:GPI (ashift:GPI 1998 (ANY_EXTEND:GPI 1999 (match_operand:ALLX 1 "register_operand" "r")) 2000 (match_operand 2 "aarch64_imm3" "Ui3")) 2001 (match_operand:GPI 3 "register_operand" "r")) 2002 (const_int 0))) 2003 (set (match_operand:GPI 0 "register_operand" "=rk") 2004 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI (match_dup 1)) 2005 (match_dup 2)) 2006 (match_dup 3)))] 2007 "" 2008 "adds\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2" 2009 [(set_attr "type" "alus_ext")] 2010) 2011 2012(define_insn "*subs_<optab><ALLX:mode>_shift_<GPI:mode>" 2013 [(set (reg:CC_NZ CC_REGNUM) 2014 (compare:CC_NZ 2015 (minus:GPI (match_operand:GPI 1 "register_operand" "r") 2016 (ashift:GPI 2017 (ANY_EXTEND:GPI 2018 (match_operand:ALLX 2 "register_operand" "r")) 2019 (match_operand 3 "aarch64_imm3" "Ui3"))) 2020 (const_int 0))) 2021 (set (match_operand:GPI 0 "register_operand" "=rk") 2022 (minus:GPI (match_dup 1) 2023 (ashift:GPI (ANY_EXTEND:GPI (match_dup 2)) 2024 (match_dup 3))))] 2025 "" 2026 "subs\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3" 2027 [(set_attr "type" "alus_ext")] 2028) 2029 2030(define_insn "*adds_<optab><mode>_multp2" 2031 [(set (reg:CC_NZ CC_REGNUM) 2032 (compare:CC_NZ 2033 (plus:GPI (ANY_EXTRACT:GPI 2034 (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2035 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2036 (match_operand 3 "const_int_operand" "n") 2037 (const_int 0)) 2038 (match_operand:GPI 4 "register_operand" "r")) 2039 (const_int 0))) 2040 (set (match_operand:GPI 0 "register_operand" "=r") 2041 (plus:GPI (ANY_EXTRACT:GPI (mult:GPI (match_dup 1) (match_dup 2)) 2042 (match_dup 3) 2043 (const_int 0)) 2044 (match_dup 4)))] 2045 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])" 2046 "adds\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2" 2047 [(set_attr "type" "alus_ext")] 2048) 2049 2050(define_insn "*subs_<optab><mode>_multp2" 2051 [(set (reg:CC_NZ CC_REGNUM) 2052 (compare:CC_NZ 2053 (minus:GPI (match_operand:GPI 4 "register_operand" "r") 2054 (ANY_EXTRACT:GPI 2055 (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2056 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2057 (match_operand 3 "const_int_operand" "n") 2058 (const_int 0))) 2059 (const_int 0))) 2060 (set (match_operand:GPI 0 "register_operand" "=r") 2061 (minus:GPI (match_dup 4) (ANY_EXTRACT:GPI 2062 (mult:GPI (match_dup 1) (match_dup 2)) 2063 (match_dup 3) 2064 (const_int 0))))] 2065 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])" 2066 "subs\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2" 2067 [(set_attr "type" "alus_ext")] 2068) 2069 2070(define_insn "*add<mode>3nr_compare0" 2071 [(set (reg:CC_NZ CC_REGNUM) 2072 (compare:CC_NZ 2073 (plus:GPI (match_operand:GPI 0 "register_operand" "%r,r,r") 2074 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")) 2075 (const_int 0)))] 2076 "" 2077 "@ 2078 cmn\\t%<w>0, %<w>1 2079 cmn\\t%<w>0, %1 2080 cmp\\t%<w>0, #%n1" 2081 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] 2082) 2083 2084(define_insn "aarch64_sub<mode>_compare0" 2085 [(set (reg:CC_NZ CC_REGNUM) 2086 (compare:CC_NZ 2087 (minus:GPI (match_operand:GPI 0 "register_operand" "r") 2088 (match_operand:GPI 1 "aarch64_plus_operand" "r")) 2089 (const_int 0)))] 2090 "" 2091 "cmp\\t%<w>0, %<w>1" 2092 [(set_attr "type" "alus_sreg")] 2093) 2094 2095(define_insn "*compare_neg<mode>" 2096 [(set (reg:CC_Z CC_REGNUM) 2097 (compare:CC_Z 2098 (neg:GPI (match_operand:GPI 0 "register_operand" "r")) 2099 (match_operand:GPI 1 "register_operand" "r")))] 2100 "" 2101 "cmn\\t%<w>1, %<w>0" 2102 [(set_attr "type" "alus_sreg")] 2103) 2104 2105(define_insn "*add_<shift>_<mode>" 2106 [(set (match_operand:GPI 0 "register_operand" "=r") 2107 (plus:GPI (ASHIFT:GPI (match_operand:GPI 1 "register_operand" "r") 2108 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")) 2109 (match_operand:GPI 3 "register_operand" "r")))] 2110 "" 2111 "add\\t%<w>0, %<w>3, %<w>1, <shift> %2" 2112 [(set_attr "type" "alu_shift_imm")] 2113) 2114 2115;; zero_extend version of above 2116(define_insn "*add_<shift>_si_uxtw" 2117 [(set (match_operand:DI 0 "register_operand" "=r") 2118 (zero_extend:DI 2119 (plus:SI (ASHIFT:SI (match_operand:SI 1 "register_operand" "r") 2120 (match_operand:QI 2 "aarch64_shift_imm_si" "n")) 2121 (match_operand:SI 3 "register_operand" "r"))))] 2122 "" 2123 "add\\t%w0, %w3, %w1, <shift> %2" 2124 [(set_attr "type" "alu_shift_imm")] 2125) 2126 2127(define_insn "*add_mul_imm_<mode>" 2128 [(set (match_operand:GPI 0 "register_operand" "=r") 2129 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2130 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n")) 2131 (match_operand:GPI 3 "register_operand" "r")))] 2132 "" 2133 "add\\t%<w>0, %<w>3, %<w>1, lsl %p2" 2134 [(set_attr "type" "alu_shift_imm")] 2135) 2136 2137(define_insn "*add_<optab><ALLX:mode>_<GPI:mode>" 2138 [(set (match_operand:GPI 0 "register_operand" "=rk") 2139 (plus:GPI (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r")) 2140 (match_operand:GPI 2 "register_operand" "r")))] 2141 "" 2142 "add\\t%<GPI:w>0, %<GPI:w>2, %<GPI:w>1, <su>xt<ALLX:size>" 2143 [(set_attr "type" "alu_ext")] 2144) 2145 2146;; zero_extend version of above 2147(define_insn "*add_<optab><SHORT:mode>_si_uxtw" 2148 [(set (match_operand:DI 0 "register_operand" "=rk") 2149 (zero_extend:DI 2150 (plus:SI (ANY_EXTEND:SI (match_operand:SHORT 1 "register_operand" "r")) 2151 (match_operand:GPI 2 "register_operand" "r"))))] 2152 "" 2153 "add\\t%w0, %w2, %w1, <su>xt<SHORT:size>" 2154 [(set_attr "type" "alu_ext")] 2155) 2156 2157(define_insn "*add_<optab><ALLX:mode>_shft_<GPI:mode>" 2158 [(set (match_operand:GPI 0 "register_operand" "=rk") 2159 (plus:GPI (ashift:GPI (ANY_EXTEND:GPI 2160 (match_operand:ALLX 1 "register_operand" "r")) 2161 (match_operand 2 "aarch64_imm3" "Ui3")) 2162 (match_operand:GPI 3 "register_operand" "r")))] 2163 "" 2164 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %2" 2165 [(set_attr "type" "alu_ext")] 2166) 2167 2168;; zero_extend version of above 2169(define_insn "*add_<optab><SHORT:mode>_shft_si_uxtw" 2170 [(set (match_operand:DI 0 "register_operand" "=rk") 2171 (zero_extend:DI 2172 (plus:SI (ashift:SI (ANY_EXTEND:SI 2173 (match_operand:SHORT 1 "register_operand" "r")) 2174 (match_operand 2 "aarch64_imm3" "Ui3")) 2175 (match_operand:SI 3 "register_operand" "r"))))] 2176 "" 2177 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %2" 2178 [(set_attr "type" "alu_ext")] 2179) 2180 2181(define_insn "*add_<optab><ALLX:mode>_mult_<GPI:mode>" 2182 [(set (match_operand:GPI 0 "register_operand" "=rk") 2183 (plus:GPI (mult:GPI (ANY_EXTEND:GPI 2184 (match_operand:ALLX 1 "register_operand" "r")) 2185 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2186 (match_operand:GPI 3 "register_operand" "r")))] 2187 "" 2188 "add\\t%<GPI:w>0, %<GPI:w>3, %<GPI:w>1, <su>xt<ALLX:size> %p2" 2189 [(set_attr "type" "alu_ext")] 2190) 2191 2192;; zero_extend version of above 2193(define_insn "*add_<optab><SHORT:mode>_mult_si_uxtw" 2194 [(set (match_operand:DI 0 "register_operand" "=rk") 2195 (zero_extend:DI (plus:SI (mult:SI (ANY_EXTEND:SI 2196 (match_operand:SHORT 1 "register_operand" "r")) 2197 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2198 (match_operand:SI 3 "register_operand" "r"))))] 2199 "" 2200 "add\\t%w0, %w3, %w1, <su>xt<SHORT:size> %p2" 2201 [(set_attr "type" "alu_ext")] 2202) 2203 2204(define_insn "*add_<optab><mode>_multp2" 2205 [(set (match_operand:GPI 0 "register_operand" "=rk") 2206 (plus:GPI (ANY_EXTRACT:GPI 2207 (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2208 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2209 (match_operand 3 "const_int_operand" "n") 2210 (const_int 0)) 2211 (match_operand:GPI 4 "register_operand" "r")))] 2212 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])" 2213 "add\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2" 2214 [(set_attr "type" "alu_ext")] 2215) 2216 2217;; zero_extend version of above 2218(define_insn "*add_<optab>si_multp2_uxtw" 2219 [(set (match_operand:DI 0 "register_operand" "=rk") 2220 (zero_extend:DI 2221 (plus:SI (ANY_EXTRACT:SI 2222 (mult:SI (match_operand:SI 1 "register_operand" "r") 2223 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2224 (match_operand 3 "const_int_operand" "n") 2225 (const_int 0)) 2226 (match_operand:SI 4 "register_operand" "r"))))] 2227 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])" 2228 "add\\t%w0, %w4, %w1, <su>xt%e3 %p2" 2229 [(set_attr "type" "alu_ext")] 2230) 2231 2232(define_expand "add<mode>3_carryin" 2233 [(set (match_operand:GPI 0 "register_operand") 2234 (plus:GPI 2235 (plus:GPI 2236 (ne:GPI (reg:CC_C CC_REGNUM) (const_int 0)) 2237 (match_operand:GPI 1 "aarch64_reg_or_zero")) 2238 (match_operand:GPI 2 "aarch64_reg_or_zero")))] 2239 "" 2240 "" 2241) 2242 2243;; Note that add with carry with two zero inputs is matched by cset, 2244;; and that add with carry with one zero input is matched by cinc. 2245 2246(define_insn "*add<mode>3_carryin" 2247 [(set (match_operand:GPI 0 "register_operand" "=r") 2248 (plus:GPI 2249 (plus:GPI 2250 (match_operand:GPI 3 "aarch64_carry_operation" "") 2251 (match_operand:GPI 1 "register_operand" "r")) 2252 (match_operand:GPI 2 "register_operand" "r")))] 2253 "" 2254 "adc\\t%<w>0, %<w>1, %<w>2" 2255 [(set_attr "type" "adc_reg")] 2256) 2257 2258;; zero_extend version of above 2259(define_insn "*addsi3_carryin_uxtw" 2260 [(set (match_operand:DI 0 "register_operand" "=r") 2261 (zero_extend:DI 2262 (plus:SI 2263 (plus:SI 2264 (match_operand:SI 3 "aarch64_carry_operation" "") 2265 (match_operand:SI 1 "register_operand" "r")) 2266 (match_operand:SI 2 "register_operand" "r"))))] 2267 "" 2268 "adc\\t%w0, %w1, %w2" 2269 [(set_attr "type" "adc_reg")] 2270) 2271 2272(define_insn "*add_uxt<mode>_shift2" 2273 [(set (match_operand:GPI 0 "register_operand" "=rk") 2274 (plus:GPI (and:GPI 2275 (ashift:GPI (match_operand:GPI 1 "register_operand" "r") 2276 (match_operand 2 "aarch64_imm3" "Ui3")) 2277 (match_operand 3 "const_int_operand" "n")) 2278 (match_operand:GPI 4 "register_operand" "r")))] 2279 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0" 2280 "* 2281 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL(operands[2]), 2282 INTVAL (operands[3]))); 2283 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";" 2284 [(set_attr "type" "alu_ext")] 2285) 2286 2287;; zero_extend version of above 2288(define_insn "*add_uxtsi_shift2_uxtw" 2289 [(set (match_operand:DI 0 "register_operand" "=rk") 2290 (zero_extend:DI 2291 (plus:SI (and:SI 2292 (ashift:SI (match_operand:SI 1 "register_operand" "r") 2293 (match_operand 2 "aarch64_imm3" "Ui3")) 2294 (match_operand 3 "const_int_operand" "n")) 2295 (match_operand:SI 4 "register_operand" "r"))))] 2296 "aarch64_uxt_size (INTVAL (operands[2]), INTVAL (operands[3])) != 0" 2297 "* 2298 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]), 2299 INTVAL (operands[3]))); 2300 return \"add\t%w0, %w4, %w1, uxt%e3 %2\";" 2301 [(set_attr "type" "alu_ext")] 2302) 2303 2304(define_insn "*add_uxt<mode>_multp2" 2305 [(set (match_operand:GPI 0 "register_operand" "=rk") 2306 (plus:GPI (and:GPI 2307 (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2308 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2309 (match_operand 3 "const_int_operand" "n")) 2310 (match_operand:GPI 4 "register_operand" "r")))] 2311 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0" 2312 "* 2313 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), 2314 INTVAL (operands[3]))); 2315 return \"add\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";" 2316 [(set_attr "type" "alu_ext")] 2317) 2318 2319;; zero_extend version of above 2320(define_insn "*add_uxtsi_multp2_uxtw" 2321 [(set (match_operand:DI 0 "register_operand" "=rk") 2322 (zero_extend:DI 2323 (plus:SI (and:SI 2324 (mult:SI (match_operand:SI 1 "register_operand" "r") 2325 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2326 (match_operand 3 "const_int_operand" "n")) 2327 (match_operand:SI 4 "register_operand" "r"))))] 2328 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), INTVAL (operands[3])) != 0" 2329 "* 2330 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), 2331 INTVAL (operands[3]))); 2332 return \"add\t%w0, %w4, %w1, uxt%e3 %p2\";" 2333 [(set_attr "type" "alu_ext")] 2334) 2335 2336(define_insn "subsi3" 2337 [(set (match_operand:SI 0 "register_operand" "=rk") 2338 (minus:SI (match_operand:SI 1 "register_operand" "rk") 2339 (match_operand:SI 2 "register_operand" "r")))] 2340 "" 2341 "sub\\t%w0, %w1, %w2" 2342 [(set_attr "type" "alu_sreg")] 2343) 2344 2345;; zero_extend version of above 2346(define_insn "*subsi3_uxtw" 2347 [(set (match_operand:DI 0 "register_operand" "=rk") 2348 (zero_extend:DI 2349 (minus:SI (match_operand:SI 1 "register_operand" "rk") 2350 (match_operand:SI 2 "register_operand" "r"))))] 2351 "" 2352 "sub\\t%w0, %w1, %w2" 2353 [(set_attr "type" "alu_sreg")] 2354) 2355 2356(define_insn "subdi3" 2357 [(set (match_operand:DI 0 "register_operand" "=rk,w") 2358 (minus:DI (match_operand:DI 1 "register_operand" "rk,w") 2359 (match_operand:DI 2 "register_operand" "r,w")))] 2360 "" 2361 "@ 2362 sub\\t%x0, %x1, %x2 2363 sub\\t%d0, %d1, %d2" 2364 [(set_attr "type" "alu_sreg, neon_sub") 2365 (set_attr "simd" "*,yes")] 2366) 2367 2368(define_expand "subti3" 2369 [(set (match_operand:TI 0 "register_operand" "") 2370 (minus:TI (match_operand:TI 1 "register_operand" "") 2371 (match_operand:TI 2 "register_operand" "")))] 2372 "" 2373{ 2374 rtx low = gen_reg_rtx (DImode); 2375 emit_insn (gen_subdi3_compare1 (low, gen_lowpart (DImode, operands[1]), 2376 gen_lowpart (DImode, operands[2]))); 2377 2378 rtx high = gen_reg_rtx (DImode); 2379 emit_insn (gen_subdi3_carryin (high, gen_highpart (DImode, operands[1]), 2380 gen_highpart (DImode, operands[2]))); 2381 2382 emit_move_insn (gen_lowpart (DImode, operands[0]), low); 2383 emit_move_insn (gen_highpart (DImode, operands[0]), high); 2384 DONE; 2385}) 2386 2387(define_insn "*sub<mode>3_compare0" 2388 [(set (reg:CC_NZ CC_REGNUM) 2389 (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "r") 2390 (match_operand:GPI 2 "register_operand" "r")) 2391 (const_int 0))) 2392 (set (match_operand:GPI 0 "register_operand" "=r") 2393 (minus:GPI (match_dup 1) (match_dup 2)))] 2394 "" 2395 "subs\\t%<w>0, %<w>1, %<w>2" 2396 [(set_attr "type" "alus_sreg")] 2397) 2398 2399;; zero_extend version of above 2400(define_insn "*subsi3_compare0_uxtw" 2401 [(set (reg:CC_NZ CC_REGNUM) 2402 (compare:CC_NZ (minus:SI (match_operand:SI 1 "register_operand" "r") 2403 (match_operand:SI 2 "register_operand" "r")) 2404 (const_int 0))) 2405 (set (match_operand:DI 0 "register_operand" "=r") 2406 (zero_extend:DI (minus:SI (match_dup 1) (match_dup 2))))] 2407 "" 2408 "subs\\t%w0, %w1, %w2" 2409 [(set_attr "type" "alus_sreg")] 2410) 2411 2412(define_insn "sub<mode>3_compare1" 2413 [(set (reg:CC CC_REGNUM) 2414 (compare:CC 2415 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ") 2416 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ"))) 2417 (set (match_operand:GPI 0 "register_operand" "=r") 2418 (minus:GPI (match_dup 1) (match_dup 2)))] 2419 "" 2420 "subs\\t%<w>0, %<w>1, %<w>2" 2421 [(set_attr "type" "alus_sreg")] 2422) 2423 2424(define_insn "sub<mode>3_compare1_imm" 2425 [(set (reg:CC CC_REGNUM) 2426 (compare:CC 2427 (match_operand:GPI 1 "register_operand" "r") 2428 (match_operand:GPI 3 "const_int_operand" "n"))) 2429 (set (match_operand:GPI 0 "register_operand" "=r") 2430 (plus:GPI (match_dup 1) 2431 (match_operand:GPI 2 "aarch64_sub_immediate" "J")))] 2432 "INTVAL (operands[3]) == -INTVAL (operands[2])" 2433 "subs\\t%<w>0, %<w>1, #%n2" 2434 [(set_attr "type" "alus_sreg")] 2435) 2436 2437(define_peephole2 2438 [(set (match_operand:GPI 0 "register_operand") 2439 (minus:GPI (match_operand:GPI 1 "aarch64_reg_or_zero") 2440 (match_operand:GPI 2 "aarch64_reg_or_zero"))) 2441 (set (reg:CC CC_REGNUM) 2442 (compare:CC 2443 (match_dup 1) 2444 (match_dup 2)))] 2445 "!reg_overlap_mentioned_p (operands[0], operands[1]) 2446 && !reg_overlap_mentioned_p (operands[0], operands[2])" 2447 [(const_int 0)] 2448 { 2449 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], 2450 operands[2])); 2451 DONE; 2452 } 2453) 2454 2455;; Same as the above peephole but with the compare and minus in 2456;; swapped order. The restriction on overlap between operand 0 2457;; and operands 1 and 2 doesn't apply here. 2458(define_peephole2 2459 [(set (reg:CC CC_REGNUM) 2460 (compare:CC 2461 (match_operand:GPI 1 "aarch64_reg_or_zero") 2462 (match_operand:GPI 2 "aarch64_reg_or_zero"))) 2463 (set (match_operand:GPI 0 "register_operand") 2464 (minus:GPI (match_dup 1) 2465 (match_dup 2)))] 2466 "" 2467 [(const_int 0)] 2468 { 2469 emit_insn (gen_sub<mode>3_compare1 (operands[0], operands[1], 2470 operands[2])); 2471 DONE; 2472 } 2473) 2474 2475(define_peephole2 2476 [(set (match_operand:GPI 0 "register_operand") 2477 (plus:GPI (match_operand:GPI 1 "register_operand") 2478 (match_operand:GPI 2 "aarch64_sub_immediate"))) 2479 (set (reg:CC CC_REGNUM) 2480 (compare:CC 2481 (match_dup 1) 2482 (match_operand:GPI 3 "const_int_operand")))] 2483 "!reg_overlap_mentioned_p (operands[0], operands[1]) 2484 && INTVAL (operands[3]) == -INTVAL (operands[2])" 2485 [(const_int 0)] 2486 { 2487 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1], 2488 operands[2], operands[3])); 2489 DONE; 2490 } 2491) 2492 2493;; Same as the above peephole but with the compare and minus in 2494;; swapped order. The restriction on overlap between operand 0 2495;; and operands 1 doesn't apply here. 2496(define_peephole2 2497 [(set (reg:CC CC_REGNUM) 2498 (compare:CC 2499 (match_operand:GPI 1 "register_operand") 2500 (match_operand:GPI 3 "const_int_operand"))) 2501 (set (match_operand:GPI 0 "register_operand") 2502 (plus:GPI (match_dup 1) 2503 (match_operand:GPI 2 "aarch64_sub_immediate")))] 2504 "INTVAL (operands[3]) == -INTVAL (operands[2])" 2505 [(const_int 0)] 2506 { 2507 emit_insn (gen_sub<mode>3_compare1_imm (operands[0], operands[1], 2508 operands[2], operands[3])); 2509 DONE; 2510 } 2511) 2512 2513(define_insn "*sub_<shift>_<mode>" 2514 [(set (match_operand:GPI 0 "register_operand" "=r") 2515 (minus:GPI (match_operand:GPI 3 "register_operand" "r") 2516 (ASHIFT:GPI 2517 (match_operand:GPI 1 "register_operand" "r") 2518 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))] 2519 "" 2520 "sub\\t%<w>0, %<w>3, %<w>1, <shift> %2" 2521 [(set_attr "type" "alu_shift_imm")] 2522) 2523 2524;; zero_extend version of above 2525(define_insn "*sub_<shift>_si_uxtw" 2526 [(set (match_operand:DI 0 "register_operand" "=r") 2527 (zero_extend:DI 2528 (minus:SI (match_operand:SI 3 "register_operand" "r") 2529 (ASHIFT:SI 2530 (match_operand:SI 1 "register_operand" "r") 2531 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))] 2532 "" 2533 "sub\\t%w0, %w3, %w1, <shift> %2" 2534 [(set_attr "type" "alu_shift_imm")] 2535) 2536 2537(define_insn "*sub_mul_imm_<mode>" 2538 [(set (match_operand:GPI 0 "register_operand" "=r") 2539 (minus:GPI (match_operand:GPI 3 "register_operand" "r") 2540 (mult:GPI 2541 (match_operand:GPI 1 "register_operand" "r") 2542 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))] 2543 "" 2544 "sub\\t%<w>0, %<w>3, %<w>1, lsl %p2" 2545 [(set_attr "type" "alu_shift_imm")] 2546) 2547 2548;; zero_extend version of above 2549(define_insn "*sub_mul_imm_si_uxtw" 2550 [(set (match_operand:DI 0 "register_operand" "=r") 2551 (zero_extend:DI 2552 (minus:SI (match_operand:SI 3 "register_operand" "r") 2553 (mult:SI 2554 (match_operand:SI 1 "register_operand" "r") 2555 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))] 2556 "" 2557 "sub\\t%w0, %w3, %w1, lsl %p2" 2558 [(set_attr "type" "alu_shift_imm")] 2559) 2560 2561(define_insn "*sub_<optab><ALLX:mode>_<GPI:mode>" 2562 [(set (match_operand:GPI 0 "register_operand" "=rk") 2563 (minus:GPI (match_operand:GPI 1 "register_operand" "rk") 2564 (ANY_EXTEND:GPI 2565 (match_operand:ALLX 2 "register_operand" "r"))))] 2566 "" 2567 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size>" 2568 [(set_attr "type" "alu_ext")] 2569) 2570 2571;; zero_extend version of above 2572(define_insn "*sub_<optab><SHORT:mode>_si_uxtw" 2573 [(set (match_operand:DI 0 "register_operand" "=rk") 2574 (zero_extend:DI 2575 (minus:SI (match_operand:SI 1 "register_operand" "rk") 2576 (ANY_EXTEND:SI 2577 (match_operand:SHORT 2 "register_operand" "r")))))] 2578 "" 2579 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size>" 2580 [(set_attr "type" "alu_ext")] 2581) 2582 2583(define_insn "*sub_<optab><ALLX:mode>_shft_<GPI:mode>" 2584 [(set (match_operand:GPI 0 "register_operand" "=rk") 2585 (minus:GPI (match_operand:GPI 1 "register_operand" "rk") 2586 (ashift:GPI (ANY_EXTEND:GPI 2587 (match_operand:ALLX 2 "register_operand" "r")) 2588 (match_operand 3 "aarch64_imm3" "Ui3"))))] 2589 "" 2590 "sub\\t%<GPI:w>0, %<GPI:w>1, %<GPI:w>2, <su>xt<ALLX:size> %3" 2591 [(set_attr "type" "alu_ext")] 2592) 2593 2594;; zero_extend version of above 2595(define_insn "*sub_<optab><SHORT:mode>_shft_si_uxtw" 2596 [(set (match_operand:DI 0 "register_operand" "=rk") 2597 (zero_extend:DI 2598 (minus:SI (match_operand:SI 1 "register_operand" "rk") 2599 (ashift:SI (ANY_EXTEND:SI 2600 (match_operand:SHORT 2 "register_operand" "r")) 2601 (match_operand 3 "aarch64_imm3" "Ui3")))))] 2602 "" 2603 "sub\\t%w0, %w1, %w2, <su>xt<SHORT:size> %3" 2604 [(set_attr "type" "alu_ext")] 2605) 2606 2607(define_insn "*sub_<optab><mode>_multp2" 2608 [(set (match_operand:GPI 0 "register_operand" "=rk") 2609 (minus:GPI (match_operand:GPI 4 "register_operand" "rk") 2610 (ANY_EXTRACT:GPI 2611 (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2612 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2613 (match_operand 3 "const_int_operand" "n") 2614 (const_int 0))))] 2615 "aarch64_is_extend_from_extract (<MODE>mode, operands[2], operands[3])" 2616 "sub\\t%<w>0, %<w>4, %<w>1, <su>xt%e3 %p2" 2617 [(set_attr "type" "alu_ext")] 2618) 2619 2620;; zero_extend version of above 2621(define_insn "*sub_<optab>si_multp2_uxtw" 2622 [(set (match_operand:DI 0 "register_operand" "=rk") 2623 (zero_extend:DI 2624 (minus:SI (match_operand:SI 4 "register_operand" "rk") 2625 (ANY_EXTRACT:SI 2626 (mult:SI (match_operand:SI 1 "register_operand" "r") 2627 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2628 (match_operand 3 "const_int_operand" "n") 2629 (const_int 0)))))] 2630 "aarch64_is_extend_from_extract (SImode, operands[2], operands[3])" 2631 "sub\\t%w0, %w4, %w1, <su>xt%e3 %p2" 2632 [(set_attr "type" "alu_ext")] 2633) 2634 2635;; The hardware description is op1 + ~op2 + C. 2636;; = op1 + (-op2 + 1) + (1 - !C) 2637;; = op1 - op2 - 1 + 1 - !C 2638;; = op1 - op2 - !C. 2639;; We describe the latter. 2640 2641(define_insn "*sub<mode>3_carryin0" 2642 [(set (match_operand:GPI 0 "register_operand" "=r") 2643 (minus:GPI 2644 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ") 2645 (match_operand:GPI 2 "aarch64_borrow_operation" "")))] 2646 "" 2647 "sbc\\t%<w>0, %<w>1, <w>zr" 2648 [(set_attr "type" "adc_reg")] 2649) 2650 2651;; zero_extend version of the above 2652(define_insn "*subsi3_carryin_uxtw" 2653 [(set (match_operand:DI 0 "register_operand" "=r") 2654 (zero_extend:DI 2655 (minus:SI 2656 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ") 2657 (match_operand:SI 2 "aarch64_borrow_operation" ""))))] 2658 "" 2659 "sbc\\t%w0, %w1, wzr" 2660 [(set_attr "type" "adc_reg")] 2661) 2662 2663(define_expand "sub<mode>3_carryin" 2664 [(set (match_operand:GPI 0 "register_operand") 2665 (minus:GPI 2666 (minus:GPI 2667 (match_operand:GPI 1 "aarch64_reg_or_zero") 2668 (match_operand:GPI 2 "register_operand")) 2669 (ltu:GPI (reg:CC CC_REGNUM) (const_int 0))))] 2670 "" 2671 "" 2672) 2673 2674(define_insn "*sub<mode>3_carryin" 2675 [(set (match_operand:GPI 0 "register_operand" "=r") 2676 (minus:GPI 2677 (minus:GPI 2678 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ") 2679 (match_operand:GPI 2 "register_operand" "r")) 2680 (match_operand:GPI 3 "aarch64_borrow_operation" "")))] 2681 2682 "" 2683 "sbc\\t%<w>0, %<w>1, %<w>2" 2684 [(set_attr "type" "adc_reg")] 2685) 2686 2687;; zero_extend version of the above 2688(define_insn "*subsi3_carryin_uxtw" 2689 [(set (match_operand:DI 0 "register_operand" "=r") 2690 (zero_extend:DI 2691 (minus:SI 2692 (minus:SI 2693 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ") 2694 (match_operand:SI 2 "register_operand" "r")) 2695 (match_operand:SI 3 "aarch64_borrow_operation" ""))))] 2696 2697 "" 2698 "sbc\\t%w0, %w1, %w2" 2699 [(set_attr "type" "adc_reg")] 2700) 2701 2702(define_insn "*sub<mode>3_carryin_alt" 2703 [(set (match_operand:GPI 0 "register_operand" "=r") 2704 (minus:GPI 2705 (minus:GPI 2706 (match_operand:GPI 1 "aarch64_reg_or_zero" "rZ") 2707 (match_operand:GPI 3 "aarch64_borrow_operation" "")) 2708 (match_operand:GPI 2 "register_operand" "r")))] 2709 "" 2710 "sbc\\t%<w>0, %<w>1, %<w>2" 2711 [(set_attr "type" "adc_reg")] 2712) 2713 2714;; zero_extend version of the above 2715(define_insn "*subsi3_carryin_alt_uxtw" 2716 [(set (match_operand:DI 0 "register_operand" "=r") 2717 (zero_extend:DI 2718 (minus:SI 2719 (minus:SI 2720 (match_operand:SI 1 "aarch64_reg_or_zero" "rZ") 2721 (match_operand:SI 3 "aarch64_borrow_operation" "")) 2722 (match_operand:SI 2 "register_operand" "r"))))] 2723 "" 2724 "sbc\\t%w0, %w1, %w2" 2725 [(set_attr "type" "adc_reg")] 2726) 2727 2728(define_insn "*sub_uxt<mode>_shift2" 2729 [(set (match_operand:GPI 0 "register_operand" "=rk") 2730 (minus:GPI (match_operand:GPI 4 "register_operand" "rk") 2731 (and:GPI 2732 (ashift:GPI (match_operand:GPI 1 "register_operand" "r") 2733 (match_operand 2 "aarch64_imm3" "Ui3")) 2734 (match_operand 3 "const_int_operand" "n"))))] 2735 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0" 2736 "* 2737 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]), 2738 INTVAL (operands[3]))); 2739 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %2\";" 2740 [(set_attr "type" "alu_ext")] 2741) 2742 2743;; zero_extend version of above 2744(define_insn "*sub_uxtsi_shift2_uxtw" 2745 [(set (match_operand:DI 0 "register_operand" "=rk") 2746 (zero_extend:DI 2747 (minus:SI (match_operand:SI 4 "register_operand" "rk") 2748 (and:SI 2749 (ashift:SI (match_operand:SI 1 "register_operand" "r") 2750 (match_operand 2 "aarch64_imm3" "Ui3")) 2751 (match_operand 3 "const_int_operand" "n")))))] 2752 "aarch64_uxt_size (INTVAL (operands[2]),INTVAL (operands[3])) != 0" 2753 "* 2754 operands[3] = GEN_INT (aarch64_uxt_size (INTVAL (operands[2]), 2755 INTVAL (operands[3]))); 2756 return \"sub\t%w0, %w4, %w1, uxt%e3 %2\";" 2757 [(set_attr "type" "alu_ext")] 2758) 2759 2760(define_insn "*sub_uxt<mode>_multp2" 2761 [(set (match_operand:GPI 0 "register_operand" "=rk") 2762 (minus:GPI (match_operand:GPI 4 "register_operand" "rk") 2763 (and:GPI 2764 (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2765 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2766 (match_operand 3 "const_int_operand" "n"))))] 2767 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0" 2768 "* 2769 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), 2770 INTVAL (operands[3]))); 2771 return \"sub\t%<w>0, %<w>4, %<w>1, uxt%e3 %p2\";" 2772 [(set_attr "type" "alu_ext")] 2773) 2774 2775;; zero_extend version of above 2776(define_insn "*sub_uxtsi_multp2_uxtw" 2777 [(set (match_operand:DI 0 "register_operand" "=rk") 2778 (zero_extend:DI 2779 (minus:SI (match_operand:SI 4 "register_operand" "rk") 2780 (and:SI 2781 (mult:SI (match_operand:SI 1 "register_operand" "r") 2782 (match_operand 2 "aarch64_pwr_imm3" "Up3")) 2783 (match_operand 3 "const_int_operand" "n")))))] 2784 "aarch64_uxt_size (exact_log2 (INTVAL (operands[2])),INTVAL (operands[3])) != 0" 2785 "* 2786 operands[3] = GEN_INT (aarch64_uxt_size (exact_log2 (INTVAL (operands[2])), 2787 INTVAL (operands[3]))); 2788 return \"sub\t%w0, %w4, %w1, uxt%e3 %p2\";" 2789 [(set_attr "type" "alu_ext")] 2790) 2791 2792(define_expand "abs<mode>2" 2793 [(match_operand:GPI 0 "register_operand" "") 2794 (match_operand:GPI 1 "register_operand" "")] 2795 "" 2796 { 2797 rtx ccreg = aarch64_gen_compare_reg (LT, operands[1], const0_rtx); 2798 rtx x = gen_rtx_LT (VOIDmode, ccreg, const0_rtx); 2799 emit_insn (gen_csneg3<mode>_insn (operands[0], x, operands[1], operands[1])); 2800 DONE; 2801 } 2802) 2803 2804(define_insn "neg<mode>2" 2805 [(set (match_operand:GPI 0 "register_operand" "=r,w") 2806 (neg:GPI (match_operand:GPI 1 "register_operand" "r,w")))] 2807 "" 2808 "@ 2809 neg\\t%<w>0, %<w>1 2810 neg\\t%<rtn>0<vas>, %<rtn>1<vas>" 2811 [(set_attr "type" "alu_sreg, neon_neg<q>") 2812 (set_attr "simd" "*,yes")] 2813) 2814 2815;; zero_extend version of above 2816(define_insn "*negsi2_uxtw" 2817 [(set (match_operand:DI 0 "register_operand" "=r") 2818 (zero_extend:DI (neg:SI (match_operand:SI 1 "register_operand" "r"))))] 2819 "" 2820 "neg\\t%w0, %w1" 2821 [(set_attr "type" "alu_sreg")] 2822) 2823 2824(define_insn "*ngc<mode>" 2825 [(set (match_operand:GPI 0 "register_operand" "=r") 2826 (minus:GPI 2827 (neg:GPI (match_operand:GPI 2 "aarch64_borrow_operation" "")) 2828 (match_operand:GPI 1 "register_operand" "r")))] 2829 "" 2830 "ngc\\t%<w>0, %<w>1" 2831 [(set_attr "type" "adc_reg")] 2832) 2833 2834(define_insn "*ngcsi_uxtw" 2835 [(set (match_operand:DI 0 "register_operand" "=r") 2836 (zero_extend:DI 2837 (minus:SI 2838 (neg:SI (match_operand:SI 2 "aarch64_borrow_operation" "")) 2839 (match_operand:SI 1 "register_operand" "r"))))] 2840 "" 2841 "ngc\\t%w0, %w1" 2842 [(set_attr "type" "adc_reg")] 2843) 2844 2845(define_insn "neg<mode>2_compare0" 2846 [(set (reg:CC_NZ CC_REGNUM) 2847 (compare:CC_NZ (neg:GPI (match_operand:GPI 1 "register_operand" "r")) 2848 (const_int 0))) 2849 (set (match_operand:GPI 0 "register_operand" "=r") 2850 (neg:GPI (match_dup 1)))] 2851 "" 2852 "negs\\t%<w>0, %<w>1" 2853 [(set_attr "type" "alus_sreg")] 2854) 2855 2856;; zero_extend version of above 2857(define_insn "*negsi2_compare0_uxtw" 2858 [(set (reg:CC_NZ CC_REGNUM) 2859 (compare:CC_NZ (neg:SI (match_operand:SI 1 "register_operand" "r")) 2860 (const_int 0))) 2861 (set (match_operand:DI 0 "register_operand" "=r") 2862 (zero_extend:DI (neg:SI (match_dup 1))))] 2863 "" 2864 "negs\\t%w0, %w1" 2865 [(set_attr "type" "alus_sreg")] 2866) 2867 2868(define_insn "*neg_<shift><mode>3_compare0" 2869 [(set (reg:CC_NZ CC_REGNUM) 2870 (compare:CC_NZ 2871 (neg:GPI (ASHIFT:GPI 2872 (match_operand:GPI 1 "register_operand" "r") 2873 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))) 2874 (const_int 0))) 2875 (set (match_operand:GPI 0 "register_operand" "=r") 2876 (neg:GPI (ASHIFT:GPI (match_dup 1) (match_dup 2))))] 2877 "" 2878 "negs\\t%<w>0, %<w>1, <shift> %2" 2879 [(set_attr "type" "alus_shift_imm")] 2880) 2881 2882(define_insn "*neg_<shift>_<mode>2" 2883 [(set (match_operand:GPI 0 "register_operand" "=r") 2884 (neg:GPI (ASHIFT:GPI 2885 (match_operand:GPI 1 "register_operand" "r") 2886 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))] 2887 "" 2888 "neg\\t%<w>0, %<w>1, <shift> %2" 2889 [(set_attr "type" "alu_shift_imm")] 2890) 2891 2892;; zero_extend version of above 2893(define_insn "*neg_<shift>_si2_uxtw" 2894 [(set (match_operand:DI 0 "register_operand" "=r") 2895 (zero_extend:DI 2896 (neg:SI (ASHIFT:SI 2897 (match_operand:SI 1 "register_operand" "r") 2898 (match_operand:QI 2 "aarch64_shift_imm_si" "n")))))] 2899 "" 2900 "neg\\t%w0, %w1, <shift> %2" 2901 [(set_attr "type" "alu_shift_imm")] 2902) 2903 2904(define_insn "*neg_mul_imm_<mode>2" 2905 [(set (match_operand:GPI 0 "register_operand" "=r") 2906 (neg:GPI (mult:GPI 2907 (match_operand:GPI 1 "register_operand" "r") 2908 (match_operand:QI 2 "aarch64_pwr_2_<mode>" "n"))))] 2909 "" 2910 "neg\\t%<w>0, %<w>1, lsl %p2" 2911 [(set_attr "type" "alu_shift_imm")] 2912) 2913 2914;; zero_extend version of above 2915(define_insn "*neg_mul_imm_si2_uxtw" 2916 [(set (match_operand:DI 0 "register_operand" "=r") 2917 (zero_extend:DI 2918 (neg:SI (mult:SI 2919 (match_operand:SI 1 "register_operand" "r") 2920 (match_operand:QI 2 "aarch64_pwr_2_si" "n")))))] 2921 "" 2922 "neg\\t%w0, %w1, lsl %p2" 2923 [(set_attr "type" "alu_shift_imm")] 2924) 2925 2926(define_insn "mul<mode>3" 2927 [(set (match_operand:GPI 0 "register_operand" "=r") 2928 (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2929 (match_operand:GPI 2 "register_operand" "r")))] 2930 "" 2931 "mul\\t%<w>0, %<w>1, %<w>2" 2932 [(set_attr "type" "mul")] 2933) 2934 2935;; zero_extend version of above 2936(define_insn "*mulsi3_uxtw" 2937 [(set (match_operand:DI 0 "register_operand" "=r") 2938 (zero_extend:DI 2939 (mult:SI (match_operand:SI 1 "register_operand" "r") 2940 (match_operand:SI 2 "register_operand" "r"))))] 2941 "" 2942 "mul\\t%w0, %w1, %w2" 2943 [(set_attr "type" "mul")] 2944) 2945 2946(define_insn "madd<mode>" 2947 [(set (match_operand:GPI 0 "register_operand" "=r") 2948 (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2949 (match_operand:GPI 2 "register_operand" "r")) 2950 (match_operand:GPI 3 "register_operand" "r")))] 2951 "" 2952 "madd\\t%<w>0, %<w>1, %<w>2, %<w>3" 2953 [(set_attr "type" "mla")] 2954) 2955 2956;; zero_extend version of above 2957(define_insn "*maddsi_uxtw" 2958 [(set (match_operand:DI 0 "register_operand" "=r") 2959 (zero_extend:DI 2960 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r") 2961 (match_operand:SI 2 "register_operand" "r")) 2962 (match_operand:SI 3 "register_operand" "r"))))] 2963 "" 2964 "madd\\t%w0, %w1, %w2, %w3" 2965 [(set_attr "type" "mla")] 2966) 2967 2968(define_insn "*msub<mode>" 2969 [(set (match_operand:GPI 0 "register_operand" "=r") 2970 (minus:GPI (match_operand:GPI 3 "register_operand" "r") 2971 (mult:GPI (match_operand:GPI 1 "register_operand" "r") 2972 (match_operand:GPI 2 "register_operand" "r"))))] 2973 2974 "" 2975 "msub\\t%<w>0, %<w>1, %<w>2, %<w>3" 2976 [(set_attr "type" "mla")] 2977) 2978 2979;; zero_extend version of above 2980(define_insn "*msubsi_uxtw" 2981 [(set (match_operand:DI 0 "register_operand" "=r") 2982 (zero_extend:DI 2983 (minus:SI (match_operand:SI 3 "register_operand" "r") 2984 (mult:SI (match_operand:SI 1 "register_operand" "r") 2985 (match_operand:SI 2 "register_operand" "r")))))] 2986 2987 "" 2988 "msub\\t%w0, %w1, %w2, %w3" 2989 [(set_attr "type" "mla")] 2990) 2991 2992(define_insn "*mul<mode>_neg" 2993 [(set (match_operand:GPI 0 "register_operand" "=r") 2994 (mult:GPI (neg:GPI (match_operand:GPI 1 "register_operand" "r")) 2995 (match_operand:GPI 2 "register_operand" "r")))] 2996 2997 "" 2998 "mneg\\t%<w>0, %<w>1, %<w>2" 2999 [(set_attr "type" "mul")] 3000) 3001 3002;; zero_extend version of above 3003(define_insn "*mulsi_neg_uxtw" 3004 [(set (match_operand:DI 0 "register_operand" "=r") 3005 (zero_extend:DI 3006 (mult:SI (neg:SI (match_operand:SI 1 "register_operand" "r")) 3007 (match_operand:SI 2 "register_operand" "r"))))] 3008 3009 "" 3010 "mneg\\t%w0, %w1, %w2" 3011 [(set_attr "type" "mul")] 3012) 3013 3014(define_insn "<su_optab>mulsidi3" 3015 [(set (match_operand:DI 0 "register_operand" "=r") 3016 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")) 3017 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))] 3018 "" 3019 "<su>mull\\t%0, %w1, %w2" 3020 [(set_attr "type" "<su>mull")] 3021) 3022 3023(define_insn "<su_optab>maddsidi4" 3024 [(set (match_operand:DI 0 "register_operand" "=r") 3025 (plus:DI (mult:DI 3026 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")) 3027 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))) 3028 (match_operand:DI 3 "register_operand" "r")))] 3029 "" 3030 "<su>maddl\\t%0, %w1, %w2, %3" 3031 [(set_attr "type" "<su>mlal")] 3032) 3033 3034(define_insn "<su_optab>msubsidi4" 3035 [(set (match_operand:DI 0 "register_operand" "=r") 3036 (minus:DI 3037 (match_operand:DI 3 "register_operand" "r") 3038 (mult:DI (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r")) 3039 (ANY_EXTEND:DI 3040 (match_operand:SI 2 "register_operand" "r")))))] 3041 "" 3042 "<su>msubl\\t%0, %w1, %w2, %3" 3043 [(set_attr "type" "<su>mlal")] 3044) 3045 3046(define_insn "*<su_optab>mulsidi_neg" 3047 [(set (match_operand:DI 0 "register_operand" "=r") 3048 (mult:DI (neg:DI 3049 (ANY_EXTEND:DI (match_operand:SI 1 "register_operand" "r"))) 3050 (ANY_EXTEND:DI (match_operand:SI 2 "register_operand" "r"))))] 3051 "" 3052 "<su>mnegl\\t%0, %w1, %w2" 3053 [(set_attr "type" "<su>mull")] 3054) 3055 3056(define_expand "<su_optab>mulditi3" 3057 [(set (match_operand:TI 0 "register_operand") 3058 (mult:TI (ANY_EXTEND:TI (match_operand:DI 1 "register_operand")) 3059 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand"))))] 3060 "" 3061{ 3062 rtx low = gen_reg_rtx (DImode); 3063 emit_insn (gen_muldi3 (low, operands[1], operands[2])); 3064 3065 rtx high = gen_reg_rtx (DImode); 3066 emit_insn (gen_<su>muldi3_highpart (high, operands[1], operands[2])); 3067 3068 emit_move_insn (gen_lowpart (DImode, operands[0]), low); 3069 emit_move_insn (gen_highpart (DImode, operands[0]), high); 3070 DONE; 3071}) 3072 3073;; The default expansion of multi3 using umuldi3_highpart will perform 3074;; the additions in an order that fails to combine into two madd insns. 3075(define_expand "multi3" 3076 [(set (match_operand:TI 0 "register_operand") 3077 (mult:TI (match_operand:TI 1 "register_operand") 3078 (match_operand:TI 2 "register_operand")))] 3079 "" 3080{ 3081 rtx l0 = gen_reg_rtx (DImode); 3082 rtx l1 = gen_lowpart (DImode, operands[1]); 3083 rtx l2 = gen_lowpart (DImode, operands[2]); 3084 rtx h0 = gen_reg_rtx (DImode); 3085 rtx h1 = gen_highpart (DImode, operands[1]); 3086 rtx h2 = gen_highpart (DImode, operands[2]); 3087 3088 emit_insn (gen_muldi3 (l0, l1, l2)); 3089 emit_insn (gen_umuldi3_highpart (h0, l1, l2)); 3090 emit_insn (gen_madddi (h0, h1, l2, h0)); 3091 emit_insn (gen_madddi (h0, l1, h2, h0)); 3092 3093 emit_move_insn (gen_lowpart (DImode, operands[0]), l0); 3094 emit_move_insn (gen_highpart (DImode, operands[0]), h0); 3095 DONE; 3096}) 3097 3098(define_insn "<su>muldi3_highpart" 3099 [(set (match_operand:DI 0 "register_operand" "=r") 3100 (truncate:DI 3101 (lshiftrt:TI 3102 (mult:TI 3103 (ANY_EXTEND:TI (match_operand:DI 1 "register_operand" "r")) 3104 (ANY_EXTEND:TI (match_operand:DI 2 "register_operand" "r"))) 3105 (const_int 64))))] 3106 "" 3107 "<su>mulh\\t%0, %1, %2" 3108 [(set_attr "type" "<su>mull")] 3109) 3110 3111(define_insn "<su_optab>div<mode>3" 3112 [(set (match_operand:GPI 0 "register_operand" "=r") 3113 (ANY_DIV:GPI (match_operand:GPI 1 "register_operand" "r") 3114 (match_operand:GPI 2 "register_operand" "r")))] 3115 "" 3116 "<su>div\\t%<w>0, %<w>1, %<w>2" 3117 [(set_attr "type" "<su>div")] 3118) 3119 3120;; zero_extend version of above 3121(define_insn "*<su_optab>divsi3_uxtw" 3122 [(set (match_operand:DI 0 "register_operand" "=r") 3123 (zero_extend:DI 3124 (ANY_DIV:SI (match_operand:SI 1 "register_operand" "r") 3125 (match_operand:SI 2 "register_operand" "r"))))] 3126 "" 3127 "<su>div\\t%w0, %w1, %w2" 3128 [(set_attr "type" "<su>div")] 3129) 3130 3131;; ------------------------------------------------------------------- 3132;; Comparison insns 3133;; ------------------------------------------------------------------- 3134 3135(define_insn "cmp<mode>" 3136 [(set (reg:CC CC_REGNUM) 3137 (compare:CC (match_operand:GPI 0 "register_operand" "r,r,r") 3138 (match_operand:GPI 1 "aarch64_plus_operand" "r,I,J")))] 3139 "" 3140 "@ 3141 cmp\\t%<w>0, %<w>1 3142 cmp\\t%<w>0, %1 3143 cmn\\t%<w>0, #%n1" 3144 [(set_attr "type" "alus_sreg,alus_imm,alus_imm")] 3145) 3146 3147(define_insn "fcmp<mode>" 3148 [(set (reg:CCFP CC_REGNUM) 3149 (compare:CCFP (match_operand:GPF 0 "register_operand" "w,w") 3150 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))] 3151 "TARGET_FLOAT" 3152 "@ 3153 fcmp\\t%<s>0, #0.0 3154 fcmp\\t%<s>0, %<s>1" 3155 [(set_attr "type" "fcmp<s>")] 3156) 3157 3158(define_insn "fcmpe<mode>" 3159 [(set (reg:CCFPE CC_REGNUM) 3160 (compare:CCFPE (match_operand:GPF 0 "register_operand" "w,w") 3161 (match_operand:GPF 1 "aarch64_fp_compare_operand" "Y,w")))] 3162 "TARGET_FLOAT" 3163 "@ 3164 fcmpe\\t%<s>0, #0.0 3165 fcmpe\\t%<s>0, %<s>1" 3166 [(set_attr "type" "fcmp<s>")] 3167) 3168 3169(define_insn "*cmp_swp_<shift>_reg<mode>" 3170 [(set (reg:CC_SWP CC_REGNUM) 3171 (compare:CC_SWP (ASHIFT:GPI 3172 (match_operand:GPI 0 "register_operand" "r") 3173 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")) 3174 (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")))] 3175 "" 3176 "cmp\\t%<w>2, %<w>0, <shift> %1" 3177 [(set_attr "type" "alus_shift_imm")] 3178) 3179 3180(define_insn "*cmp_swp_<optab><ALLX:mode>_reg<GPI:mode>" 3181 [(set (reg:CC_SWP CC_REGNUM) 3182 (compare:CC_SWP (ANY_EXTEND:GPI 3183 (match_operand:ALLX 0 "register_operand" "r")) 3184 (match_operand:GPI 1 "register_operand" "r")))] 3185 "" 3186 "cmp\\t%<GPI:w>1, %<GPI:w>0, <su>xt<ALLX:size>" 3187 [(set_attr "type" "alus_ext")] 3188) 3189 3190(define_insn "*cmp_swp_<optab><ALLX:mode>_shft_<GPI:mode>" 3191 [(set (reg:CC_SWP CC_REGNUM) 3192 (compare:CC_SWP (ashift:GPI 3193 (ANY_EXTEND:GPI 3194 (match_operand:ALLX 0 "register_operand" "r")) 3195 (match_operand 1 "aarch64_imm3" "Ui3")) 3196 (match_operand:GPI 2 "register_operand" "r")))] 3197 "" 3198 "cmp\\t%<GPI:w>2, %<GPI:w>0, <su>xt<ALLX:size> %1" 3199 [(set_attr "type" "alus_ext")] 3200) 3201 3202;; ------------------------------------------------------------------- 3203;; Store-flag and conditional select insns 3204;; ------------------------------------------------------------------- 3205 3206(define_expand "cstore<mode>4" 3207 [(set (match_operand:SI 0 "register_operand" "") 3208 (match_operator:SI 1 "aarch64_comparison_operator" 3209 [(match_operand:GPI 2 "register_operand" "") 3210 (match_operand:GPI 3 "aarch64_plus_operand" "")]))] 3211 "" 3212 " 3213 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2], 3214 operands[3]); 3215 operands[3] = const0_rtx; 3216 " 3217) 3218 3219(define_expand "cstorecc4" 3220 [(set (match_operand:SI 0 "register_operand") 3221 (match_operator 1 "aarch64_comparison_operator_mode" 3222 [(match_operand 2 "cc_register") 3223 (match_operand 3 "const0_operand")]))] 3224 "" 3225"{ 3226 emit_insn (gen_rtx_SET (operands[0], operands[1])); 3227 DONE; 3228}") 3229 3230 3231(define_expand "cstore<mode>4" 3232 [(set (match_operand:SI 0 "register_operand" "") 3233 (match_operator:SI 1 "aarch64_comparison_operator_mode" 3234 [(match_operand:GPF 2 "register_operand" "") 3235 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]))] 3236 "" 3237 " 3238 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2], 3239 operands[3]); 3240 operands[3] = const0_rtx; 3241 " 3242) 3243 3244(define_insn "aarch64_cstore<mode>" 3245 [(set (match_operand:ALLI 0 "register_operand" "=r") 3246 (match_operator:ALLI 1 "aarch64_comparison_operator_mode" 3247 [(match_operand 2 "cc_register" "") (const_int 0)]))] 3248 "" 3249 "cset\\t%<w>0, %m1" 3250 [(set_attr "type" "csel")] 3251) 3252 3253;; For a 24-bit immediate CST we can optimize the compare for equality 3254;; and branch sequence from: 3255;; mov x0, #imm1 3256;; movk x0, #imm2, lsl 16 /* x0 contains CST. */ 3257;; cmp x1, x0 3258;; cset x2, <ne,eq> 3259;; into the shorter: 3260;; sub x0, x1, #(CST & 0xfff000) 3261;; subs x0, x0, #(CST & 0x000fff) 3262;; cset x2, <ne, eq>. 3263(define_insn_and_split "*compare_cstore<mode>_insn" 3264 [(set (match_operand:GPI 0 "register_operand" "=r") 3265 (EQL:GPI (match_operand:GPI 1 "register_operand" "r") 3266 (match_operand:GPI 2 "aarch64_imm24" "n"))) 3267 (clobber (reg:CC CC_REGNUM))] 3268 "!aarch64_move_imm (INTVAL (operands[2]), <MODE>mode) 3269 && !aarch64_plus_operand (operands[2], <MODE>mode) 3270 && !reload_completed" 3271 "#" 3272 "&& true" 3273 [(const_int 0)] 3274 { 3275 HOST_WIDE_INT lo_imm = UINTVAL (operands[2]) & 0xfff; 3276 HOST_WIDE_INT hi_imm = UINTVAL (operands[2]) & 0xfff000; 3277 rtx tmp = gen_reg_rtx (<MODE>mode); 3278 emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (-hi_imm))); 3279 emit_insn (gen_add<mode>3_compare0 (tmp, tmp, GEN_INT (-lo_imm))); 3280 rtx cc_reg = gen_rtx_REG (CC_NZmode, CC_REGNUM); 3281 rtx cmp_rtx = gen_rtx_fmt_ee (<EQL:CMP>, <MODE>mode, cc_reg, const0_rtx); 3282 emit_insn (gen_aarch64_cstore<mode> (operands[0], cmp_rtx, cc_reg)); 3283 DONE; 3284 } 3285 [(set_attr "type" "csel")] 3286) 3287 3288;; zero_extend version of the above 3289(define_insn "*cstoresi_insn_uxtw" 3290 [(set (match_operand:DI 0 "register_operand" "=r") 3291 (zero_extend:DI 3292 (match_operator:SI 1 "aarch64_comparison_operator_mode" 3293 [(match_operand 2 "cc_register" "") (const_int 0)])))] 3294 "" 3295 "cset\\t%w0, %m1" 3296 [(set_attr "type" "csel")] 3297) 3298 3299(define_insn "cstore<mode>_neg" 3300 [(set (match_operand:ALLI 0 "register_operand" "=r") 3301 (neg:ALLI (match_operator:ALLI 1 "aarch64_comparison_operator_mode" 3302 [(match_operand 2 "cc_register" "") (const_int 0)])))] 3303 "" 3304 "csetm\\t%<w>0, %m1" 3305 [(set_attr "type" "csel")] 3306) 3307 3308;; zero_extend version of the above 3309(define_insn "*cstoresi_neg_uxtw" 3310 [(set (match_operand:DI 0 "register_operand" "=r") 3311 (zero_extend:DI 3312 (neg:SI (match_operator:SI 1 "aarch64_comparison_operator_mode" 3313 [(match_operand 2 "cc_register" "") (const_int 0)]))))] 3314 "" 3315 "csetm\\t%w0, %m1" 3316 [(set_attr "type" "csel")] 3317) 3318 3319(define_expand "cmov<mode>6" 3320 [(set (match_operand:GPI 0 "register_operand" "") 3321 (if_then_else:GPI 3322 (match_operator 1 "aarch64_comparison_operator" 3323 [(match_operand:GPI 2 "register_operand" "") 3324 (match_operand:GPI 3 "aarch64_plus_operand" "")]) 3325 (match_operand:GPI 4 "register_operand" "") 3326 (match_operand:GPI 5 "register_operand" "")))] 3327 "" 3328 " 3329 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2], 3330 operands[3]); 3331 operands[3] = const0_rtx; 3332 " 3333) 3334 3335(define_expand "cmov<mode>6" 3336 [(set (match_operand:GPF 0 "register_operand" "") 3337 (if_then_else:GPF 3338 (match_operator 1 "aarch64_comparison_operator" 3339 [(match_operand:GPF 2 "register_operand" "") 3340 (match_operand:GPF 3 "aarch64_fp_compare_operand" "")]) 3341 (match_operand:GPF 4 "register_operand" "") 3342 (match_operand:GPF 5 "register_operand" "")))] 3343 "" 3344 " 3345 operands[2] = aarch64_gen_compare_reg (GET_CODE (operands[1]), operands[2], 3346 operands[3]); 3347 operands[3] = const0_rtx; 3348 " 3349) 3350 3351(define_insn "*cmov<mode>_insn" 3352 [(set (match_operand:ALLI 0 "register_operand" "=r,r,r,r,r,r,r") 3353 (if_then_else:ALLI 3354 (match_operator 1 "aarch64_comparison_operator" 3355 [(match_operand 2 "cc_register" "") (const_int 0)]) 3356 (match_operand:ALLI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1") 3357 (match_operand:ALLI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1")))] 3358 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx) 3359 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))" 3360 ;; Final two alternatives should be unreachable, but included for completeness 3361 "@ 3362 csel\\t%<w>0, %<w>3, %<w>4, %m1 3363 csinv\\t%<w>0, %<w>3, <w>zr, %m1 3364 csinv\\t%<w>0, %<w>4, <w>zr, %M1 3365 csinc\\t%<w>0, %<w>3, <w>zr, %m1 3366 csinc\\t%<w>0, %<w>4, <w>zr, %M1 3367 mov\\t%<w>0, -1 3368 mov\\t%<w>0, 1" 3369 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")] 3370) 3371 3372;; zero_extend version of above 3373(define_insn "*cmovsi_insn_uxtw" 3374 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r,r") 3375 (zero_extend:DI 3376 (if_then_else:SI 3377 (match_operator 1 "aarch64_comparison_operator" 3378 [(match_operand 2 "cc_register" "") (const_int 0)]) 3379 (match_operand:SI 3 "aarch64_reg_zero_or_m1_or_1" "rZ,rZ,UsM,rZ,Ui1,UsM,Ui1") 3380 (match_operand:SI 4 "aarch64_reg_zero_or_m1_or_1" "rZ,UsM,rZ,Ui1,rZ,UsM,Ui1"))))] 3381 "!((operands[3] == const1_rtx && operands[4] == constm1_rtx) 3382 || (operands[3] == constm1_rtx && operands[4] == const1_rtx))" 3383 ;; Final two alternatives should be unreachable, but included for completeness 3384 "@ 3385 csel\\t%w0, %w3, %w4, %m1 3386 csinv\\t%w0, %w3, wzr, %m1 3387 csinv\\t%w0, %w4, wzr, %M1 3388 csinc\\t%w0, %w3, wzr, %m1 3389 csinc\\t%w0, %w4, wzr, %M1 3390 mov\\t%w0, -1 3391 mov\\t%w0, 1" 3392 [(set_attr "type" "csel, csel, csel, csel, csel, mov_imm, mov_imm")] 3393) 3394 3395(define_insn "*cmovdi_insn_uxtw" 3396 [(set (match_operand:DI 0 "register_operand" "=r") 3397 (if_then_else:DI 3398 (match_operator 1 "aarch64_comparison_operator" 3399 [(match_operand 2 "cc_register" "") (const_int 0)]) 3400 (zero_extend:DI (match_operand:SI 3 "register_operand" "r")) 3401 (zero_extend:DI (match_operand:SI 4 "register_operand" "r"))))] 3402 "" 3403 "csel\\t%w0, %w3, %w4, %m1" 3404 [(set_attr "type" "csel")] 3405) 3406 3407(define_insn "*cmov<mode>_insn" 3408 [(set (match_operand:GPF 0 "register_operand" "=w") 3409 (if_then_else:GPF 3410 (match_operator 1 "aarch64_comparison_operator" 3411 [(match_operand 2 "cc_register" "") (const_int 0)]) 3412 (match_operand:GPF 3 "register_operand" "w") 3413 (match_operand:GPF 4 "register_operand" "w")))] 3414 "TARGET_FLOAT" 3415 "fcsel\\t%<s>0, %<s>3, %<s>4, %m1" 3416 [(set_attr "type" "fcsel")] 3417) 3418 3419(define_expand "mov<mode>cc" 3420 [(set (match_operand:ALLI 0 "register_operand" "") 3421 (if_then_else:ALLI (match_operand 1 "aarch64_comparison_operator" "") 3422 (match_operand:ALLI 2 "register_operand" "") 3423 (match_operand:ALLI 3 "register_operand" "")))] 3424 "" 3425 { 3426 rtx ccreg; 3427 enum rtx_code code = GET_CODE (operands[1]); 3428 3429 if (code == UNEQ || code == LTGT) 3430 FAIL; 3431 3432 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0), 3433 XEXP (operands[1], 1)); 3434 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); 3435 } 3436) 3437 3438(define_expand "mov<GPF:mode><GPI:mode>cc" 3439 [(set (match_operand:GPI 0 "register_operand" "") 3440 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "") 3441 (match_operand:GPF 2 "register_operand" "") 3442 (match_operand:GPF 3 "register_operand" "")))] 3443 "" 3444 { 3445 rtx ccreg; 3446 enum rtx_code code = GET_CODE (operands[1]); 3447 3448 if (code == UNEQ || code == LTGT) 3449 FAIL; 3450 3451 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0), 3452 XEXP (operands[1], 1)); 3453 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); 3454 } 3455) 3456 3457(define_expand "mov<mode>cc" 3458 [(set (match_operand:GPF 0 "register_operand" "") 3459 (if_then_else:GPF (match_operand 1 "aarch64_comparison_operator" "") 3460 (match_operand:GPF 2 "register_operand" "") 3461 (match_operand:GPF 3 "register_operand" "")))] 3462 "" 3463 { 3464 rtx ccreg; 3465 enum rtx_code code = GET_CODE (operands[1]); 3466 3467 if (code == UNEQ || code == LTGT) 3468 FAIL; 3469 3470 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0), 3471 XEXP (operands[1], 1)); 3472 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); 3473 } 3474) 3475 3476(define_expand "<neg_not_op><mode>cc" 3477 [(set (match_operand:GPI 0 "register_operand" "") 3478 (if_then_else:GPI (match_operand 1 "aarch64_comparison_operator" "") 3479 (NEG_NOT:GPI (match_operand:GPI 2 "register_operand" "")) 3480 (match_operand:GPI 3 "register_operand" "")))] 3481 "" 3482 { 3483 rtx ccreg; 3484 enum rtx_code code = GET_CODE (operands[1]); 3485 3486 if (code == UNEQ || code == LTGT) 3487 FAIL; 3488 3489 ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0), 3490 XEXP (operands[1], 1)); 3491 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx); 3492 } 3493) 3494 3495;; CRC32 instructions. 3496(define_insn "aarch64_<crc_variant>" 3497 [(set (match_operand:SI 0 "register_operand" "=r") 3498 (unspec:SI [(match_operand:SI 1 "register_operand" "r") 3499 (match_operand:<crc_mode> 2 "register_operand" "r")] 3500 CRC))] 3501 "TARGET_CRC32" 3502 { 3503 if (GET_MODE_BITSIZE (<crc_mode>mode) >= 64) 3504 return "<crc_variant>\\t%w0, %w1, %x2"; 3505 else 3506 return "<crc_variant>\\t%w0, %w1, %w2"; 3507 } 3508 [(set_attr "type" "crc")] 3509) 3510 3511(define_insn "*csinc2<mode>_insn" 3512 [(set (match_operand:GPI 0 "register_operand" "=r") 3513 (plus:GPI (match_operand 2 "aarch64_comparison_operation" "") 3514 (match_operand:GPI 1 "register_operand" "r")))] 3515 "" 3516 "cinc\\t%<w>0, %<w>1, %m2" 3517 [(set_attr "type" "csel")] 3518) 3519 3520(define_insn "csinc3<mode>_insn" 3521 [(set (match_operand:GPI 0 "register_operand" "=r") 3522 (if_then_else:GPI 3523 (match_operand 1 "aarch64_comparison_operation" "") 3524 (plus:GPI (match_operand:GPI 2 "register_operand" "r") 3525 (const_int 1)) 3526 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))] 3527 "" 3528 "csinc\\t%<w>0, %<w>3, %<w>2, %M1" 3529 [(set_attr "type" "csel")] 3530) 3531 3532(define_insn "*csinv3<mode>_insn" 3533 [(set (match_operand:GPI 0 "register_operand" "=r") 3534 (if_then_else:GPI 3535 (match_operand 1 "aarch64_comparison_operation" "") 3536 (not:GPI (match_operand:GPI 2 "register_operand" "r")) 3537 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))] 3538 "" 3539 "csinv\\t%<w>0, %<w>3, %<w>2, %M1" 3540 [(set_attr "type" "csel")] 3541) 3542 3543(define_insn "csneg3_uxtw_insn" 3544 [(set (match_operand:DI 0 "register_operand" "=r") 3545 (zero_extend:DI 3546 (if_then_else:SI 3547 (match_operand 1 "aarch64_comparison_operation" "") 3548 (neg:SI (match_operand:SI 2 "register_operand" "r")) 3549 (match_operand:SI 3 "aarch64_reg_or_zero" "rZ"))))] 3550 "" 3551 "csneg\\t%w0, %w3, %w2, %M1" 3552 [(set_attr "type" "csel")] 3553) 3554 3555(define_insn "csneg3<mode>_insn" 3556 [(set (match_operand:GPI 0 "register_operand" "=r") 3557 (if_then_else:GPI 3558 (match_operand 1 "aarch64_comparison_operation" "") 3559 (neg:GPI (match_operand:GPI 2 "register_operand" "r")) 3560 (match_operand:GPI 3 "aarch64_reg_or_zero" "rZ")))] 3561 "" 3562 "csneg\\t%<w>0, %<w>3, %<w>2, %M1" 3563 [(set_attr "type" "csel")] 3564) 3565 3566;; If X can be loaded by a single CNT[BHWD] instruction, 3567;; 3568;; A = UMAX (B, X) 3569;; 3570;; is equivalent to: 3571;; 3572;; TMP = UQDEC[BHWD] (B, X) 3573;; A = TMP + X 3574;; 3575;; Defining the pattern this way means that: 3576;; 3577;; A = UMAX (B, X) - X 3578;; 3579;; becomes: 3580;; 3581;; TMP1 = UQDEC[BHWD] (B, X) 3582;; TMP2 = TMP1 + X 3583;; A = TMP2 - X 3584;; 3585;; which combine can optimize to: 3586;; 3587;; A = UQDEC[BHWD] (B, X) 3588;; 3589;; We don't use match_operand predicates because the order of the operands 3590;; can vary: the CNT[BHWD] constant will come first if the other operand is 3591;; a simpler constant (such as a CONST_INT), otherwise it will come second. 3592(define_expand "umax<mode>3" 3593 [(set (match_operand:GPI 0 "register_operand") 3594 (umax:GPI (match_operand:GPI 1 "") 3595 (match_operand:GPI 2 "")))] 3596 "TARGET_SVE" 3597 { 3598 if (aarch64_sve_cnt_immediate (operands[1], <MODE>mode)) 3599 std::swap (operands[1], operands[2]); 3600 else if (!aarch64_sve_cnt_immediate (operands[2], <MODE>mode)) 3601 FAIL; 3602 rtx temp = gen_reg_rtx (<MODE>mode); 3603 operands[1] = force_reg (<MODE>mode, operands[1]); 3604 emit_insn (gen_aarch64_uqdec<mode> (temp, operands[1], operands[2])); 3605 emit_insn (gen_add<mode>3 (operands[0], temp, operands[2])); 3606 DONE; 3607 } 3608) 3609 3610;; Saturating unsigned subtraction of a CNT[BHWD] immediate. 3611(define_insn "aarch64_uqdec<mode>" 3612 [(set (match_operand:GPI 0 "register_operand" "=r") 3613 (minus:GPI 3614 (umax:GPI (match_operand:GPI 1 "register_operand" "0") 3615 (match_operand:GPI 2 "aarch64_sve_cnt_immediate" "Usv")) 3616 (match_dup 2)))] 3617 "TARGET_SVE" 3618 { 3619 return aarch64_output_sve_cnt_immediate ("uqdec", "%<w>0", operands[2]); 3620 } 3621) 3622 3623;; ------------------------------------------------------------------- 3624;; Logical operations 3625;; ------------------------------------------------------------------- 3626 3627 3628(define_insn_and_split "*aarch64_and<mode>_imm2" 3629 [(set (match_operand:GPI 0 "register_operand" "=rk") 3630 (and:GPI (match_operand:GPI 1 "register_operand" "%r") 3631 (match_operand:GPI 2 "aarch64_logical_and_immediate" "<lconst2>")))] 3632 "" 3633 "#" 3634 "true" 3635 [(const_int 0)] 3636 { 3637 HOST_WIDE_INT val = INTVAL (operands[2]); 3638 rtx imm1 = GEN_INT (aarch64_and_split_imm1 (val)); 3639 rtx imm2 = GEN_INT (aarch64_and_split_imm2 (val)); 3640 3641 emit_insn (gen_and<mode>3 (operands[0], operands[1], imm1)); 3642 emit_insn (gen_and<mode>3 (operands[0], operands[0], imm2)); 3643 DONE; 3644 } 3645) 3646 3647(define_insn "<optab><mode>3" 3648 [(set (match_operand:GPI 0 "register_operand" "=r,rk,w") 3649 (LOGICAL:GPI (match_operand:GPI 1 "register_operand" "%r,r,w") 3650 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>,w")))] 3651 "" 3652 "@ 3653 <logical>\\t%<w>0, %<w>1, %<w>2 3654 <logical>\\t%<w>0, %<w>1, %2 3655 <logical>\\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>" 3656 [(set_attr "type" "logic_reg,logic_imm,neon_logic") 3657 (set_attr "simd" "*,*,yes")] 3658) 3659 3660;; zero_extend version of above 3661(define_insn "*<optab>si3_uxtw" 3662 [(set (match_operand:DI 0 "register_operand" "=r,rk") 3663 (zero_extend:DI 3664 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r") 3665 (match_operand:SI 2 "aarch64_logical_operand" "r,K"))))] 3666 "" 3667 "@ 3668 <logical>\\t%w0, %w1, %w2 3669 <logical>\\t%w0, %w1, %2" 3670 [(set_attr "type" "logic_reg,logic_imm")] 3671) 3672 3673(define_insn "*and<mode>3_compare0" 3674 [(set (reg:CC_NZ CC_REGNUM) 3675 (compare:CC_NZ 3676 (and:GPI (match_operand:GPI 1 "register_operand" "%r,r") 3677 (match_operand:GPI 2 "aarch64_logical_operand" "r,<lconst>")) 3678 (const_int 0))) 3679 (set (match_operand:GPI 0 "register_operand" "=r,r") 3680 (and:GPI (match_dup 1) (match_dup 2)))] 3681 "" 3682 "@ 3683 ands\\t%<w>0, %<w>1, %<w>2 3684 ands\\t%<w>0, %<w>1, %2" 3685 [(set_attr "type" "logics_reg,logics_imm")] 3686) 3687 3688;; zero_extend version of above 3689(define_insn "*andsi3_compare0_uxtw" 3690 [(set (reg:CC_NZ CC_REGNUM) 3691 (compare:CC_NZ 3692 (and:SI (match_operand:SI 1 "register_operand" "%r,r") 3693 (match_operand:SI 2 "aarch64_logical_operand" "r,K")) 3694 (const_int 0))) 3695 (set (match_operand:DI 0 "register_operand" "=r,r") 3696 (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))] 3697 "" 3698 "@ 3699 ands\\t%w0, %w1, %w2 3700 ands\\t%w0, %w1, %2" 3701 [(set_attr "type" "logics_reg,logics_imm")] 3702) 3703 3704(define_insn "*and_<SHIFT:optab><mode>3_compare0" 3705 [(set (reg:CC_NZ CC_REGNUM) 3706 (compare:CC_NZ 3707 (and:GPI (SHIFT:GPI 3708 (match_operand:GPI 1 "register_operand" "r") 3709 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")) 3710 (match_operand:GPI 3 "register_operand" "r")) 3711 (const_int 0))) 3712 (set (match_operand:GPI 0 "register_operand" "=r") 3713 (and:GPI (SHIFT:GPI (match_dup 1) (match_dup 2)) (match_dup 3)))] 3714 "" 3715 "ands\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2" 3716 [(set_attr "type" "logics_shift_imm")] 3717) 3718 3719;; zero_extend version of above 3720(define_insn "*and_<SHIFT:optab>si3_compare0_uxtw" 3721 [(set (reg:CC_NZ CC_REGNUM) 3722 (compare:CC_NZ 3723 (and:SI (SHIFT:SI 3724 (match_operand:SI 1 "register_operand" "r") 3725 (match_operand:QI 2 "aarch64_shift_imm_si" "n")) 3726 (match_operand:SI 3 "register_operand" "r")) 3727 (const_int 0))) 3728 (set (match_operand:DI 0 "register_operand" "=r") 3729 (zero_extend:DI (and:SI (SHIFT:SI (match_dup 1) (match_dup 2)) 3730 (match_dup 3))))] 3731 "" 3732 "ands\\t%w0, %w3, %w1, <SHIFT:shift> %2" 3733 [(set_attr "type" "logics_shift_imm")] 3734) 3735 3736(define_insn "*<LOGICAL:optab>_<SHIFT:optab><mode>3" 3737 [(set (match_operand:GPI 0 "register_operand" "=r") 3738 (LOGICAL:GPI (SHIFT:GPI 3739 (match_operand:GPI 1 "register_operand" "r") 3740 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")) 3741 (match_operand:GPI 3 "register_operand" "r")))] 3742 "" 3743 "<LOGICAL:logical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2" 3744 [(set_attr "type" "logic_shift_imm")] 3745) 3746 3747(define_insn "*<optab>_rol<mode>3" 3748 [(set (match_operand:GPI 0 "register_operand" "=r") 3749 (LOGICAL:GPI (rotate:GPI 3750 (match_operand:GPI 1 "register_operand" "r") 3751 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")) 3752 (match_operand:GPI 3 "register_operand" "r")))] 3753 "" 3754 "<logical>\\t%<w>0, %<w>3, %<w>1, ror (<sizen> - %2)" 3755 [(set_attr "type" "logic_shift_imm")] 3756) 3757 3758;; zero_extend versions of above 3759(define_insn "*<LOGICAL:optab>_<SHIFT:optab>si3_uxtw" 3760 [(set (match_operand:DI 0 "register_operand" "=r") 3761 (zero_extend:DI 3762 (LOGICAL:SI (SHIFT:SI 3763 (match_operand:SI 1 "register_operand" "r") 3764 (match_operand:QI 2 "aarch64_shift_imm_si" "n")) 3765 (match_operand:SI 3 "register_operand" "r"))))] 3766 "" 3767 "<LOGICAL:logical>\\t%w0, %w3, %w1, <SHIFT:shift> %2" 3768 [(set_attr "type" "logic_shift_imm")] 3769) 3770 3771(define_insn "*<optab>_rolsi3_uxtw" 3772 [(set (match_operand:DI 0 "register_operand" "=r") 3773 (zero_extend:DI 3774 (LOGICAL:SI (rotate:SI 3775 (match_operand:SI 1 "register_operand" "r") 3776 (match_operand:QI 2 "aarch64_shift_imm_si" "n")) 3777 (match_operand:SI 3 "register_operand" "r"))))] 3778 "" 3779 "<logical>\\t%w0, %w3, %w1, ror (32 - %2)" 3780 [(set_attr "type" "logic_shift_imm")] 3781) 3782 3783(define_insn "one_cmpl<mode>2" 3784 [(set (match_operand:GPI 0 "register_operand" "=r,w") 3785 (not:GPI (match_operand:GPI 1 "register_operand" "r,w")))] 3786 "" 3787 "@ 3788 mvn\\t%<w>0, %<w>1 3789 mvn\\t%0.8b, %1.8b" 3790 [(set_attr "type" "logic_reg,neon_logic") 3791 (set_attr "simd" "*,yes")] 3792) 3793 3794(define_insn "*one_cmpl_<optab><mode>2" 3795 [(set (match_operand:GPI 0 "register_operand" "=r") 3796 (not:GPI (SHIFT:GPI (match_operand:GPI 1 "register_operand" "r") 3797 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))))] 3798 "" 3799 "mvn\\t%<w>0, %<w>1, <shift> %2" 3800 [(set_attr "type" "logic_shift_imm")] 3801) 3802 3803;; Binary logical operators negating one operand, i.e. (a & !b), (a | !b). 3804 3805(define_insn "*<NLOGICAL:optab>_one_cmpl<mode>3" 3806 [(set (match_operand:GPI 0 "register_operand" "=r,w") 3807 (NLOGICAL:GPI (not:GPI (match_operand:GPI 1 "register_operand" "r,w")) 3808 (match_operand:GPI 2 "register_operand" "r,w")))] 3809 "" 3810 "@ 3811 <NLOGICAL:nlogical>\\t%<w>0, %<w>2, %<w>1 3812 <NLOGICAL:nlogical>\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype>" 3813 [(set_attr "type" "logic_reg,neon_logic") 3814 (set_attr "simd" "*,yes")] 3815) 3816 3817(define_insn "*<NLOGICAL:optab>_one_cmplsidi3_ze" 3818 [(set (match_operand:DI 0 "register_operand" "=r") 3819 (zero_extend:DI 3820 (NLOGICAL:SI (not:SI (match_operand:SI 1 "register_operand" "r")) 3821 (match_operand:SI 2 "register_operand" "r"))))] 3822 "" 3823 "<NLOGICAL:nlogical>\\t%w0, %w2, %w1" 3824 [(set_attr "type" "logic_reg")] 3825) 3826 3827(define_insn "*xor_one_cmplsidi3_ze" 3828 [(set (match_operand:DI 0 "register_operand" "=r") 3829 (zero_extend:DI 3830 (not:SI (xor:SI (match_operand:SI 1 "register_operand" "r") 3831 (match_operand:SI 2 "register_operand" "r")))))] 3832 "" 3833 "eon\\t%w0, %w1, %w2" 3834 [(set_attr "type" "logic_reg")] 3835) 3836 3837;; (xor (not a) b) is simplify_rtx-ed down to (not (xor a b)). 3838;; eon does not operate on SIMD registers so the vector variant must be split. 3839(define_insn_and_split "*xor_one_cmpl<mode>3" 3840 [(set (match_operand:GPI 0 "register_operand" "=r,w") 3841 (not:GPI (xor:GPI (match_operand:GPI 1 "register_operand" "r,?w") 3842 (match_operand:GPI 2 "register_operand" "r,w"))))] 3843 "" 3844 "@ 3845 eon\\t%<w>0, %<w>1, %<w>2 3846 #" 3847 "reload_completed && FP_REGNUM_P (REGNO (operands[0]))" ;; For SIMD registers. 3848 [(set (match_operand:GPI 0 "register_operand" "=w") 3849 (xor:GPI (match_operand:GPI 1 "register_operand" "w") 3850 (match_operand:GPI 2 "register_operand" "w"))) 3851 (set (match_dup 0) (not:GPI (match_dup 0)))] 3852 "" 3853 [(set_attr "type" "logic_reg,multiple") 3854 (set_attr "simd" "*,yes")] 3855) 3856 3857(define_insn "*and_one_cmpl<mode>3_compare0" 3858 [(set (reg:CC_NZ CC_REGNUM) 3859 (compare:CC_NZ 3860 (and:GPI (not:GPI 3861 (match_operand:GPI 1 "register_operand" "r")) 3862 (match_operand:GPI 2 "register_operand" "r")) 3863 (const_int 0))) 3864 (set (match_operand:GPI 0 "register_operand" "=r") 3865 (and:GPI (not:GPI (match_dup 1)) (match_dup 2)))] 3866 "" 3867 "bics\\t%<w>0, %<w>2, %<w>1" 3868 [(set_attr "type" "logics_reg")] 3869) 3870 3871;; zero_extend version of above 3872(define_insn "*and_one_cmplsi3_compare0_uxtw" 3873 [(set (reg:CC_NZ CC_REGNUM) 3874 (compare:CC_NZ 3875 (and:SI (not:SI 3876 (match_operand:SI 1 "register_operand" "r")) 3877 (match_operand:SI 2 "register_operand" "r")) 3878 (const_int 0))) 3879 (set (match_operand:DI 0 "register_operand" "=r") 3880 (zero_extend:DI (and:SI (not:SI (match_dup 1)) (match_dup 2))))] 3881 "" 3882 "bics\\t%w0, %w2, %w1" 3883 [(set_attr "type" "logics_reg")] 3884) 3885 3886(define_insn "*and_one_cmpl<mode>3_compare0_no_reuse" 3887 [(set (reg:CC_NZ CC_REGNUM) 3888 (compare:CC_NZ 3889 (and:GPI (not:GPI 3890 (match_operand:GPI 0 "register_operand" "r")) 3891 (match_operand:GPI 1 "register_operand" "r")) 3892 (const_int 0)))] 3893 "" 3894 "bics\\t<w>zr, %<w>1, %<w>0" 3895 [(set_attr "type" "logics_reg")] 3896) 3897 3898(define_insn "<LOGICAL:optab>_one_cmpl_<SHIFT:optab><mode>3" 3899 [(set (match_operand:GPI 0 "register_operand" "=r") 3900 (LOGICAL:GPI (not:GPI 3901 (SHIFT:GPI 3902 (match_operand:GPI 1 "register_operand" "r") 3903 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))) 3904 (match_operand:GPI 3 "register_operand" "r")))] 3905 "" 3906 "<LOGICAL:nlogical>\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2" 3907 [(set_attr "type" "logic_shift_imm")] 3908) 3909 3910(define_insn "*eor_one_cmpl_<SHIFT:optab><mode>3_alt" 3911 [(set (match_operand:GPI 0 "register_operand" "=r") 3912 (not:GPI (xor:GPI 3913 (SHIFT:GPI 3914 (match_operand:GPI 1 "register_operand" "r") 3915 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n")) 3916 (match_operand:GPI 3 "register_operand" "r"))))] 3917 "" 3918 "eon\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2" 3919 [(set_attr "type" "logic_shift_imm")] 3920) 3921 3922;; Zero-extend version of the above. 3923(define_insn "*eor_one_cmpl_<SHIFT:optab>sidi3_alt_ze" 3924 [(set (match_operand:DI 0 "register_operand" "=r") 3925 (zero_extend:DI 3926 (not:SI (xor:SI 3927 (SHIFT:SI 3928 (match_operand:SI 1 "register_operand" "r") 3929 (match_operand:QI 2 "aarch64_shift_imm_si" "n")) 3930 (match_operand:SI 3 "register_operand" "r")))))] 3931 "" 3932 "eon\\t%w0, %w3, %w1, <SHIFT:shift> %2" 3933 [(set_attr "type" "logic_shift_imm")] 3934) 3935 3936(define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0" 3937 [(set (reg:CC_NZ CC_REGNUM) 3938 (compare:CC_NZ 3939 (and:GPI (not:GPI 3940 (SHIFT:GPI 3941 (match_operand:GPI 1 "register_operand" "r") 3942 (match_operand:QI 2 "aarch64_shift_imm_<mode>" "n"))) 3943 (match_operand:GPI 3 "register_operand" "r")) 3944 (const_int 0))) 3945 (set (match_operand:GPI 0 "register_operand" "=r") 3946 (and:GPI (not:GPI 3947 (SHIFT:GPI 3948 (match_dup 1) (match_dup 2))) (match_dup 3)))] 3949 "" 3950 "bics\\t%<w>0, %<w>3, %<w>1, <SHIFT:shift> %2" 3951 [(set_attr "type" "logics_shift_imm")] 3952) 3953 3954;; zero_extend version of above 3955(define_insn "*and_one_cmpl_<SHIFT:optab>si3_compare0_uxtw" 3956 [(set (reg:CC_NZ CC_REGNUM) 3957 (compare:CC_NZ 3958 (and:SI (not:SI 3959 (SHIFT:SI 3960 (match_operand:SI 1 "register_operand" "r") 3961 (match_operand:QI 2 "aarch64_shift_imm_si" "n"))) 3962 (match_operand:SI 3 "register_operand" "r")) 3963 (const_int 0))) 3964 (set (match_operand:DI 0 "register_operand" "=r") 3965 (zero_extend:DI (and:SI 3966 (not:SI 3967 (SHIFT:SI (match_dup 1) (match_dup 2))) (match_dup 3))))] 3968 "" 3969 "bics\\t%w0, %w3, %w1, <SHIFT:shift> %2" 3970 [(set_attr "type" "logics_shift_imm")] 3971) 3972 3973(define_insn "*and_one_cmpl_<SHIFT:optab><mode>3_compare0_no_reuse" 3974 [(set (reg:CC_NZ CC_REGNUM) 3975 (compare:CC_NZ 3976 (and:GPI (not:GPI 3977 (SHIFT:GPI 3978 (match_operand:GPI 0 "register_operand" "r") 3979 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n"))) 3980 (match_operand:GPI 2 "register_operand" "r")) 3981 (const_int 0)))] 3982 "" 3983 "bics\\t<w>zr, %<w>2, %<w>0, <SHIFT:shift> %1" 3984 [(set_attr "type" "logics_shift_imm")] 3985) 3986 3987(define_insn "clz<mode>2" 3988 [(set (match_operand:GPI 0 "register_operand" "=r") 3989 (clz:GPI (match_operand:GPI 1 "register_operand" "r")))] 3990 "" 3991 "clz\\t%<w>0, %<w>1" 3992 [(set_attr "type" "clz")] 3993) 3994 3995(define_expand "ffs<mode>2" 3996 [(match_operand:GPI 0 "register_operand") 3997 (match_operand:GPI 1 "register_operand")] 3998 "" 3999 { 4000 rtx ccreg = aarch64_gen_compare_reg (EQ, operands[1], const0_rtx); 4001 rtx x = gen_rtx_NE (VOIDmode, ccreg, const0_rtx); 4002 4003 emit_insn (gen_rbit<mode>2 (operands[0], operands[1])); 4004 emit_insn (gen_clz<mode>2 (operands[0], operands[0])); 4005 emit_insn (gen_csinc3<mode>_insn (operands[0], x, operands[0], const0_rtx)); 4006 DONE; 4007 } 4008) 4009 4010;; Pop count be done via the "CNT" instruction in AdvSIMD. 4011;; 4012;; MOV v.1d, x0 4013;; CNT v1.8b, v.8b 4014;; ADDV b2, v1.8b 4015;; MOV w0, v2.b[0] 4016 4017(define_expand "popcount<mode>2" 4018 [(match_operand:GPI 0 "register_operand") 4019 (match_operand:GPI 1 "register_operand")] 4020 "TARGET_SIMD" 4021{ 4022 rtx v = gen_reg_rtx (V8QImode); 4023 rtx v1 = gen_reg_rtx (V8QImode); 4024 rtx r = gen_reg_rtx (QImode); 4025 rtx in = operands[1]; 4026 rtx out = operands[0]; 4027 if(<MODE>mode == SImode) 4028 { 4029 rtx tmp; 4030 tmp = gen_reg_rtx (DImode); 4031 /* If we have SImode, zero extend to DImode, pop count does 4032 not change if we have extra zeros. */ 4033 emit_insn (gen_zero_extendsidi2 (tmp, in)); 4034 in = tmp; 4035 } 4036 emit_move_insn (v, gen_lowpart (V8QImode, in)); 4037 emit_insn (gen_popcountv8qi2 (v1, v)); 4038 emit_insn (gen_reduc_plus_scal_v8qi (r, v1)); 4039 emit_insn (gen_zero_extendqi<mode>2 (out, r)); 4040 DONE; 4041}) 4042 4043(define_insn "clrsb<mode>2" 4044 [(set (match_operand:GPI 0 "register_operand" "=r") 4045 (clrsb:GPI (match_operand:GPI 1 "register_operand" "r")))] 4046 "" 4047 "cls\\t%<w>0, %<w>1" 4048 [(set_attr "type" "clz")] 4049) 4050 4051(define_insn "rbit<mode>2" 4052 [(set (match_operand:GPI 0 "register_operand" "=r") 4053 (unspec:GPI [(match_operand:GPI 1 "register_operand" "r")] UNSPEC_RBIT))] 4054 "" 4055 "rbit\\t%<w>0, %<w>1" 4056 [(set_attr "type" "rbit")] 4057) 4058 4059;; Split after reload into RBIT + CLZ. Since RBIT is represented as an UNSPEC 4060;; it is unlikely to fold with any other operation, so keep this as a CTZ 4061;; expression and split after reload to enable scheduling them apart if 4062;; needed. 4063 4064(define_insn_and_split "ctz<mode>2" 4065 [(set (match_operand:GPI 0 "register_operand" "=r") 4066 (ctz:GPI (match_operand:GPI 1 "register_operand" "r")))] 4067 "" 4068 "#" 4069 "reload_completed" 4070 [(const_int 0)] 4071 " 4072 emit_insn (gen_rbit<mode>2 (operands[0], operands[1])); 4073 emit_insn (gen_clz<mode>2 (operands[0], operands[0])); 4074 DONE; 4075") 4076 4077(define_insn "*and<mode>_compare0" 4078 [(set (reg:CC_NZ CC_REGNUM) 4079 (compare:CC_NZ 4080 (match_operand:SHORT 0 "register_operand" "r") 4081 (const_int 0)))] 4082 "" 4083 "tst\\t%<w>0, <short_mask>" 4084 [(set_attr "type" "alus_imm")] 4085) 4086 4087(define_insn "*ands<mode>_compare0" 4088 [(set (reg:CC_NZ CC_REGNUM) 4089 (compare:CC_NZ 4090 (zero_extend:GPI (match_operand:SHORT 1 "register_operand" "r")) 4091 (const_int 0))) 4092 (set (match_operand:GPI 0 "register_operand" "=r") 4093 (zero_extend:GPI (match_dup 1)))] 4094 "" 4095 "ands\\t%<GPI:w>0, %<GPI:w>1, <short_mask>" 4096 [(set_attr "type" "alus_imm")] 4097) 4098 4099(define_insn "*and<mode>3nr_compare0" 4100 [(set (reg:CC_NZ CC_REGNUM) 4101 (compare:CC_NZ 4102 (and:GPI (match_operand:GPI 0 "register_operand" "%r,r") 4103 (match_operand:GPI 1 "aarch64_logical_operand" "r,<lconst>")) 4104 (const_int 0)))] 4105 "" 4106 "@ 4107 tst\\t%<w>0, %<w>1 4108 tst\\t%<w>0, %1" 4109 [(set_attr "type" "logics_reg,logics_imm")] 4110) 4111 4112(define_split 4113 [(set (reg:CC_NZ CC_REGNUM) 4114 (compare:CC_NZ 4115 (and:GPI (match_operand:GPI 0 "register_operand") 4116 (match_operand:GPI 1 "aarch64_mov_imm_operand")) 4117 (const_int 0))) 4118 (clobber (match_operand:SI 2 "register_operand"))] 4119 "" 4120 [(set (match_dup 2) (match_dup 1)) 4121 (set (reg:CC_NZ CC_REGNUM) 4122 (compare:CC_NZ 4123 (and:GPI (match_dup 0) 4124 (match_dup 2)) 4125 (const_int 0)))] 4126) 4127 4128(define_insn "*and<mode>3nr_compare0_zextract" 4129 [(set (reg:CC_NZ CC_REGNUM) 4130 (compare:CC_NZ 4131 (zero_extract:GPI (match_operand:GPI 0 "register_operand" "r") 4132 (match_operand:GPI 1 "const_int_operand" "n") 4133 (match_operand:GPI 2 "const_int_operand" "n")) 4134 (const_int 0)))] 4135 "INTVAL (operands[1]) > 0 4136 && ((INTVAL (operands[1]) + INTVAL (operands[2])) 4137 <= GET_MODE_BITSIZE (<MODE>mode)) 4138 && aarch64_bitmask_imm ( 4139 UINTVAL (aarch64_mask_from_zextract_ops (operands[1], 4140 operands[2])), 4141 <MODE>mode)" 4142 { 4143 operands[1] 4144 = aarch64_mask_from_zextract_ops (operands[1], operands[2]); 4145 return "tst\\t%<w>0, %1"; 4146 } 4147 [(set_attr "type" "logics_shift_imm")] 4148) 4149 4150(define_insn "*and_<SHIFT:optab><mode>3nr_compare0" 4151 [(set (reg:CC_NZ CC_REGNUM) 4152 (compare:CC_NZ 4153 (and:GPI (SHIFT:GPI 4154 (match_operand:GPI 0 "register_operand" "r") 4155 (match_operand:QI 1 "aarch64_shift_imm_<mode>" "n")) 4156 (match_operand:GPI 2 "register_operand" "r")) 4157 (const_int 0)))] 4158 "" 4159 "tst\\t%<w>2, %<w>0, <SHIFT:shift> %1" 4160 [(set_attr "type" "logics_shift_imm")] 4161) 4162 4163(define_split 4164 [(set (reg:CC_NZ CC_REGNUM) 4165 (compare:CC_NZ 4166 (and:GPI (SHIFT:GPI 4167 (match_operand:GPI 0 "register_operand") 4168 (match_operand:QI 1 "aarch64_shift_imm_<mode>")) 4169 (match_operand:GPI 2 "aarch64_mov_imm_operand")) 4170 (const_int 0))) 4171 (clobber (match_operand:SI 3 "register_operand"))] 4172 "" 4173 [(set (match_dup 3) (match_dup 2)) 4174 (set (reg:CC_NZ CC_REGNUM) 4175 (compare:CC_NZ 4176 (and:GPI (SHIFT:GPI 4177 (match_dup 0) 4178 (match_dup 1)) 4179 (match_dup 3)) 4180 (const_int 0)))] 4181) 4182 4183;; ------------------------------------------------------------------- 4184;; Shifts 4185;; ------------------------------------------------------------------- 4186 4187(define_expand "<optab><mode>3" 4188 [(set (match_operand:GPI 0 "register_operand") 4189 (ASHIFT:GPI (match_operand:GPI 1 "register_operand") 4190 (match_operand:QI 2 "aarch64_reg_or_imm")))] 4191 "" 4192 { 4193 if (CONST_INT_P (operands[2])) 4194 { 4195 operands[2] = GEN_INT (INTVAL (operands[2]) 4196 & (GET_MODE_BITSIZE (<MODE>mode) - 1)); 4197 4198 if (operands[2] == const0_rtx) 4199 { 4200 emit_insn (gen_mov<mode> (operands[0], operands[1])); 4201 DONE; 4202 } 4203 } 4204 } 4205) 4206 4207(define_expand "ashl<mode>3" 4208 [(set (match_operand:SHORT 0 "register_operand") 4209 (ashift:SHORT (match_operand:SHORT 1 "register_operand") 4210 (match_operand:QI 2 "const_int_operand")))] 4211 "" 4212 { 4213 operands[2] = GEN_INT (INTVAL (operands[2]) & GET_MODE_MASK (<MODE>mode)); 4214 4215 if (operands[2] == const0_rtx) 4216 { 4217 emit_insn (gen_mov<mode> (operands[0], operands[1])); 4218 DONE; 4219 } 4220 } 4221) 4222 4223(define_expand "rotr<mode>3" 4224 [(set (match_operand:GPI 0 "register_operand") 4225 (rotatert:GPI (match_operand:GPI 1 "register_operand") 4226 (match_operand:QI 2 "aarch64_reg_or_imm")))] 4227 "" 4228 { 4229 if (CONST_INT_P (operands[2])) 4230 { 4231 operands[2] = GEN_INT (INTVAL (operands[2]) 4232 & (GET_MODE_BITSIZE (<MODE>mode) - 1)); 4233 4234 if (operands[2] == const0_rtx) 4235 { 4236 emit_insn (gen_mov<mode> (operands[0], operands[1])); 4237 DONE; 4238 } 4239 } 4240 } 4241) 4242 4243(define_expand "rotl<mode>3" 4244 [(set (match_operand:GPI 0 "register_operand") 4245 (rotatert:GPI (match_operand:GPI 1 "register_operand") 4246 (match_operand:QI 2 "aarch64_reg_or_imm")))] 4247 "" 4248 { 4249 /* (SZ - cnt) % SZ == -cnt % SZ */ 4250 if (CONST_INT_P (operands[2])) 4251 { 4252 operands[2] = GEN_INT ((-INTVAL (operands[2])) 4253 & (GET_MODE_BITSIZE (<MODE>mode) - 1)); 4254 if (operands[2] == const0_rtx) 4255 { 4256 emit_insn (gen_mov<mode> (operands[0], operands[1])); 4257 DONE; 4258 } 4259 } 4260 else 4261 operands[2] = expand_simple_unop (QImode, NEG, operands[2], 4262 NULL_RTX, 1); 4263 } 4264) 4265 4266;; When the LSL, LSR, ASR, ROR instructions operate on all register arguments 4267;; they truncate the shift/rotate amount by the size of the registers they 4268;; operate on: 32 for W-regs, 64 for X-regs. This allows us to optimise away 4269;; such redundant masking instructions. GCC can do that automatically when 4270;; SHIFT_COUNT_TRUNCATED is true, but we can't enable it for TARGET_SIMD 4271;; because some of the SISD shift alternatives don't perform this truncations. 4272;; So this pattern exists to catch such cases. 4273 4274(define_insn "*aarch64_<optab>_reg_<mode>3_mask1" 4275 [(set (match_operand:GPI 0 "register_operand" "=r") 4276 (SHIFT:GPI 4277 (match_operand:GPI 1 "register_operand" "r") 4278 (match_operator 4 "subreg_lowpart_operator" 4279 [(and:GPI (match_operand:GPI 2 "register_operand" "r") 4280 (match_operand 3 "const_int_operand" "n"))])))] 4281 "(~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0" 4282 "<shift>\t%<w>0, %<w>1, %<w>2" 4283 [(set_attr "type" "shift_reg")] 4284) 4285 4286(define_insn_and_split "*aarch64_<optab>_reg_<mode>3_neg_mask2" 4287 [(set (match_operand:GPI 0 "register_operand" "=&r") 4288 (SHIFT:GPI 4289 (match_operand:GPI 1 "register_operand" "r") 4290 (match_operator 4 "subreg_lowpart_operator" 4291 [(neg:SI (and:SI (match_operand:SI 2 "register_operand" "r") 4292 (match_operand 3 "const_int_operand" "n")))])))] 4293 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0)" 4294 "#" 4295 "&& true" 4296 [(const_int 0)] 4297 { 4298 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode) 4299 : lowpart_subreg (SImode, operands[0], <MODE>mode)); 4300 emit_insn (gen_negsi2 (tmp, operands[2])); 4301 4302 rtx and_op = gen_rtx_AND (SImode, tmp, operands[3]); 4303 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[4]), and_op, 4304 SUBREG_BYTE (operands[4])); 4305 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp)); 4306 DONE; 4307 } 4308) 4309 4310(define_insn_and_split "*aarch64_ashl_reg_<mode>3_minus_mask" 4311 [(set (match_operand:GPI 0 "register_operand" "=&r") 4312 (ashift:GPI 4313 (match_operand:GPI 1 "register_operand" "r") 4314 (minus:QI (match_operand 2 "const_int_operand" "n") 4315 (match_operator 5 "subreg_lowpart_operator" 4316 [(and:SI (match_operand:SI 3 "register_operand" "r") 4317 (match_operand 4 "const_int_operand" "n"))]))))] 4318 "((~INTVAL (operands[4]) & (GET_MODE_BITSIZE (<MODE>mode) - 1)) == 0) 4319 && INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)" 4320 "#" 4321 "&& true" 4322 [(const_int 0)] 4323 { 4324 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode) 4325 : operands[0]); 4326 4327 emit_insn (gen_negsi2 (tmp, operands[3])); 4328 4329 rtx and_op = gen_rtx_AND (SImode, tmp, operands[4]); 4330 rtx subreg_tmp = gen_rtx_SUBREG (GET_MODE (operands[5]), and_op, 4331 SUBREG_BYTE (operands[5])); 4332 4333 emit_insn (gen_ashl<mode>3 (operands[0], operands[1], subreg_tmp)); 4334 DONE; 4335 } 4336) 4337 4338(define_insn "*aarch64_<optab>_reg_di3_mask2" 4339 [(set (match_operand:DI 0 "register_operand" "=r") 4340 (SHIFT:DI 4341 (match_operand:DI 1 "register_operand" "r") 4342 (match_operator 4 "subreg_lowpart_operator" 4343 [(and:SI (match_operand:SI 2 "register_operand" "r") 4344 (match_operand 3 "const_int_operand" "n"))])))] 4345 "((~INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode) - 1)) == 0)" 4346{ 4347 rtx xop[3]; 4348 xop[0] = operands[0]; 4349 xop[1] = operands[1]; 4350 xop[2] = gen_lowpart (GET_MODE (operands[4]), operands[2]); 4351 output_asm_insn ("<shift>\t%x0, %x1, %x2", xop); 4352 return ""; 4353} 4354 [(set_attr "type" "shift_reg")] 4355) 4356 4357(define_insn_and_split "*aarch64_<optab>_reg_minus<mode>3" 4358 [(set (match_operand:GPI 0 "register_operand" "=&r") 4359 (ASHIFT:GPI 4360 (match_operand:GPI 1 "register_operand" "r") 4361 (minus:QI (match_operand 2 "const_int_operand" "n") 4362 (match_operand:QI 3 "register_operand" "r"))))] 4363 "INTVAL (operands[2]) == GET_MODE_BITSIZE (<MODE>mode)" 4364 "#" 4365 "&& true" 4366 [(const_int 0)] 4367 { 4368 rtx subreg_tmp = gen_lowpart (SImode, operands[3]); 4369 4370 rtx tmp = (can_create_pseudo_p () ? gen_reg_rtx (SImode) 4371 : gen_lowpart (SImode, operands[0])); 4372 4373 emit_insn (gen_negsi2 (tmp, subreg_tmp)); 4374 4375 rtx and_op = gen_rtx_AND (SImode, tmp, 4376 GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1)); 4377 4378 rtx subreg_tmp2 = gen_lowpart_SUBREG (QImode, and_op); 4379 4380 emit_insn (gen_<optab><mode>3 (operands[0], operands[1], subreg_tmp2)); 4381 DONE; 4382 } 4383 [(set_attr "length" "8")] 4384) 4385 4386;; Logical left shift using SISD or Integer instruction 4387(define_insn "*aarch64_ashl_sisd_or_int_<mode>3" 4388 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,w") 4389 (ashift:GPI 4390 (match_operand:GPI 1 "register_operand" "r,r,w,w") 4391 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r,Us<cmode>,w")))] 4392 "" 4393 "@ 4394 lsl\t%<w>0, %<w>1, %2 4395 lsl\t%<w>0, %<w>1, %<w>2 4396 shl\t%<rtn>0<vas>, %<rtn>1<vas>, %2 4397 ushl\t%<rtn>0<vas>, %<rtn>1<vas>, %<rtn>2<vas>" 4398 [(set_attr "simd" "no,no,yes,yes") 4399 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>, neon_shift_reg<q>")] 4400) 4401 4402;; Logical right shift using SISD or Integer instruction 4403(define_insn "*aarch64_lshr_sisd_or_int_<mode>3" 4404 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w") 4405 (lshiftrt:GPI 4406 (match_operand:GPI 1 "register_operand" "r,r,w,w,w") 4407 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" 4408 "Us<cmode>,r,Us<cmode_simd>,w,0")))] 4409 "" 4410 "@ 4411 lsr\t%<w>0, %<w>1, %2 4412 lsr\t%<w>0, %<w>1, %<w>2 4413 ushr\t%<rtn>0<vas>, %<rtn>1<vas>, %2 4414 # 4415 #" 4416 [(set_attr "simd" "no,no,yes,yes,yes") 4417 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")] 4418) 4419 4420(define_split 4421 [(set (match_operand:DI 0 "aarch64_simd_register") 4422 (lshiftrt:DI 4423 (match_operand:DI 1 "aarch64_simd_register") 4424 (match_operand:QI 2 "aarch64_simd_register")))] 4425 "TARGET_SIMD && reload_completed" 4426 [(set (match_dup 3) 4427 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG)) 4428 (set (match_dup 0) 4429 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))] 4430 { 4431 operands[3] = gen_lowpart (QImode, operands[0]); 4432 } 4433) 4434 4435(define_split 4436 [(set (match_operand:SI 0 "aarch64_simd_register") 4437 (lshiftrt:SI 4438 (match_operand:SI 1 "aarch64_simd_register") 4439 (match_operand:QI 2 "aarch64_simd_register")))] 4440 "TARGET_SIMD && reload_completed" 4441 [(set (match_dup 3) 4442 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG)) 4443 (set (match_dup 0) 4444 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))] 4445 { 4446 operands[3] = gen_lowpart (QImode, operands[0]); 4447 } 4448) 4449 4450;; Arithmetic right shift using SISD or Integer instruction 4451(define_insn "*aarch64_ashr_sisd_or_int_<mode>3" 4452 [(set (match_operand:GPI 0 "register_operand" "=r,r,w,&w,&w") 4453 (ashiftrt:GPI 4454 (match_operand:GPI 1 "register_operand" "r,r,w,w,w") 4455 (match_operand:QI 2 "aarch64_reg_or_shift_imm_di" 4456 "Us<cmode>,r,Us<cmode_simd>,w,0")))] 4457 "" 4458 "@ 4459 asr\t%<w>0, %<w>1, %2 4460 asr\t%<w>0, %<w>1, %<w>2 4461 sshr\t%<rtn>0<vas>, %<rtn>1<vas>, %2 4462 # 4463 #" 4464 [(set_attr "simd" "no,no,yes,yes,yes") 4465 (set_attr "type" "bfx,shift_reg,neon_shift_imm<q>,neon_shift_reg<q>,neon_shift_reg<q>")] 4466) 4467 4468(define_split 4469 [(set (match_operand:DI 0 "aarch64_simd_register") 4470 (ashiftrt:DI 4471 (match_operand:DI 1 "aarch64_simd_register") 4472 (match_operand:QI 2 "aarch64_simd_register")))] 4473 "TARGET_SIMD && reload_completed" 4474 [(set (match_dup 3) 4475 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG)) 4476 (set (match_dup 0) 4477 (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_SSHL))] 4478{ 4479 operands[3] = gen_lowpart (QImode, operands[0]); 4480} 4481) 4482 4483(define_split 4484 [(set (match_operand:SI 0 "aarch64_simd_register") 4485 (ashiftrt:SI 4486 (match_operand:SI 1 "aarch64_simd_register") 4487 (match_operand:QI 2 "aarch64_simd_register")))] 4488 "TARGET_SIMD && reload_completed" 4489 [(set (match_dup 3) 4490 (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG)) 4491 (set (match_dup 0) 4492 (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_SSHL_2S))] 4493{ 4494 operands[3] = gen_lowpart (QImode, operands[0]); 4495} 4496) 4497 4498(define_insn "*aarch64_sisd_ushl" 4499 [(set (match_operand:DI 0 "register_operand" "=w") 4500 (unspec:DI [(match_operand:DI 1 "register_operand" "w") 4501 (match_operand:QI 2 "register_operand" "w")] 4502 UNSPEC_SISD_USHL))] 4503 "TARGET_SIMD" 4504 "ushl\t%d0, %d1, %d2" 4505 [(set_attr "simd" "yes") 4506 (set_attr "type" "neon_shift_reg")] 4507) 4508 4509(define_insn "*aarch64_ushl_2s" 4510 [(set (match_operand:SI 0 "register_operand" "=w") 4511 (unspec:SI [(match_operand:SI 1 "register_operand" "w") 4512 (match_operand:QI 2 "register_operand" "w")] 4513 UNSPEC_USHL_2S))] 4514 "TARGET_SIMD" 4515 "ushl\t%0.2s, %1.2s, %2.2s" 4516 [(set_attr "simd" "yes") 4517 (set_attr "type" "neon_shift_reg")] 4518) 4519 4520(define_insn "*aarch64_sisd_sshl" 4521 [(set (match_operand:DI 0 "register_operand" "=w") 4522 (unspec:DI [(match_operand:DI 1 "register_operand" "w") 4523 (match_operand:QI 2 "register_operand" "w")] 4524 UNSPEC_SISD_SSHL))] 4525 "TARGET_SIMD" 4526 "sshl\t%d0, %d1, %d2" 4527 [(set_attr "simd" "yes") 4528 (set_attr "type" "neon_shift_reg")] 4529) 4530 4531(define_insn "*aarch64_sshl_2s" 4532 [(set (match_operand:SI 0 "register_operand" "=w") 4533 (unspec:SI [(match_operand:SI 1 "register_operand" "w") 4534 (match_operand:QI 2 "register_operand" "w")] 4535 UNSPEC_SSHL_2S))] 4536 "TARGET_SIMD" 4537 "sshl\t%0.2s, %1.2s, %2.2s" 4538 [(set_attr "simd" "yes") 4539 (set_attr "type" "neon_shift_reg")] 4540) 4541 4542(define_insn "*aarch64_sisd_neg_qi" 4543 [(set (match_operand:QI 0 "register_operand" "=w") 4544 (unspec:QI [(match_operand:QI 1 "register_operand" "w")] 4545 UNSPEC_SISD_NEG))] 4546 "TARGET_SIMD" 4547 "neg\t%d0, %d1" 4548 [(set_attr "simd" "yes") 4549 (set_attr "type" "neon_neg")] 4550) 4551 4552;; Rotate right 4553(define_insn "*ror<mode>3_insn" 4554 [(set (match_operand:GPI 0 "register_operand" "=r,r") 4555 (rotatert:GPI 4556 (match_operand:GPI 1 "register_operand" "r,r") 4557 (match_operand:QI 2 "aarch64_reg_or_shift_imm_<mode>" "Us<cmode>,r")))] 4558 "" 4559 "@ 4560 ror\\t%<w>0, %<w>1, %2 4561 ror\\t%<w>0, %<w>1, %<w>2" 4562 [(set_attr "type" "rotate_imm,shift_reg")] 4563) 4564 4565;; zero_extend version of above 4566(define_insn "*<optab>si3_insn_uxtw" 4567 [(set (match_operand:DI 0 "register_operand" "=r,r") 4568 (zero_extend:DI (SHIFT:SI 4569 (match_operand:SI 1 "register_operand" "r,r") 4570 (match_operand:QI 2 "aarch64_reg_or_shift_imm_si" "Uss,r"))))] 4571 "" 4572 "@ 4573 <shift>\\t%w0, %w1, %2 4574 <shift>\\t%w0, %w1, %w2" 4575 [(set_attr "type" "bfx,shift_reg")] 4576) 4577 4578(define_insn "*<optab><mode>3_insn" 4579 [(set (match_operand:SHORT 0 "register_operand" "=r") 4580 (ASHIFT:SHORT (match_operand:SHORT 1 "register_operand" "r") 4581 (match_operand 2 "const_int_operand" "n")))] 4582 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)" 4583{ 4584 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2])); 4585 return "<bfshift>\t%w0, %w1, %2, %3"; 4586} 4587 [(set_attr "type" "bfx")] 4588) 4589 4590(define_insn "*extr<mode>5_insn" 4591 [(set (match_operand:GPI 0 "register_operand" "=r") 4592 (ior:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r") 4593 (match_operand 3 "const_int_operand" "n")) 4594 (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r") 4595 (match_operand 4 "const_int_operand" "n"))))] 4596 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) && 4597 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == GET_MODE_BITSIZE (<MODE>mode))" 4598 "extr\\t%<w>0, %<w>1, %<w>2, %4" 4599 [(set_attr "type" "rotate_imm")] 4600) 4601 4602;; There are no canonicalisation rules for ashift and lshiftrt inside an ior 4603;; so we have to match both orderings. 4604(define_insn "*extr<mode>5_insn_alt" 4605 [(set (match_operand:GPI 0 "register_operand" "=r") 4606 (ior:GPI (lshiftrt:GPI (match_operand:GPI 2 "register_operand" "r") 4607 (match_operand 4 "const_int_operand" "n")) 4608 (ashift:GPI (match_operand:GPI 1 "register_operand" "r") 4609 (match_operand 3 "const_int_operand" "n"))))] 4610 "UINTVAL (operands[3]) < GET_MODE_BITSIZE (<MODE>mode) 4611 && (UINTVAL (operands[3]) + UINTVAL (operands[4]) 4612 == GET_MODE_BITSIZE (<MODE>mode))" 4613 "extr\\t%<w>0, %<w>1, %<w>2, %4" 4614 [(set_attr "type" "rotate_imm")] 4615) 4616 4617;; zero_extend version of the above 4618(define_insn "*extrsi5_insn_uxtw" 4619 [(set (match_operand:DI 0 "register_operand" "=r") 4620 (zero_extend:DI 4621 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") 4622 (match_operand 3 "const_int_operand" "n")) 4623 (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") 4624 (match_operand 4 "const_int_operand" "n")))))] 4625 "UINTVAL (operands[3]) < 32 && 4626 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)" 4627 "extr\\t%w0, %w1, %w2, %4" 4628 [(set_attr "type" "rotate_imm")] 4629) 4630 4631(define_insn "*extrsi5_insn_uxtw_alt" 4632 [(set (match_operand:DI 0 "register_operand" "=r") 4633 (zero_extend:DI 4634 (ior:SI (lshiftrt:SI (match_operand:SI 2 "register_operand" "r") 4635 (match_operand 4 "const_int_operand" "n")) 4636 (ashift:SI (match_operand:SI 1 "register_operand" "r") 4637 (match_operand 3 "const_int_operand" "n")))))] 4638 "UINTVAL (operands[3]) < 32 && 4639 (UINTVAL (operands[3]) + UINTVAL (operands[4]) == 32)" 4640 "extr\\t%w0, %w1, %w2, %4" 4641 [(set_attr "type" "rotate_imm")] 4642) 4643 4644(define_insn "*ror<mode>3_insn" 4645 [(set (match_operand:GPI 0 "register_operand" "=r") 4646 (rotate:GPI (match_operand:GPI 1 "register_operand" "r") 4647 (match_operand 2 "const_int_operand" "n")))] 4648 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)" 4649{ 4650 operands[3] = GEN_INT (<sizen> - UINTVAL (operands[2])); 4651 return "ror\\t%<w>0, %<w>1, %3"; 4652} 4653 [(set_attr "type" "rotate_imm")] 4654) 4655 4656;; zero_extend version of the above 4657(define_insn "*rorsi3_insn_uxtw" 4658 [(set (match_operand:DI 0 "register_operand" "=r") 4659 (zero_extend:DI 4660 (rotate:SI (match_operand:SI 1 "register_operand" "r") 4661 (match_operand 2 "const_int_operand" "n"))))] 4662 "UINTVAL (operands[2]) < 32" 4663{ 4664 operands[3] = GEN_INT (32 - UINTVAL (operands[2])); 4665 return "ror\\t%w0, %w1, %3"; 4666} 4667 [(set_attr "type" "rotate_imm")] 4668) 4669 4670(define_insn "*<ANY_EXTEND:optab><GPI:mode>_ashl<SHORT:mode>" 4671 [(set (match_operand:GPI 0 "register_operand" "=r") 4672 (ANY_EXTEND:GPI 4673 (ashift:SHORT (match_operand:SHORT 1 "register_operand" "r") 4674 (match_operand 2 "const_int_operand" "n"))))] 4675 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)" 4676{ 4677 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2])); 4678 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3"; 4679} 4680 [(set_attr "type" "bfx")] 4681) 4682 4683(define_insn "*zero_extend<GPI:mode>_lshr<SHORT:mode>" 4684 [(set (match_operand:GPI 0 "register_operand" "=r") 4685 (zero_extend:GPI 4686 (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r") 4687 (match_operand 2 "const_int_operand" "n"))))] 4688 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)" 4689{ 4690 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2])); 4691 return "ubfx\t%<GPI:w>0, %<GPI:w>1, %2, %3"; 4692} 4693 [(set_attr "type" "bfx")] 4694) 4695 4696(define_insn "*extend<GPI:mode>_ashr<SHORT:mode>" 4697 [(set (match_operand:GPI 0 "register_operand" "=r") 4698 (sign_extend:GPI 4699 (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" "r") 4700 (match_operand 2 "const_int_operand" "n"))))] 4701 "UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)" 4702{ 4703 operands[3] = GEN_INT (<SHORT:sizen> - UINTVAL (operands[2])); 4704 return "sbfx\\t%<GPI:w>0, %<GPI:w>1, %2, %3"; 4705} 4706 [(set_attr "type" "bfx")] 4707) 4708 4709;; ------------------------------------------------------------------- 4710;; Bitfields 4711;; ------------------------------------------------------------------- 4712 4713(define_expand "<optab>" 4714 [(set (match_operand:DI 0 "register_operand" "=r") 4715 (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand") 4716 (match_operand 2 4717 "aarch64_simd_shift_imm_offset_di") 4718 (match_operand 3 "aarch64_simd_shift_imm_di")))] 4719 "" 4720 { 4721 if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 4722 1, GET_MODE_BITSIZE (DImode) - 1)) 4723 FAIL; 4724 } 4725) 4726 4727 4728(define_insn "*<optab><mode>" 4729 [(set (match_operand:GPI 0 "register_operand" "=r") 4730 (ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r") 4731 (match_operand 2 4732 "aarch64_simd_shift_imm_offset_<mode>" "n") 4733 (match_operand 3 4734 "aarch64_simd_shift_imm_<mode>" "n")))] 4735 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 4736 1, GET_MODE_BITSIZE (<MODE>mode) - 1)" 4737 "<su>bfx\\t%<w>0, %<w>1, %3, %2" 4738 [(set_attr "type" "bfx")] 4739) 4740 4741;; When the bit position and width add up to 32 we can use a W-reg LSR 4742;; instruction taking advantage of the implicit zero-extension of the X-reg. 4743(define_split 4744 [(set (match_operand:DI 0 "register_operand") 4745 (zero_extract:DI (match_operand:DI 1 "register_operand") 4746 (match_operand 2 4747 "aarch64_simd_shift_imm_offset_di") 4748 (match_operand 3 4749 "aarch64_simd_shift_imm_di")))] 4750 "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]), 1, 4751 GET_MODE_BITSIZE (DImode) - 1) 4752 && (INTVAL (operands[2]) + INTVAL (operands[3])) 4753 == GET_MODE_BITSIZE (SImode)" 4754 [(set (match_dup 0) 4755 (zero_extend:DI (lshiftrt:SI (match_dup 4) (match_dup 3))))] 4756 { 4757 operands[4] = gen_lowpart (SImode, operands[1]); 4758 } 4759) 4760 4761;; Bitfield Insert (insv) 4762(define_expand "insv<mode>" 4763 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand") 4764 (match_operand 1 "const_int_operand") 4765 (match_operand 2 "const_int_operand")) 4766 (match_operand:GPI 3 "general_operand"))] 4767 "" 4768{ 4769 unsigned HOST_WIDE_INT width = UINTVAL (operands[1]); 4770 unsigned HOST_WIDE_INT pos = UINTVAL (operands[2]); 4771 rtx value = operands[3]; 4772 4773 if (width == 0 || (pos + width) > GET_MODE_BITSIZE (<MODE>mode)) 4774 FAIL; 4775 4776 if (CONST_INT_P (value)) 4777 { 4778 unsigned HOST_WIDE_INT mask = ((unsigned HOST_WIDE_INT)1 << width) - 1; 4779 4780 /* Prefer AND/OR for inserting all zeros or all ones. */ 4781 if ((UINTVAL (value) & mask) == 0 4782 || (UINTVAL (value) & mask) == mask) 4783 FAIL; 4784 4785 /* 16-bit aligned 16-bit wide insert is handled by insv_imm. */ 4786 if (width == 16 && (pos % 16) == 0) 4787 DONE; 4788 } 4789 operands[3] = force_reg (<MODE>mode, value); 4790}) 4791 4792(define_insn "*insv_reg<mode>" 4793 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r") 4794 (match_operand 1 "const_int_operand" "n") 4795 (match_operand 2 "const_int_operand" "n")) 4796 (match_operand:GPI 3 "register_operand" "r"))] 4797 "!(UINTVAL (operands[1]) == 0 4798 || (UINTVAL (operands[2]) + UINTVAL (operands[1]) 4799 > GET_MODE_BITSIZE (<MODE>mode)))" 4800 "bfi\\t%<w>0, %<w>3, %2, %1" 4801 [(set_attr "type" "bfm")] 4802) 4803 4804(define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4" 4805 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r") 4806 (match_operand 1 "const_int_operand" "n") 4807 (match_operand 2 "const_int_operand" "n")) 4808 (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))] 4809 "UINTVAL (operands[1]) <= <ALLX:sizen>" 4810 "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1" 4811 [(set_attr "type" "bfm")] 4812) 4813 4814(define_insn "*extr_insv_lower_reg<mode>" 4815 [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r") 4816 (match_operand 1 "const_int_operand" "n") 4817 (const_int 0)) 4818 (zero_extract:GPI (match_operand:GPI 2 "register_operand" "r") 4819 (match_dup 1) 4820 (match_operand 3 "const_int_operand" "n")))] 4821 "!(UINTVAL (operands[1]) == 0 4822 || (UINTVAL (operands[3]) + UINTVAL (operands[1]) 4823 > GET_MODE_BITSIZE (<MODE>mode)))" 4824 "bfxil\\t%<w>0, %<w>2, %3, %1" 4825 [(set_attr "type" "bfm")] 4826) 4827 4828(define_insn "*<optab><ALLX:mode>_shft_<GPI:mode>" 4829 [(set (match_operand:GPI 0 "register_operand" "=r") 4830 (ashift:GPI (ANY_EXTEND:GPI 4831 (match_operand:ALLX 1 "register_operand" "r")) 4832 (match_operand 2 "const_int_operand" "n")))] 4833 "UINTVAL (operands[2]) < <GPI:sizen>" 4834{ 4835 operands[3] = (<ALLX:sizen> <= (<GPI:sizen> - UINTVAL (operands[2]))) 4836 ? GEN_INT (<ALLX:sizen>) 4837 : GEN_INT (<GPI:sizen> - UINTVAL (operands[2])); 4838 return "<su>bfiz\t%<GPI:w>0, %<GPI:w>1, %2, %3"; 4839} 4840 [(set_attr "type" "bfx")] 4841) 4842 4843;; XXX We should match (any_extend (ashift)) here, like (and (ashift)) below 4844 4845(define_insn "*andim_ashift<mode>_bfiz" 4846 [(set (match_operand:GPI 0 "register_operand" "=r") 4847 (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r") 4848 (match_operand 2 "const_int_operand" "n")) 4849 (match_operand 3 "const_int_operand" "n")))] 4850 "aarch64_mask_and_shift_for_ubfiz_p (<MODE>mode, operands[3], operands[2])" 4851 "ubfiz\\t%<w>0, %<w>1, %2, %P3" 4852 [(set_attr "type" "bfx")] 4853) 4854 4855;; When the bit position and width of the equivalent extraction add up to 32 4856;; we can use a W-reg LSL instruction taking advantage of the implicit 4857;; zero-extension of the X-reg. 4858(define_split 4859 [(set (match_operand:DI 0 "register_operand") 4860 (and:DI (ashift:DI (match_operand:DI 1 "register_operand") 4861 (match_operand 2 "const_int_operand")) 4862 (match_operand 3 "const_int_operand")))] 4863 "aarch64_mask_and_shift_for_ubfiz_p (DImode, operands[3], operands[2]) 4864 && (INTVAL (operands[2]) + popcount_hwi (INTVAL (operands[3]))) 4865 == GET_MODE_BITSIZE (SImode)" 4866 [(set (match_dup 0) 4867 (zero_extend:DI (ashift:SI (match_dup 4) (match_dup 2))))] 4868 { 4869 operands[4] = gen_lowpart (SImode, operands[1]); 4870 } 4871) 4872 4873(define_insn "bswap<mode>2" 4874 [(set (match_operand:GPI 0 "register_operand" "=r") 4875 (bswap:GPI (match_operand:GPI 1 "register_operand" "r")))] 4876 "" 4877 "rev\\t%<w>0, %<w>1" 4878 [(set_attr "type" "rev")] 4879) 4880 4881(define_insn "bswaphi2" 4882 [(set (match_operand:HI 0 "register_operand" "=r") 4883 (bswap:HI (match_operand:HI 1 "register_operand" "r")))] 4884 "" 4885 "rev16\\t%w0, %w1" 4886 [(set_attr "type" "rev")] 4887) 4888 4889;; There are no canonicalisation rules for the position of the lshiftrt, ashift 4890;; operations within an IOR/AND RTX, therefore we have two patterns matching 4891;; each valid permutation. 4892 4893(define_insn "rev16<mode>2" 4894 [(set (match_operand:GPI 0 "register_operand" "=r") 4895 (ior:GPI (and:GPI (ashift:GPI (match_operand:GPI 1 "register_operand" "r") 4896 (const_int 8)) 4897 (match_operand:GPI 3 "const_int_operand" "n")) 4898 (and:GPI (lshiftrt:GPI (match_dup 1) 4899 (const_int 8)) 4900 (match_operand:GPI 2 "const_int_operand" "n"))))] 4901 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode) 4902 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)" 4903 "rev16\\t%<w>0, %<w>1" 4904 [(set_attr "type" "rev")] 4905) 4906 4907(define_insn "rev16<mode>2_alt" 4908 [(set (match_operand:GPI 0 "register_operand" "=r") 4909 (ior:GPI (and:GPI (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "r") 4910 (const_int 8)) 4911 (match_operand:GPI 2 "const_int_operand" "n")) 4912 (and:GPI (ashift:GPI (match_dup 1) 4913 (const_int 8)) 4914 (match_operand:GPI 3 "const_int_operand" "n"))))] 4915 "aarch_rev16_shleft_mask_imm_p (operands[3], <MODE>mode) 4916 && aarch_rev16_shright_mask_imm_p (operands[2], <MODE>mode)" 4917 "rev16\\t%<w>0, %<w>1" 4918 [(set_attr "type" "rev")] 4919) 4920 4921;; zero_extend version of above 4922(define_insn "*bswapsi2_uxtw" 4923 [(set (match_operand:DI 0 "register_operand" "=r") 4924 (zero_extend:DI (bswap:SI (match_operand:SI 1 "register_operand" "r"))))] 4925 "" 4926 "rev\\t%w0, %w1" 4927 [(set_attr "type" "rev")] 4928) 4929 4930;; ------------------------------------------------------------------- 4931;; Floating-point intrinsics 4932;; ------------------------------------------------------------------- 4933 4934;; frint floating-point round to integral standard patterns. 4935;; Expands to btrunc, ceil, floor, nearbyint, rint, round, frintn. 4936 4937(define_insn "<frint_pattern><mode>2" 4938 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 4939 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")] 4940 FRINT))] 4941 "TARGET_FLOAT" 4942 "frint<frint_suffix>\\t%<s>0, %<s>1" 4943 [(set_attr "type" "f_rint<stype>")] 4944) 4945 4946;; frcvt floating-point round to integer and convert standard patterns. 4947;; Expands to lbtrunc, lceil, lfloor, lround. 4948(define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2" 4949 [(set (match_operand:GPI 0 "register_operand" "=r") 4950 (FIXUORS:GPI 4951 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")] 4952 FCVT)))] 4953 "TARGET_FLOAT" 4954 "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1" 4955 [(set_attr "type" "f_cvtf2i")] 4956) 4957 4958(define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult" 4959 [(set (match_operand:GPI 0 "register_operand" "=r") 4960 (FIXUORS:GPI 4961 (mult:GPF 4962 (match_operand:GPF 1 "register_operand" "w") 4963 (match_operand:GPF 2 "aarch64_fp_pow2" "F"))))] 4964 "TARGET_FLOAT 4965 && IN_RANGE (aarch64_fpconst_pow_of_2 (operands[2]), 1, 4966 GET_MODE_BITSIZE (<GPI:MODE>mode))" 4967 { 4968 int fbits = aarch64_fpconst_pow_of_2 (operands[2]); 4969 char buf[64]; 4970 snprintf (buf, 64, "fcvtz<su>\\t%%<GPI:w>0, %%<GPF:s>1, #%d", fbits); 4971 output_asm_insn (buf, operands); 4972 return ""; 4973 } 4974 [(set_attr "type" "f_cvtf2i")] 4975) 4976 4977;; fma - no throw 4978 4979(define_insn "fma<mode>4" 4980 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 4981 (fma:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w") 4982 (match_operand:GPF_F16 2 "register_operand" "w") 4983 (match_operand:GPF_F16 3 "register_operand" "w")))] 4984 "TARGET_FLOAT" 4985 "fmadd\\t%<s>0, %<s>1, %<s>2, %<s>3" 4986 [(set_attr "type" "fmac<stype>")] 4987) 4988 4989(define_insn "fnma<mode>4" 4990 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 4991 (fma:GPF_F16 4992 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")) 4993 (match_operand:GPF_F16 2 "register_operand" "w") 4994 (match_operand:GPF_F16 3 "register_operand" "w")))] 4995 "TARGET_FLOAT" 4996 "fmsub\\t%<s>0, %<s>1, %<s>2, %<s>3" 4997 [(set_attr "type" "fmac<stype>")] 4998) 4999 5000(define_insn "fms<mode>4" 5001 [(set (match_operand:GPF 0 "register_operand" "=w") 5002 (fma:GPF (match_operand:GPF 1 "register_operand" "w") 5003 (match_operand:GPF 2 "register_operand" "w") 5004 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))] 5005 "TARGET_FLOAT" 5006 "fnmsub\\t%<s>0, %<s>1, %<s>2, %<s>3" 5007 [(set_attr "type" "fmac<s>")] 5008) 5009 5010(define_insn "fnms<mode>4" 5011 [(set (match_operand:GPF 0 "register_operand" "=w") 5012 (fma:GPF (neg:GPF (match_operand:GPF 1 "register_operand" "w")) 5013 (match_operand:GPF 2 "register_operand" "w") 5014 (neg:GPF (match_operand:GPF 3 "register_operand" "w"))))] 5015 "TARGET_FLOAT" 5016 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3" 5017 [(set_attr "type" "fmac<s>")] 5018) 5019 5020;; If signed zeros are ignored, -(a * b + c) = -a * b - c. 5021(define_insn "*fnmadd<mode>4" 5022 [(set (match_operand:GPF 0 "register_operand" "=w") 5023 (neg:GPF (fma:GPF (match_operand:GPF 1 "register_operand" "w") 5024 (match_operand:GPF 2 "register_operand" "w") 5025 (match_operand:GPF 3 "register_operand" "w"))))] 5026 "!HONOR_SIGNED_ZEROS (<MODE>mode) && TARGET_FLOAT" 5027 "fnmadd\\t%<s>0, %<s>1, %<s>2, %<s>3" 5028 [(set_attr "type" "fmac<s>")] 5029) 5030 5031;; ------------------------------------------------------------------- 5032;; Floating-point conversions 5033;; ------------------------------------------------------------------- 5034 5035(define_insn "extendsfdf2" 5036 [(set (match_operand:DF 0 "register_operand" "=w") 5037 (float_extend:DF (match_operand:SF 1 "register_operand" "w")))] 5038 "TARGET_FLOAT" 5039 "fcvt\\t%d0, %s1" 5040 [(set_attr "type" "f_cvt")] 5041) 5042 5043(define_insn "extendhfsf2" 5044 [(set (match_operand:SF 0 "register_operand" "=w") 5045 (float_extend:SF (match_operand:HF 1 "register_operand" "w")))] 5046 "TARGET_FLOAT" 5047 "fcvt\\t%s0, %h1" 5048 [(set_attr "type" "f_cvt")] 5049) 5050 5051(define_insn "extendhfdf2" 5052 [(set (match_operand:DF 0 "register_operand" "=w") 5053 (float_extend:DF (match_operand:HF 1 "register_operand" "w")))] 5054 "TARGET_FLOAT" 5055 "fcvt\\t%d0, %h1" 5056 [(set_attr "type" "f_cvt")] 5057) 5058 5059(define_insn "truncdfsf2" 5060 [(set (match_operand:SF 0 "register_operand" "=w") 5061 (float_truncate:SF (match_operand:DF 1 "register_operand" "w")))] 5062 "TARGET_FLOAT" 5063 "fcvt\\t%s0, %d1" 5064 [(set_attr "type" "f_cvt")] 5065) 5066 5067(define_insn "truncsfhf2" 5068 [(set (match_operand:HF 0 "register_operand" "=w") 5069 (float_truncate:HF (match_operand:SF 1 "register_operand" "w")))] 5070 "TARGET_FLOAT" 5071 "fcvt\\t%h0, %s1" 5072 [(set_attr "type" "f_cvt")] 5073) 5074 5075(define_insn "truncdfhf2" 5076 [(set (match_operand:HF 0 "register_operand" "=w") 5077 (float_truncate:HF (match_operand:DF 1 "register_operand" "w")))] 5078 "TARGET_FLOAT" 5079 "fcvt\\t%h0, %d1" 5080 [(set_attr "type" "f_cvt")] 5081) 5082 5083;; Convert SF -> SI or DF -> DI while preferring w = w register constraints 5084;; and making r = w more expensive 5085 5086(define_insn "<optab>_trunc<fcvt_target><GPI:mode>2" 5087 [(set (match_operand:GPI 0 "register_operand" "=?r,w") 5088 (FIXUORS:GPI (match_operand:<FCVT_TARGET> 1 "register_operand" "w,w")))] 5089 "TARGET_FLOAT" 5090 "@ 5091 fcvtz<su>\t%<w>0, %<s>1 5092 fcvtz<su>\t%<s>0, %<s>1" 5093 [(set_attr "type" "f_cvtf2i,neon_fp_to_int_s")] 5094) 5095 5096;; Convert HF -> SI or DI 5097 5098(define_insn "<optab>_trunchf<GPI:mode>2" 5099 [(set (match_operand:GPI 0 "register_operand" "=r") 5100 (FIXUORS:GPI (match_operand:HF 1 "register_operand" "w")))] 5101 "TARGET_FP_F16INST" 5102 "fcvtz<su>\t%<w>0, %h1" 5103 [(set_attr "type" "f_cvtf2i")] 5104) 5105 5106;; Convert DF -> SI or SF -> DI which can only be accomplished with 5107;; input in a fp register and output in a integer register 5108 5109(define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>2" 5110 [(set (match_operand:GPI 0 "register_operand" "=r") 5111 (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand" "w")))] 5112 "TARGET_FLOAT" 5113 "fcvtz<su>\t%<w>0, %<fpw>1" 5114 [(set_attr "type" "f_cvtf2i")] 5115) 5116 5117(define_insn "<optab><fcvt_target><GPF:mode>2" 5118 [(set (match_operand:GPF 0 "register_operand" "=w,w") 5119 (FLOATUORS:GPF (match_operand:<FCVT_TARGET> 1 "register_operand" "w,r")))] 5120 "TARGET_FLOAT" 5121 "@ 5122 <su_optab>cvtf\t%<GPF:s>0, %<s>1 5123 <su_optab>cvtf\t%<GPF:s>0, %<w1>1" 5124 [(set_attr "simd" "yes,no") 5125 (set_attr "fp" "no,yes") 5126 (set_attr "type" "neon_int_to_fp_<Vetype>,f_cvti2f")] 5127) 5128 5129(define_insn "<optab><fcvt_iesize><GPF:mode>2" 5130 [(set (match_operand:GPF 0 "register_operand" "=w") 5131 (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))] 5132 "TARGET_FLOAT" 5133 "<su_optab>cvtf\t%<GPF:s>0, %<w2>1" 5134 [(set_attr "type" "f_cvti2f")] 5135) 5136 5137;; If we do not have ARMv8.2-A 16-bit floating point extensions, the 5138;; midend will arrange for an SImode conversion to HFmode to first go 5139;; through DFmode, then to HFmode. But first it will try converting 5140;; to DImode then down, which would match our DImode pattern below and 5141;; give very poor code-generation. So, we must provide our own emulation 5142;; of the mid-end logic. 5143 5144(define_insn "aarch64_fp16_<optab><mode>hf2" 5145 [(set (match_operand:HF 0 "register_operand" "=w") 5146 (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))] 5147 "TARGET_FP_F16INST" 5148 "<su_optab>cvtf\t%h0, %<w>1" 5149 [(set_attr "type" "f_cvti2f")] 5150) 5151 5152(define_expand "<optab>sihf2" 5153 [(set (match_operand:HF 0 "register_operand") 5154 (FLOATUORS:HF (match_operand:SI 1 "register_operand")))] 5155 "TARGET_FLOAT" 5156{ 5157 if (TARGET_FP_F16INST) 5158 emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1])); 5159 else 5160 { 5161 rtx convert_target = gen_reg_rtx (DFmode); 5162 emit_insn (gen_<optab>sidf2 (convert_target, operands[1])); 5163 emit_insn (gen_truncdfhf2 (operands[0], convert_target)); 5164 } 5165 DONE; 5166} 5167) 5168 5169;; For DImode there is no wide enough floating-point mode that we 5170;; can convert through natively (TFmode would work, but requires a library 5171;; call). However, we know that any value >= 65504 will be rounded 5172;; to infinity on conversion. This is well within the range of SImode, so 5173;; we can: 5174;; Saturate to SImode. 5175;; Convert from that to DFmode 5176;; Convert from that to HFmode (phew!). 5177;; Note that the saturation to SImode requires the SIMD extensions. If 5178;; we ever need to provide this pattern where the SIMD extensions are not 5179;; available, we would need a different approach. 5180 5181(define_expand "<optab>dihf2" 5182 [(set (match_operand:HF 0 "register_operand") 5183 (FLOATUORS:HF (match_operand:DI 1 "register_operand")))] 5184 "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)" 5185{ 5186 if (TARGET_FP_F16INST) 5187 emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1])); 5188 else 5189 { 5190 rtx sat_target = gen_reg_rtx (SImode); 5191 emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1])); 5192 emit_insn (gen_<optab>sihf2 (operands[0], sat_target)); 5193 } 5194 5195 DONE; 5196} 5197) 5198 5199;; Convert between fixed-point and floating-point (scalar modes) 5200 5201(define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3" 5202 [(set (match_operand:<GPF:FCVT_TARGET> 0 "register_operand" "=r, w") 5203 (unspec:<GPF:FCVT_TARGET> [(match_operand:GPF 1 "register_operand" "w, w") 5204 (match_operand:SI 2 "immediate_operand" "i, i")] 5205 FCVT_F2FIXED))] 5206 "" 5207 "@ 5208 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:w1>0, %<GPF:s>1, #%2 5209 <FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPF:s>0, %<GPF:s>1, #%2" 5210 [(set_attr "type" "f_cvtf2i, neon_fp_to_int_<GPF:Vetype>") 5211 (set_attr "fp" "yes, *") 5212 (set_attr "simd" "*, yes")] 5213) 5214 5215(define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><GPI:mode>3" 5216 [(set (match_operand:<GPI:FCVT_TARGET> 0 "register_operand" "=w, w") 5217 (unspec:<GPI:FCVT_TARGET> [(match_operand:GPI 1 "register_operand" "r, w") 5218 (match_operand:SI 2 "immediate_operand" "i, i")] 5219 FCVT_FIXED2F))] 5220 "" 5221 "@ 5222 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:w>1, #%2 5223 <FCVT_FIXED2F:fcvt_fixed_insn>\t%<GPI:v>0, %<GPI:v>1, #%2" 5224 [(set_attr "type" "f_cvti2f, neon_int_to_fp_<GPI:Vetype>") 5225 (set_attr "fp" "yes, *") 5226 (set_attr "simd" "*, yes")] 5227) 5228 5229(define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf<mode>3" 5230 [(set (match_operand:GPI 0 "register_operand" "=r") 5231 (unspec:GPI [(match_operand:HF 1 "register_operand" "w") 5232 (match_operand:SI 2 "immediate_operand" "i")] 5233 FCVT_F2FIXED))] 5234 "TARGET_FP_F16INST" 5235 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%<GPI:w>0, %h1, #%2" 5236 [(set_attr "type" "f_cvtf2i")] 5237) 5238 5239(define_insn "<FCVT_FIXED2F:fcvt_fixed_insn><mode>hf3" 5240 [(set (match_operand:HF 0 "register_operand" "=w") 5241 (unspec:HF [(match_operand:GPI 1 "register_operand" "r") 5242 (match_operand:SI 2 "immediate_operand" "i")] 5243 FCVT_FIXED2F))] 5244 "TARGET_FP_F16INST" 5245 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %<GPI:w>1, #%2" 5246 [(set_attr "type" "f_cvti2f")] 5247) 5248 5249(define_insn "<FCVT_F2FIXED:fcvt_fixed_insn>hf3" 5250 [(set (match_operand:HI 0 "register_operand" "=w") 5251 (unspec:HI [(match_operand:HF 1 "register_operand" "w") 5252 (match_operand:SI 2 "immediate_operand" "i")] 5253 FCVT_F2FIXED))] 5254 "TARGET_SIMD" 5255 "<FCVT_F2FIXED:fcvt_fixed_insn>\t%h0, %h1, #%2" 5256 [(set_attr "type" "neon_fp_to_int_s")] 5257) 5258 5259(define_insn "<FCVT_FIXED2F:fcvt_fixed_insn>hi3" 5260 [(set (match_operand:HF 0 "register_operand" "=w") 5261 (unspec:HF [(match_operand:HI 1 "register_operand" "w") 5262 (match_operand:SI 2 "immediate_operand" "i")] 5263 FCVT_FIXED2F))] 5264 "TARGET_SIMD" 5265 "<FCVT_FIXED2F:fcvt_fixed_insn>\t%h0, %h1, #%2" 5266 [(set_attr "type" "neon_int_to_fp_s")] 5267) 5268 5269;; ------------------------------------------------------------------- 5270;; Floating-point arithmetic 5271;; ------------------------------------------------------------------- 5272 5273(define_insn "add<mode>3" 5274 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5275 (plus:GPF_F16 5276 (match_operand:GPF_F16 1 "register_operand" "w") 5277 (match_operand:GPF_F16 2 "register_operand" "w")))] 5278 "TARGET_FLOAT" 5279 "fadd\\t%<s>0, %<s>1, %<s>2" 5280 [(set_attr "type" "fadd<stype>")] 5281) 5282 5283(define_insn "sub<mode>3" 5284 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5285 (minus:GPF_F16 5286 (match_operand:GPF_F16 1 "register_operand" "w") 5287 (match_operand:GPF_F16 2 "register_operand" "w")))] 5288 "TARGET_FLOAT" 5289 "fsub\\t%<s>0, %<s>1, %<s>2" 5290 [(set_attr "type" "fadd<stype>")] 5291) 5292 5293(define_insn "mul<mode>3" 5294 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5295 (mult:GPF_F16 5296 (match_operand:GPF_F16 1 "register_operand" "w") 5297 (match_operand:GPF_F16 2 "register_operand" "w")))] 5298 "TARGET_FLOAT" 5299 "fmul\\t%<s>0, %<s>1, %<s>2" 5300 [(set_attr "type" "fmul<stype>")] 5301) 5302 5303(define_insn "*fnmul<mode>3" 5304 [(set (match_operand:GPF 0 "register_operand" "=w") 5305 (mult:GPF 5306 (neg:GPF (match_operand:GPF 1 "register_operand" "w")) 5307 (match_operand:GPF 2 "register_operand" "w")))] 5308 "TARGET_FLOAT && !flag_rounding_math" 5309 "fnmul\\t%<s>0, %<s>1, %<s>2" 5310 [(set_attr "type" "fmul<s>")] 5311) 5312 5313(define_insn "*fnmul<mode>3" 5314 [(set (match_operand:GPF 0 "register_operand" "=w") 5315 (neg:GPF (mult:GPF 5316 (match_operand:GPF 1 "register_operand" "w") 5317 (match_operand:GPF 2 "register_operand" "w"))))] 5318 "TARGET_FLOAT" 5319 "fnmul\\t%<s>0, %<s>1, %<s>2" 5320 [(set_attr "type" "fmul<s>")] 5321) 5322 5323(define_expand "div<mode>3" 5324 [(set (match_operand:GPF_F16 0 "register_operand") 5325 (div:GPF_F16 (match_operand:GPF_F16 1 "general_operand") 5326 (match_operand:GPF_F16 2 "register_operand")))] 5327 "TARGET_FLOAT" 5328{ 5329 if (aarch64_emit_approx_div (operands[0], operands[1], operands[2])) 5330 DONE; 5331 5332 operands[1] = force_reg (<MODE>mode, operands[1]); 5333}) 5334 5335(define_insn "*div<mode>3" 5336 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5337 (div:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w") 5338 (match_operand:GPF_F16 2 "register_operand" "w")))] 5339 "TARGET_FLOAT" 5340 "fdiv\\t%<s>0, %<s>1, %<s>2" 5341 [(set_attr "type" "fdiv<stype>")] 5342) 5343 5344(define_insn "neg<mode>2" 5345 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5346 (neg:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))] 5347 "TARGET_FLOAT" 5348 "fneg\\t%<s>0, %<s>1" 5349 [(set_attr "type" "ffarith<stype>")] 5350) 5351 5352(define_expand "sqrt<mode>2" 5353 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5354 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))] 5355 "TARGET_FLOAT" 5356{ 5357 if (aarch64_emit_approx_sqrt (operands[0], operands[1], false)) 5358 DONE; 5359}) 5360 5361(define_insn "*sqrt<mode>2" 5362 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5363 (sqrt:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))] 5364 "TARGET_FLOAT" 5365 "fsqrt\\t%<s>0, %<s>1" 5366 [(set_attr "type" "fsqrt<stype>")] 5367) 5368 5369(define_insn "abs<mode>2" 5370 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5371 (abs:GPF_F16 (match_operand:GPF_F16 1 "register_operand" "w")))] 5372 "TARGET_FLOAT" 5373 "fabs\\t%<s>0, %<s>1" 5374 [(set_attr "type" "ffarith<stype>")] 5375) 5376 5377;; Given that smax/smin do not specify the result when either input is NaN, 5378;; we could use either FMAXNM or FMAX for smax, and either FMINNM or FMIN 5379;; for smin. 5380 5381(define_insn "smax<mode>3" 5382 [(set (match_operand:GPF 0 "register_operand" "=w") 5383 (smax:GPF (match_operand:GPF 1 "register_operand" "w") 5384 (match_operand:GPF 2 "register_operand" "w")))] 5385 "TARGET_FLOAT" 5386 "fmaxnm\\t%<s>0, %<s>1, %<s>2" 5387 [(set_attr "type" "f_minmax<s>")] 5388) 5389 5390(define_insn "smin<mode>3" 5391 [(set (match_operand:GPF 0 "register_operand" "=w") 5392 (smin:GPF (match_operand:GPF 1 "register_operand" "w") 5393 (match_operand:GPF 2 "register_operand" "w")))] 5394 "TARGET_FLOAT" 5395 "fminnm\\t%<s>0, %<s>1, %<s>2" 5396 [(set_attr "type" "f_minmax<s>")] 5397) 5398 5399;; Scalar forms for fmax, fmin, fmaxnm, fminnm. 5400;; fmaxnm and fminnm are used for the fmax<mode>3 standard pattern names, 5401;; which implement the IEEE fmax ()/fmin () functions. 5402(define_insn "<maxmin_uns><mode>3" 5403 [(set (match_operand:GPF_F16 0 "register_operand" "=w") 5404 (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w") 5405 (match_operand:GPF_F16 2 "register_operand" "w")] 5406 FMAXMIN_UNS))] 5407 "TARGET_FLOAT" 5408 "<maxmin_uns_op>\\t%<s>0, %<s>1, %<s>2" 5409 [(set_attr "type" "f_minmax<stype>")] 5410) 5411 5412(define_expand "lrint<GPF:mode><GPI:mode>2" 5413 [(match_operand:GPI 0 "register_operand") 5414 (match_operand:GPF 1 "register_operand")] 5415 "TARGET_FLOAT 5416 && ((GET_MODE_BITSIZE (<GPF:MODE>mode) <= LONG_TYPE_SIZE) 5417 || !flag_trapping_math || flag_fp_int_builtin_inexact)" 5418{ 5419 rtx cvt = gen_reg_rtx (<GPF:MODE>mode); 5420 emit_insn (gen_rint<GPF:mode>2 (cvt, operands[1])); 5421 emit_insn (gen_lbtrunc<GPF:mode><GPI:mode>2 (operands[0], cvt)); 5422 DONE; 5423} 5424) 5425 5426;; For copysign (x, y), we want to generate: 5427;; 5428;; LDR d2, #(1 << 63) 5429;; BSL v2.8b, [y], [x] 5430;; 5431;; or another, equivalent, sequence using one of BSL/BIT/BIF. Because 5432;; we expect these operations to nearly always operate on 5433;; floating-point values, we do not want the operation to be 5434;; simplified into a bit-field insert operation that operates on the 5435;; integer side, since typically that would involve three inter-bank 5436;; register copies. As we do not expect copysign to be followed by 5437;; other logical operations on the result, it seems preferable to keep 5438;; this as an unspec operation, rather than exposing the underlying 5439;; logic to the compiler. 5440 5441(define_expand "copysign<GPF:mode>3" 5442 [(match_operand:GPF 0 "register_operand") 5443 (match_operand:GPF 1 "register_operand") 5444 (match_operand:GPF 2 "register_operand")] 5445 "TARGET_FLOAT && TARGET_SIMD" 5446{ 5447 rtx bitmask = gen_reg_rtx (<V_INT_EQUIV>mode); 5448 emit_move_insn (bitmask, GEN_INT (HOST_WIDE_INT_M1U 5449 << (GET_MODE_BITSIZE (<MODE>mode) - 1))); 5450 emit_insn (gen_copysign<mode>3_insn (operands[0], operands[1], operands[2], 5451 bitmask)); 5452 DONE; 5453} 5454) 5455 5456(define_insn "copysign<GPF:mode>3_insn" 5457 [(set (match_operand:GPF 0 "register_operand" "=w,w,w,r") 5458 (unspec:GPF [(match_operand:GPF 1 "register_operand" "w,0,w,r") 5459 (match_operand:GPF 2 "register_operand" "w,w,0,0") 5460 (match_operand:<V_INT_EQUIV> 3 "register_operand" 5461 "0,w,w,X")] 5462 UNSPEC_COPYSIGN))] 5463 "TARGET_FLOAT && TARGET_SIMD" 5464 "@ 5465 bsl\\t%0.<Vbtype>, %2.<Vbtype>, %1.<Vbtype> 5466 bit\\t%0.<Vbtype>, %2.<Vbtype>, %3.<Vbtype> 5467 bif\\t%0.<Vbtype>, %1.<Vbtype>, %3.<Vbtype> 5468 bfxil\\t%<w1>0, %<w1>1, #0, <sizem1>" 5469 [(set_attr "type" "neon_bsl<q>,neon_bsl<q>,neon_bsl<q>,bfm")] 5470) 5471 5472 5473;; For xorsign (x, y), we want to generate: 5474;; 5475;; LDR d2, #1<<63 5476;; AND v3.8B, v1.8B, v2.8B 5477;; EOR v0.8B, v0.8B, v3.8B 5478;; 5479 5480(define_expand "xorsign<mode>3" 5481 [(match_operand:GPF 0 "register_operand") 5482 (match_operand:GPF 1 "register_operand") 5483 (match_operand:GPF 2 "register_operand")] 5484 "TARGET_FLOAT && TARGET_SIMD" 5485{ 5486 5487 machine_mode imode = <V_INT_EQUIV>mode; 5488 rtx mask = gen_reg_rtx (imode); 5489 rtx op1x = gen_reg_rtx (imode); 5490 rtx op2x = gen_reg_rtx (imode); 5491 5492 int bits = GET_MODE_BITSIZE (<MODE>mode) - 1; 5493 emit_move_insn (mask, GEN_INT (trunc_int_for_mode (HOST_WIDE_INT_M1U << bits, 5494 imode))); 5495 5496 emit_insn (gen_and<v_int_equiv>3 (op2x, mask, 5497 lowpart_subreg (imode, operands[2], 5498 <MODE>mode))); 5499 emit_insn (gen_xor<v_int_equiv>3 (op1x, 5500 lowpart_subreg (imode, operands[1], 5501 <MODE>mode), 5502 op2x)); 5503 emit_move_insn (operands[0], 5504 lowpart_subreg (<MODE>mode, op1x, imode)); 5505 DONE; 5506} 5507) 5508 5509;; ------------------------------------------------------------------- 5510;; Reload support 5511;; ------------------------------------------------------------------- 5512;; Reload Scalar Floating point modes from constant pool. 5513;; The AArch64 port doesn't have __int128 constant move support. 5514(define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>" 5515 [(set (match_operand:GPF_TF 0 "register_operand" "=w") 5516 (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S"))) 5517 (clobber (match_operand:P 2 "register_operand" "=&r"))] 5518 "TARGET_FLOAT" 5519 { 5520 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0)); 5521 emit_move_insn (operands[0], gen_rtx_MEM (<GPF_TF:MODE>mode, operands[2])); 5522 DONE; 5523 } 5524) 5525 5526;; Reload Vector modes from constant pool. 5527(define_expand "aarch64_reload_movcp<VALL:mode><P:mode>" 5528 [(set (match_operand:VALL 0 "register_operand" "=w") 5529 (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S"))) 5530 (clobber (match_operand:P 2 "register_operand" "=&r"))] 5531 "TARGET_FLOAT" 5532 { 5533 aarch64_expand_mov_immediate (operands[2], XEXP (operands[1], 0)); 5534 emit_move_insn (operands[0], gen_rtx_MEM (<VALL:MODE>mode, operands[2])); 5535 DONE; 5536 } 5537) 5538 5539(define_expand "aarch64_reload_mov<mode>" 5540 [(set (match_operand:TX 0 "register_operand" "=w") 5541 (match_operand:TX 1 "register_operand" "w")) 5542 (clobber (match_operand:DI 2 "register_operand" "=&r")) 5543 ] 5544 "TARGET_FLOAT" 5545 { 5546 rtx op0 = simplify_gen_subreg (TImode, operands[0], <MODE>mode, 0); 5547 rtx op1 = simplify_gen_subreg (TImode, operands[1], <MODE>mode, 0); 5548 gen_aarch64_movtilow_tilow (op0, op1); 5549 gen_aarch64_movdi_tihigh (operands[2], op1); 5550 gen_aarch64_movtihigh_di (op0, operands[2]); 5551 DONE; 5552 } 5553) 5554 5555;; The following secondary reload helpers patterns are invoked 5556;; after or during reload as we don't want these patterns to start 5557;; kicking in during the combiner. 5558 5559(define_insn "aarch64_movdi_<mode>low" 5560 [(set (match_operand:DI 0 "register_operand" "=r") 5561 (zero_extract:DI (match_operand:TX 1 "register_operand" "w") 5562 (const_int 64) (const_int 0)))] 5563 "TARGET_FLOAT && (reload_completed || reload_in_progress)" 5564 "fmov\\t%x0, %d1" 5565 [(set_attr "type" "f_mrc") 5566 (set_attr "length" "4") 5567 ]) 5568 5569(define_insn "aarch64_movdi_<mode>high" 5570 [(set (match_operand:DI 0 "register_operand" "=r") 5571 (zero_extract:DI (match_operand:TX 1 "register_operand" "w") 5572 (const_int 64) (const_int 64)))] 5573 "TARGET_FLOAT && (reload_completed || reload_in_progress)" 5574 "fmov\\t%x0, %1.d[1]" 5575 [(set_attr "type" "f_mrc") 5576 (set_attr "length" "4") 5577 ]) 5578 5579(define_insn "aarch64_mov<mode>high_di" 5580 [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w") 5581 (const_int 64) (const_int 64)) 5582 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))] 5583 "TARGET_FLOAT && (reload_completed || reload_in_progress)" 5584 "fmov\\t%0.d[1], %x1" 5585 [(set_attr "type" "f_mcr") 5586 (set_attr "length" "4") 5587 ]) 5588 5589(define_insn "aarch64_mov<mode>low_di" 5590 [(set (match_operand:TX 0 "register_operand" "=w") 5591 (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))] 5592 "TARGET_FLOAT && (reload_completed || reload_in_progress)" 5593 "fmov\\t%d0, %x1" 5594 [(set_attr "type" "f_mcr") 5595 (set_attr "length" "4") 5596 ]) 5597 5598(define_insn "aarch64_movtilow_tilow" 5599 [(set (match_operand:TI 0 "register_operand" "=w") 5600 (zero_extend:TI 5601 (truncate:DI (match_operand:TI 1 "register_operand" "w"))))] 5602 "TARGET_FLOAT && (reload_completed || reload_in_progress)" 5603 "fmov\\t%d0, %d1" 5604 [(set_attr "type" "fmov") 5605 (set_attr "length" "4") 5606 ]) 5607 5608;; There is a deliberate reason why the parameters of high and lo_sum's 5609;; don't have modes for ADRP and ADD instructions. This is to allow high 5610;; and lo_sum's to be used with the labels defining the jump tables in 5611;; rodata section. 5612 5613(define_expand "add_losym" 5614 [(set (match_operand 0 "register_operand" "=r") 5615 (lo_sum (match_operand 1 "register_operand" "r") 5616 (match_operand 2 "aarch64_valid_symref" "S")))] 5617 "" 5618{ 5619 machine_mode mode = GET_MODE (operands[0]); 5620 5621 emit_insn ((mode == DImode 5622 ? gen_add_losym_di 5623 : gen_add_losym_si) (operands[0], 5624 operands[1], 5625 operands[2])); 5626 DONE; 5627}) 5628 5629(define_insn "add_losym_<mode>" 5630 [(set (match_operand:P 0 "register_operand" "=r") 5631 (lo_sum:P (match_operand:P 1 "register_operand" "r") 5632 (match_operand 2 "aarch64_valid_symref" "S")))] 5633 "" 5634 "add\\t%<w>0, %<w>1, :lo12:%c2" 5635 [(set_attr "type" "alu_imm")] 5636) 5637 5638(define_insn "ldr_got_small_<mode>" 5639 [(set (match_operand:PTR 0 "register_operand" "=r") 5640 (unspec:PTR [(mem:PTR (lo_sum:PTR 5641 (match_operand:PTR 1 "register_operand" "r") 5642 (match_operand:PTR 2 "aarch64_valid_symref" "S")))] 5643 UNSPEC_GOTSMALLPIC))] 5644 "" 5645 "ldr\\t%<w>0, [%1, #:got_lo12:%c2]" 5646 [(set_attr "type" "load_<ldst_sz>")] 5647) 5648 5649(define_insn "ldr_got_small_sidi" 5650 [(set (match_operand:DI 0 "register_operand" "=r") 5651 (zero_extend:DI 5652 (unspec:SI [(mem:SI (lo_sum:DI 5653 (match_operand:DI 1 "register_operand" "r") 5654 (match_operand:DI 2 "aarch64_valid_symref" "S")))] 5655 UNSPEC_GOTSMALLPIC)))] 5656 "TARGET_ILP32" 5657 "ldr\\t%w0, [%1, #:got_lo12:%c2]" 5658 [(set_attr "type" "load_4")] 5659) 5660 5661(define_insn "ldr_got_small_28k_<mode>" 5662 [(set (match_operand:PTR 0 "register_operand" "=r") 5663 (unspec:PTR [(mem:PTR (lo_sum:PTR 5664 (match_operand:PTR 1 "register_operand" "r") 5665 (match_operand:PTR 2 "aarch64_valid_symref" "S")))] 5666 UNSPEC_GOTSMALLPIC28K))] 5667 "" 5668 "ldr\\t%<w>0, [%1, #:<got_modifier>:%c2]" 5669 [(set_attr "type" "load_<ldst_sz>")] 5670) 5671 5672(define_insn "ldr_got_small_28k_sidi" 5673 [(set (match_operand:DI 0 "register_operand" "=r") 5674 (zero_extend:DI 5675 (unspec:SI [(mem:SI (lo_sum:DI 5676 (match_operand:DI 1 "register_operand" "r") 5677 (match_operand:DI 2 "aarch64_valid_symref" "S")))] 5678 UNSPEC_GOTSMALLPIC28K)))] 5679 "TARGET_ILP32" 5680 "ldr\\t%w0, [%1, #:gotpage_lo14:%c2]" 5681 [(set_attr "type" "load_4")] 5682) 5683 5684(define_insn "ldr_got_tiny" 5685 [(set (match_operand:DI 0 "register_operand" "=r") 5686 (unspec:DI [(match_operand:DI 1 "aarch64_valid_symref" "S")] 5687 UNSPEC_GOTTINYPIC))] 5688 "" 5689 "ldr\\t%0, %L1" 5690 [(set_attr "type" "load_8")] 5691) 5692 5693(define_insn "aarch64_load_tp_hard" 5694 [(set (match_operand:DI 0 "register_operand" "=r") 5695 (unspec:DI [(const_int 0)] UNSPEC_TLS))] 5696 "" 5697 "mrs\\t%0, tpidr_el0" 5698 [(set_attr "type" "mrs")] 5699) 5700 5701;; The TLS ABI specifically requires that the compiler does not schedule 5702;; instructions in the TLS stubs, in order to enable linker relaxation. 5703;; Therefore we treat the stubs as an atomic sequence. 5704(define_expand "tlsgd_small_<mode>" 5705 [(parallel [(set (match_operand 0 "register_operand" "") 5706 (call (mem:DI (match_dup 2)) (const_int 1))) 5707 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "")] UNSPEC_GOTSMALLTLS) 5708 (clobber (reg:DI LR_REGNUM))])] 5709 "" 5710{ 5711 operands[2] = aarch64_tls_get_addr (); 5712}) 5713 5714(define_insn "*tlsgd_small_<mode>" 5715 [(set (match_operand 0 "register_operand" "") 5716 (call (mem:DI (match_operand:DI 2 "" "")) (const_int 1))) 5717 (unspec:DI [(match_operand:PTR 1 "aarch64_valid_symref" "S")] UNSPEC_GOTSMALLTLS) 5718 (clobber (reg:DI LR_REGNUM)) 5719 ] 5720 "" 5721 "adrp\\tx0, %A1\;add\\tx0, x0, %L1\;bl\\t%2\;nop" 5722 [(set_attr "type" "call") 5723 (set_attr "length" "16")]) 5724 5725(define_insn "tlsie_small_<mode>" 5726 [(set (match_operand:PTR 0 "register_operand" "=r") 5727 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S")] 5728 UNSPEC_GOTSMALLTLS))] 5729 "" 5730 "adrp\\t%0, %A1\;ldr\\t%<w>0, [%0, #%L1]" 5731 [(set_attr "type" "load_4") 5732 (set_attr "length" "8")] 5733) 5734 5735(define_insn "tlsie_small_sidi" 5736 [(set (match_operand:DI 0 "register_operand" "=r") 5737 (zero_extend:DI 5738 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S")] 5739 UNSPEC_GOTSMALLTLS)))] 5740 "" 5741 "adrp\\t%0, %A1\;ldr\\t%w0, [%0, #%L1]" 5742 [(set_attr "type" "load_4") 5743 (set_attr "length" "8")] 5744) 5745 5746(define_insn "tlsie_tiny_<mode>" 5747 [(set (match_operand:PTR 0 "register_operand" "=&r") 5748 (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S") 5749 (match_operand:PTR 2 "register_operand" "r")] 5750 UNSPEC_GOTTINYTLS))] 5751 "" 5752 "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2" 5753 [(set_attr "type" "multiple") 5754 (set_attr "length" "8")] 5755) 5756 5757(define_insn "tlsie_tiny_sidi" 5758 [(set (match_operand:DI 0 "register_operand" "=&r") 5759 (zero_extend:DI 5760 (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S") 5761 (match_operand:DI 2 "register_operand" "r") 5762 ] 5763 UNSPEC_GOTTINYTLS)))] 5764 "" 5765 "ldr\\t%w0, %L1\;add\\t%w0, %w0, %w2" 5766 [(set_attr "type" "multiple") 5767 (set_attr "length" "8")] 5768) 5769 5770(define_insn "tlsle12_<mode>" 5771 [(set (match_operand:P 0 "register_operand" "=r") 5772 (unspec:P [(match_operand:P 1 "register_operand" "r") 5773 (match_operand 2 "aarch64_tls_le_symref" "S")] 5774 UNSPEC_TLSLE12))] 5775 "" 5776 "add\\t%<w>0, %<w>1, #%L2"; 5777 [(set_attr "type" "alu_sreg") 5778 (set_attr "length" "4")] 5779) 5780 5781(define_insn "tlsle24_<mode>" 5782 [(set (match_operand:P 0 "register_operand" "=r") 5783 (unspec:P [(match_operand:P 1 "register_operand" "r") 5784 (match_operand 2 "aarch64_tls_le_symref" "S")] 5785 UNSPEC_TLSLE24))] 5786 "" 5787 "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2" 5788 [(set_attr "type" "multiple") 5789 (set_attr "length" "8")] 5790) 5791 5792(define_insn "tlsle32_<mode>" 5793 [(set (match_operand:P 0 "register_operand" "=r") 5794 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")] 5795 UNSPEC_TLSLE32))] 5796 "" 5797 "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1" 5798 [(set_attr "type" "multiple") 5799 (set_attr "length" "8")] 5800) 5801 5802(define_insn "tlsle48_<mode>" 5803 [(set (match_operand:P 0 "register_operand" "=r") 5804 (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")] 5805 UNSPEC_TLSLE48))] 5806 "" 5807 "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1" 5808 [(set_attr "type" "multiple") 5809 (set_attr "length" "12")] 5810) 5811 5812(define_expand "tlsdesc_small_<mode>" 5813 [(unspec:PTR [(match_operand 0 "aarch64_valid_symref")] UNSPEC_TLSDESC)] 5814 "TARGET_TLS_DESC" 5815 { 5816 if (TARGET_SVE) 5817 emit_insn (gen_tlsdesc_small_sve_<mode> (operands[0])); 5818 else 5819 emit_insn (gen_tlsdesc_small_advsimd_<mode> (operands[0])); 5820 DONE; 5821 } 5822) 5823 5824;; tlsdesc calls preserve all core and Advanced SIMD registers except 5825;; R0 and LR. 5826(define_insn "tlsdesc_small_advsimd_<mode>" 5827 [(set (reg:PTR R0_REGNUM) 5828 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")] 5829 UNSPEC_TLSDESC)) 5830 (clobber (reg:DI LR_REGNUM)) 5831 (clobber (reg:CC CC_REGNUM)) 5832 (clobber (match_scratch:DI 1 "=r"))] 5833 "TARGET_TLS_DESC && !TARGET_SVE" 5834 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1" 5835 [(set_attr "type" "call") 5836 (set_attr "length" "16")]) 5837 5838;; For SVE, model tlsdesc calls as clobbering all vector and predicate 5839;; registers, on top of the usual R0 and LR. In reality the calls 5840;; preserve the low 128 bits of the vector registers, but we don't 5841;; yet have a way of representing that in the instruction pattern. 5842(define_insn "tlsdesc_small_sve_<mode>" 5843 [(set (reg:PTR R0_REGNUM) 5844 (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")] 5845 UNSPEC_TLSDESC)) 5846 (clobber (reg:DI LR_REGNUM)) 5847 (clobber (reg:CC CC_REGNUM)) 5848 (clobber (reg:XI V0_REGNUM)) 5849 (clobber (reg:XI V4_REGNUM)) 5850 (clobber (reg:XI V8_REGNUM)) 5851 (clobber (reg:XI V12_REGNUM)) 5852 (clobber (reg:XI V16_REGNUM)) 5853 (clobber (reg:XI V20_REGNUM)) 5854 (clobber (reg:XI V24_REGNUM)) 5855 (clobber (reg:XI V28_REGNUM)) 5856 (clobber (reg:VNx2BI P0_REGNUM)) 5857 (clobber (reg:VNx2BI P1_REGNUM)) 5858 (clobber (reg:VNx2BI P2_REGNUM)) 5859 (clobber (reg:VNx2BI P3_REGNUM)) 5860 (clobber (reg:VNx2BI P4_REGNUM)) 5861 (clobber (reg:VNx2BI P5_REGNUM)) 5862 (clobber (reg:VNx2BI P6_REGNUM)) 5863 (clobber (reg:VNx2BI P7_REGNUM)) 5864 (clobber (reg:VNx2BI P8_REGNUM)) 5865 (clobber (reg:VNx2BI P9_REGNUM)) 5866 (clobber (reg:VNx2BI P10_REGNUM)) 5867 (clobber (reg:VNx2BI P11_REGNUM)) 5868 (clobber (reg:VNx2BI P12_REGNUM)) 5869 (clobber (reg:VNx2BI P13_REGNUM)) 5870 (clobber (reg:VNx2BI P14_REGNUM)) 5871 (clobber (reg:VNx2BI P15_REGNUM)) 5872 (clobber (match_scratch:DI 1 "=r"))] 5873 "TARGET_TLS_DESC && TARGET_SVE" 5874 "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, %L0\;.tlsdesccall\\t%0\;blr\\t%1" 5875 [(set_attr "type" "call") 5876 (set_attr "length" "16")]) 5877 5878(define_insn "stack_tie" 5879 [(set (mem:BLK (scratch)) 5880 (unspec:BLK [(match_operand:DI 0 "register_operand" "rk") 5881 (match_operand:DI 1 "register_operand" "rk")] 5882 UNSPEC_PRLG_STK))] 5883 "" 5884 "" 5885 [(set_attr "length" "0")] 5886) 5887 5888;; Pointer authentication patterns are always provided. In architecture 5889;; revisions prior to ARMv8.3-A these HINT instructions operate as NOPs. 5890;; This lets the user write portable software which authenticates pointers 5891;; when run on something which implements ARMv8.3-A, and which runs 5892;; correctly, but does not authenticate pointers, where ARMv8.3-A is not 5893;; implemented. 5894 5895;; Signing/Authenticating R30 using SP as the salt. 5896 5897(define_insn "<pauth_mnem_prefix>sp" 5898 [(set (reg:DI R30_REGNUM) 5899 (unspec:DI [(reg:DI R30_REGNUM) (reg:DI SP_REGNUM)] PAUTH_LR_SP))] 5900 "" 5901 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>asp"; 5902) 5903 5904;; Signing/Authenticating X17 using X16 as the salt. 5905 5906(define_insn "<pauth_mnem_prefix>1716" 5907 [(set (reg:DI R17_REGNUM) 5908 (unspec:DI [(reg:DI R17_REGNUM) (reg:DI R16_REGNUM)] PAUTH_17_16))] 5909 "" 5910 "hint\t<pauth_hint_num_a> // <pauth_mnem_prefix>a1716"; 5911) 5912 5913;; Stripping the signature in R30. 5914 5915(define_insn "xpaclri" 5916 [(set (reg:DI R30_REGNUM) (unspec:DI [(reg:DI R30_REGNUM)] UNSPEC_XPACLRI))] 5917 "" 5918 "hint\t7 // xpaclri" 5919) 5920 5921;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and 5922;; all of memory. This blocks insns from being moved across this point. 5923 5924(define_insn "blockage" 5925 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] 5926 "" 5927 "" 5928 [(set_attr "length" "0") 5929 (set_attr "type" "block")] 5930) 5931 5932(define_insn "probe_stack_range" 5933 [(set (match_operand:DI 0 "register_operand" "=r") 5934 (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0") 5935 (match_operand:DI 2 "register_operand" "r")] 5936 UNSPECV_PROBE_STACK_RANGE))] 5937 "" 5938{ 5939 return aarch64_output_probe_stack_range (operands[0], operands[2]); 5940} 5941 [(set_attr "length" "32")] 5942) 5943 5944;; Named pattern for expanding thread pointer reference. 5945(define_expand "get_thread_pointerdi" 5946 [(match_operand:DI 0 "register_operand" "=r")] 5947 "" 5948{ 5949 rtx tmp = aarch64_load_tp (operands[0]); 5950 if (tmp != operands[0]) 5951 emit_move_insn (operands[0], tmp); 5952 DONE; 5953}) 5954 5955;; Named patterns for stack smashing protection. 5956(define_expand "stack_protect_set" 5957 [(match_operand 0 "memory_operand") 5958 (match_operand 1 "memory_operand")] 5959 "" 5960{ 5961 machine_mode mode = GET_MODE (operands[0]); 5962 5963 emit_insn ((mode == DImode 5964 ? gen_stack_protect_set_di 5965 : gen_stack_protect_set_si) (operands[0], operands[1])); 5966 DONE; 5967}) 5968 5969(define_insn "stack_protect_set_<mode>" 5970 [(set (match_operand:PTR 0 "memory_operand" "=m") 5971 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")] 5972 UNSPEC_SP_SET)) 5973 (set (match_scratch:PTR 2 "=&r") (const_int 0))] 5974 "" 5975 "ldr\\t%<w>2, %1\;str\\t%<w>2, %0\;mov\t%<w>2,0" 5976 [(set_attr "length" "12") 5977 (set_attr "type" "multiple")]) 5978 5979(define_expand "stack_protect_test" 5980 [(match_operand 0 "memory_operand") 5981 (match_operand 1 "memory_operand") 5982 (match_operand 2)] 5983 "" 5984{ 5985 rtx result; 5986 machine_mode mode = GET_MODE (operands[0]); 5987 5988 result = gen_reg_rtx(mode); 5989 5990 emit_insn ((mode == DImode 5991 ? gen_stack_protect_test_di 5992 : gen_stack_protect_test_si) (result, 5993 operands[0], 5994 operands[1])); 5995 5996 if (mode == DImode) 5997 emit_jump_insn (gen_cbranchdi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx), 5998 result, const0_rtx, operands[2])); 5999 else 6000 emit_jump_insn (gen_cbranchsi4 (gen_rtx_EQ (VOIDmode, result, const0_rtx), 6001 result, const0_rtx, operands[2])); 6002 DONE; 6003}) 6004 6005(define_insn "stack_protect_test_<mode>" 6006 [(set (match_operand:PTR 0 "register_operand" "=r") 6007 (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m") 6008 (match_operand:PTR 2 "memory_operand" "m")] 6009 UNSPEC_SP_TEST)) 6010 (clobber (match_scratch:PTR 3 "=&r"))] 6011 "" 6012 "ldr\t%<w>3, %1\;ldr\t%<w>0, %2\;eor\t%<w>0, %<w>3, %<w>0" 6013 [(set_attr "length" "12") 6014 (set_attr "type" "multiple")]) 6015 6016;; Write Floating-point Control Register. 6017(define_insn "set_fpcr" 6018 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)] 6019 "" 6020 "msr\\tfpcr, %0" 6021 [(set_attr "type" "mrs")]) 6022 6023;; Read Floating-point Control Register. 6024(define_insn "get_fpcr" 6025 [(set (match_operand:SI 0 "register_operand" "=r") 6026 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))] 6027 "" 6028 "mrs\\t%0, fpcr" 6029 [(set_attr "type" "mrs")]) 6030 6031;; Write Floating-point Status Register. 6032(define_insn "set_fpsr" 6033 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)] 6034 "" 6035 "msr\\tfpsr, %0" 6036 [(set_attr "type" "mrs")]) 6037 6038;; Read Floating-point Status Register. 6039(define_insn "get_fpsr" 6040 [(set (match_operand:SI 0 "register_operand" "=r") 6041 (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))] 6042 "" 6043 "mrs\\t%0, fpsr" 6044 [(set_attr "type" "mrs")]) 6045 6046 6047;; Define the subtract-one-and-jump insns so loop.c 6048;; knows what to generate. 6049(define_expand "doloop_end" 6050 [(use (match_operand 0 "" "")) ; loop pseudo 6051 (use (match_operand 1 "" ""))] ; label 6052 "optimize > 0 && flag_modulo_sched" 6053{ 6054 rtx s0; 6055 rtx bcomp; 6056 rtx loc_ref; 6057 rtx cc_reg; 6058 rtx insn; 6059 rtx cmp; 6060 6061 /* Currently SMS relies on the do-loop pattern to recognize loops 6062 where (1) the control part consists of all insns defining and/or 6063 using a certain 'count' register and (2) the loop count can be 6064 adjusted by modifying this register prior to the loop. 6065 ??? The possible introduction of a new block to initialize the 6066 new IV can potentially affect branch optimizations. */ 6067 6068 if (GET_MODE (operands[0]) != DImode) 6069 FAIL; 6070 6071 s0 = operands [0]; 6072 insn = emit_insn (gen_adddi3_compare0 (s0, s0, GEN_INT (-1))); 6073 6074 cmp = XVECEXP (PATTERN (insn), 0, 0); 6075 cc_reg = SET_DEST (cmp); 6076 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx); 6077 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]); 6078 emit_jump_insn (gen_rtx_SET (pc_rtx, 6079 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, 6080 loc_ref, pc_rtx))); 6081 DONE; 6082}) 6083 6084;; Helper for aarch64.c code. 6085(define_expand "set_clobber_cc" 6086 [(parallel [(set (match_operand 0) 6087 (match_operand 1)) 6088 (clobber (reg:CC CC_REGNUM))])]) 6089 6090;; AdvSIMD Stuff 6091(include "aarch64-simd.md") 6092 6093;; Atomic Operations 6094(include "atomics.md") 6095 6096;; ldp/stp peephole patterns 6097(include "aarch64-ldpstp.md") 6098 6099;; SVE. 6100(include "aarch64-sve.md") 6101