1;; ARM Thumb-2 Machine Description 2;; Copyright (C) 2007-2020 Free Software Foundation, Inc. 3;; Written by CodeSourcery, LLC. 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;; Note: Thumb-2 is the variant of the Thumb architecture that adds 22;; 32-bit encodings of [almost all of] the Arm instruction set. 23;; Some old documents refer to the relatively minor interworking 24;; changes made in armv5t as "thumb2". These are considered part 25;; the 16-bit Thumb-1 instruction set. 26 27;; We use the '0' constraint for operand 1 because reload should 28;; be smart enough to generate an appropriate move for the r/r/r case. 29(define_insn_and_split "*thumb2_smaxsi3" 30 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r") 31 (smax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0") 32 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I"))) 33 (clobber (reg:CC CC_REGNUM))] 34 "TARGET_THUMB2" 35 "#" 36 ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2 37 "TARGET_THUMB2 && reload_completed" 38 [(set (reg:CC CC_REGNUM) 39 (compare:CC (match_dup 1) (match_dup 2))) 40 (cond_exec (lt:SI (reg:CC CC_REGNUM) (const_int 0)) 41 (set (match_dup 0) 42 (match_dup 2)))] 43 "" 44 [(set_attr "conds" "clob") 45 (set_attr "enabled_for_short_it" "yes,yes,no") 46 (set_attr "length" "6,6,10") 47 (set_attr "type" "multiple")] 48) 49 50(define_insn_and_split "*thumb2_sminsi3" 51 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r") 52 (smin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0") 53 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I"))) 54 (clobber (reg:CC CC_REGNUM))] 55 "TARGET_THUMB2" 56 "#" 57 ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2 58 "TARGET_THUMB2 && reload_completed" 59 [(set (reg:CC CC_REGNUM) 60 (compare:CC (match_dup 1) (match_dup 2))) 61 (cond_exec (ge:SI (reg:CC CC_REGNUM) (const_int 0)) 62 (set (match_dup 0) 63 (match_dup 2)))] 64 "" 65 [(set_attr "conds" "clob") 66 (set_attr "enabled_for_short_it" "yes,yes,no") 67 (set_attr "length" "6,6,10") 68 (set_attr "type" "multiple")] 69) 70 71(define_insn_and_split "*thumb32_umaxsi3" 72 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r") 73 (umax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0") 74 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I"))) 75 (clobber (reg:CC CC_REGNUM))] 76 "TARGET_THUMB2" 77 "#" 78 ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2 79 "TARGET_THUMB2 && reload_completed" 80 [(set (reg:CC CC_REGNUM) 81 (compare:CC (match_dup 1) (match_dup 2))) 82 (cond_exec (ltu:SI (reg:CC CC_REGNUM) (const_int 0)) 83 (set (match_dup 0) 84 (match_dup 2)))] 85 "" 86 [(set_attr "conds" "clob") 87 (set_attr "length" "6,6,10") 88 (set_attr "enabled_for_short_it" "yes,yes,no") 89 (set_attr "type" "multiple")] 90) 91 92(define_insn_and_split "*thumb2_uminsi3" 93 [(set (match_operand:SI 0 "s_register_operand" "=r,l,r") 94 (umin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0") 95 (match_operand:SI 2 "arm_rhs_operand" "r,Py,I"))) 96 (clobber (reg:CC CC_REGNUM))] 97 "TARGET_THUMB2" 98 "#" 99 ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2 100 "TARGET_THUMB2 && reload_completed" 101 [(set (reg:CC CC_REGNUM) 102 (compare:CC (match_dup 1) (match_dup 2))) 103 (cond_exec (geu:SI (reg:CC CC_REGNUM) (const_int 0)) 104 (set (match_dup 0) 105 (match_dup 2)))] 106 "" 107 [(set_attr "conds" "clob") 108 (set_attr "length" "6,6,10") 109 (set_attr "enabled_for_short_it" "yes,yes,no") 110 (set_attr "type" "multiple")] 111) 112 113(define_insn_and_split "*thumb2_abssi2" 114 [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r") 115 (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0"))) 116 (clobber (reg:CC CC_REGNUM))] 117 "TARGET_THUMB2" 118 "#" 119 ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31 120 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0 121 ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0 122 "&& reload_completed" 123 [(const_int 0)] 124 { 125 if (REGNO(operands[0]) == REGNO(operands[1])) 126 { 127 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); 128 129 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0], 130 const0_rtx))); 131 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 132 (gen_rtx_LT (SImode, 133 cc_reg, 134 const0_rtx)), 135 (gen_rtx_SET (operands[0], 136 (gen_rtx_MINUS (SImode, 137 const0_rtx, 138 operands[1])))))); 139 } 140 else 141 { 142 emit_insn (gen_rtx_SET (operands[0], 143 gen_rtx_XOR (SImode, 144 gen_rtx_ASHIFTRT (SImode, 145 operands[1], 146 GEN_INT (31)), 147 operands[1]))); 148 emit_insn (gen_rtx_SET (operands[0], 149 gen_rtx_MINUS (SImode, 150 operands[0], 151 gen_rtx_ASHIFTRT (SImode, 152 operands[1], 153 GEN_INT (31))))); 154 } 155 DONE; 156 } 157 [(set_attr "conds" "*,clob,clob") 158 (set_attr "shift" "1") 159 (set_attr "predicable" "yes,no,no") 160 (set_attr "enabled_for_short_it" "yes,yes,no") 161 (set_attr "ce_count" "2") 162 (set_attr "length" "8,6,10") 163 (set_attr "type" "multiple")] 164) 165 166(define_insn_and_split "*thumb2_neg_abssi2" 167 [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r") 168 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0")))) 169 (clobber (reg:CC CC_REGNUM))] 170 "TARGET_THUMB2" 171 "#" 172 ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31 173 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0 174 ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0 175 "&& reload_completed" 176 [(const_int 0)] 177 { 178 if (REGNO(operands[0]) == REGNO(operands[1])) 179 { 180 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); 181 182 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[0], 183 const0_rtx))); 184 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 185 (gen_rtx_GT (SImode, 186 cc_reg, 187 const0_rtx)), 188 (gen_rtx_SET (operands[0], 189 (gen_rtx_MINUS (SImode, 190 const0_rtx, 191 operands[1])))))); 192 } 193 else 194 { 195 emit_insn (gen_rtx_SET (operands[0], 196 gen_rtx_XOR (SImode, 197 gen_rtx_ASHIFTRT (SImode, 198 operands[1], 199 GEN_INT (31)), 200 operands[1]))); 201 emit_insn (gen_rtx_SET (operands[0], 202 gen_rtx_MINUS (SImode, 203 gen_rtx_ASHIFTRT (SImode, 204 operands[1], 205 GEN_INT (31)), 206 operands[0]))); 207 } 208 DONE; 209 } 210 [(set_attr "conds" "*,clob,clob") 211 (set_attr "shift" "1") 212 (set_attr "predicable" "yes,no,no") 213 (set_attr "enabled_for_short_it" "yes,yes,no") 214 (set_attr "ce_count" "2") 215 (set_attr "length" "8,6,10") 216 (set_attr "type" "multiple")] 217) 218 219;; Pop a single register as its size is preferred over a post-incremental load 220(define_insn "*thumb2_pop_single" 221 [(set (match_operand:SI 0 "low_register_operand" "=r") 222 (mem:SI (post_inc:SI (reg:SI SP_REGNUM))))] 223 "TARGET_THUMB2 && (reload_in_progress || reload_completed)" 224 "pop\t{%0}" 225 [(set_attr "type" "load_4") 226 (set_attr "length" "2") 227 (set_attr "predicable" "yes")] 228) 229 230;; We have two alternatives here for memory loads (and similarly for stores) 231;; to reflect the fact that the permissible constant pool ranges differ 232;; between ldr instructions taking low regs and ldr instructions taking high 233;; regs. The high register alternatives are not taken into account when 234;; choosing register preferences in order to reflect their expense. 235(define_insn "*thumb2_movsi_insn" 236 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r,lk*r,m") 237 (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,lk*r"))] 238 "TARGET_THUMB2 && !TARGET_IWMMXT && !TARGET_HARD_FLOAT 239 && ( register_operand (operands[0], SImode) 240 || register_operand (operands[1], SImode))" 241{ 242 switch (which_alternative) 243 { 244 case 0: 245 case 1: 246 case 2: 247 return \"mov%?\\t%0, %1\"; 248 case 3: return \"mvn%?\\t%0, #%B1\"; 249 case 4: return \"movw%?\\t%0, %1\"; 250 case 5: 251 /* Cannot load it directly, split to load it via MOV / MOVT. */ 252 if (!MEM_P (operands[1]) && arm_disable_literal_pool) 253 return \"#\"; 254 return \"ldr%?\\t%0, %1\"; 255 case 6: return \"str%?\\t%1, %0\"; 256 default: gcc_unreachable (); 257 } 258} 259 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mvn_imm,mov_imm,load_4,store_4") 260 (set_attr "length" "2,4,2,4,4,4,4") 261 (set_attr "predicable" "yes") 262 (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no") 263 (set_attr "pool_range" "*,*,*,*,*,1018,*") 264 (set_attr "neg_pool_range" "*,*,*,*,*,0,*")] 265) 266 267(define_insn "tls_load_dot_plus_four" 268 [(set (match_operand:SI 0 "register_operand" "=l,l,r,r") 269 (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1") 270 (const_int 4) 271 (match_operand 3 "" "")] 272 UNSPEC_PIC_BASE))) 273 (clobber (match_scratch:SI 1 "=X,l,X,r"))] 274 "TARGET_THUMB2" 275 "* 276 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\", 277 INTVAL (operands[3])); 278 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\"; 279 " 280 [(set_attr "length" "4,4,6,6") 281 (set_attr "type" "multiple")] 282) 283 284;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot 285;; of the messiness associated with the ARM patterns. 286(define_insn "*thumb2_movhi_insn" 287 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,l,r,m,r") 288 (match_operand:HI 1 "general_operand" "rk,I,Py,n,r,m"))] 289 "TARGET_THUMB2 290 && (register_operand (operands[0], HImode) 291 || register_operand (operands[1], HImode))" 292 "@ 293 mov%?\\t%0, %1\\t%@ movhi 294 mov%?\\t%0, %1\\t%@ movhi 295 mov%?\\t%0, %1\\t%@ movhi 296 movw%?\\t%0, %L1\\t%@ movhi 297 strh%?\\t%1, %0\\t%@ movhi 298 ldrh%?\\t%0, %1\\t%@ movhi" 299 [(set_attr "type" "mov_reg,mov_imm,mov_imm,mov_imm,store_4,load_4") 300 (set_attr "predicable" "yes") 301 (set_attr "predicable_short_it" "yes,no,yes,no,no,no") 302 (set_attr "length" "2,4,2,4,4,4") 303 (set_attr "pool_range" "*,*,*,*,*,4094") 304 (set_attr "neg_pool_range" "*,*,*,*,*,250")] 305) 306 307(define_insn "*thumb2_storewb_pairsi" 308 [(set (match_operand:SI 0 "register_operand" "=&kr") 309 (plus:SI (match_operand:SI 1 "register_operand" "0") 310 (match_operand:SI 2 "const_int_operand" "n"))) 311 (set (mem:SI (plus:SI (match_dup 0) (match_dup 2))) 312 (match_operand:SI 3 "register_operand" "r")) 313 (set (mem:SI (plus:SI (match_dup 0) 314 (match_operand:SI 5 "const_int_operand" "n"))) 315 (match_operand:SI 4 "register_operand" "r"))] 316 "TARGET_THUMB2 317 && INTVAL (operands[5]) == INTVAL (operands[2]) + 4" 318 "strd\\t%3, %4, [%0, %2]!" 319 [(set_attr "type" "store_8")] 320) 321 322(define_insn_and_split "*thumb2_mov_scc" 323 [(set (match_operand:SI 0 "s_register_operand" "=l,r") 324 (match_operator:SI 1 "arm_comparison_operator_mode" 325 [(match_operand 2 "cc_register" "") (const_int 0)]))] 326 "TARGET_THUMB2" 327 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 328 "TARGET_THUMB2" 329 [(set (match_dup 0) 330 (if_then_else:SI (match_dup 1) 331 (const_int 1) 332 (const_int 0)))] 333 "" 334 [(set_attr "conds" "use") 335 (set_attr "enabled_for_short_it" "yes,no") 336 (set_attr "length" "8,10") 337 (set_attr "type" "multiple")] 338) 339 340(define_insn_and_split "*thumb2_mov_negscc" 341 [(set (match_operand:SI 0 "s_register_operand" "=r") 342 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode" 343 [(match_operand 2 "cc_register" "") (const_int 0)])))] 344 "TARGET_THUMB2 345 && !arm_restrict_it 346 && !arm_borrow_operation (operands[1], SImode)" 347 "#" ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 348 "&& true" 349 [(set (match_dup 0) 350 (if_then_else:SI (match_dup 1) 351 (match_dup 3) 352 (const_int 0)))] 353 { 354 operands[3] = GEN_INT (~0); 355 } 356 [(set_attr "conds" "use") 357 (set_attr "length" "10") 358 (set_attr "type" "multiple")] 359) 360 361(define_insn_and_split "*thumb2_mov_negscc_strict_it" 362 [(set (match_operand:SI 0 "low_register_operand" "=l") 363 (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode" 364 [(match_operand 2 "cc_register" "") (const_int 0)])))] 365 "TARGET_THUMB2 366 && arm_restrict_it 367 && !arm_borrow_operation (operands[1], SImode)" 368 "#" ; ";mvn\\t%0, #0 ;it\\t%D1\;mov%D1\\t%0, #0\" 369 "&& reload_completed" 370 [(set (match_dup 0) 371 (match_dup 3)) 372 (cond_exec (match_dup 4) 373 (set (match_dup 0) 374 (const_int 0)))] 375 { 376 operands[3] = GEN_INT (~0); 377 machine_mode mode = GET_MODE (operands[2]); 378 enum rtx_code rc = GET_CODE (operands[1]); 379 380 if (mode == CCFPmode || mode == CCFPEmode) 381 rc = reverse_condition_maybe_unordered (rc); 382 else 383 rc = reverse_condition (rc); 384 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx); 385 386 } 387 [(set_attr "conds" "use") 388 (set_attr "length" "8") 389 (set_attr "type" "multiple")] 390) 391 392(define_insn_and_split "*thumb2_mov_notscc" 393 [(set (match_operand:SI 0 "s_register_operand" "=r") 394 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode" 395 [(match_operand 2 "cc_register" "") (const_int 0)])))] 396 "TARGET_THUMB2 && !arm_restrict_it" 397 "#" ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1" 398 "&& true" 399 [(set (match_dup 0) 400 (if_then_else:SI (match_dup 1) 401 (match_dup 3) 402 (match_dup 4)))] 403 { 404 operands[3] = GEN_INT (~1); 405 operands[4] = GEN_INT (~0); 406 } 407 [(set_attr "conds" "use") 408 (set_attr "length" "10") 409 (set_attr "type" "multiple")] 410) 411 412(define_insn_and_split "*thumb2_mov_notscc_strict_it" 413 [(set (match_operand:SI 0 "low_register_operand" "=l") 414 (not:SI (match_operator:SI 1 "arm_comparison_operator_mode" 415 [(match_operand 2 "cc_register" "") (const_int 0)])))] 416 "TARGET_THUMB2 && arm_restrict_it" 417 "#" ; "mvn %0, #0 ; it%d1 ; lsl%d1 %0, %0, #1" 418 "&& reload_completed" 419 [(set (match_dup 0) 420 (match_dup 3)) 421 (cond_exec (match_dup 4) 422 (set (match_dup 0) 423 (ashift:SI (match_dup 0) 424 (const_int 1))))] 425 { 426 operands[3] = GEN_INT (~0); 427 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]), 428 VOIDmode, operands[2], const0_rtx); 429 } 430 [(set_attr "conds" "use") 431 (set_attr "length" "8") 432 (set_attr "type" "multiple")] 433) 434 435(define_insn_and_split "*thumb2_movsicc_insn" 436 [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,r") 437 (if_then_else:SI 438 (match_operator 3 "arm_comparison_operator" 439 [(match_operand 4 "cc_register" "") (const_int 0)]) 440 (match_operand:SI 1 "arm_not_operand" "0 ,lPy,0 ,0,rI,K,I ,r,rI,K ,K,r") 441 (match_operand:SI 2 "arm_not_operand" "lPy,0 ,rI,K,0 ,0,rI,I,K ,rI,K,r")))] 442 "TARGET_THUMB2" 443 "@ 444 it\\t%D3\;mov%D3\\t%0, %2 445 it\\t%d3\;mov%d3\\t%0, %1 446 it\\t%D3\;mov%D3\\t%0, %2 447 it\\t%D3\;mvn%D3\\t%0, #%B2 448 it\\t%d3\;mov%d3\\t%0, %1 449 it\\t%d3\;mvn%d3\\t%0, #%B1 450 # 451 # 452 # 453 # 454 # 455 #" 456 ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2 457 ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2 458 ; alt 8: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 459 ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 460 ; alt 10: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2 461 ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2 462 "&& reload_completed" 463 [(const_int 0)] 464 { 465 enum rtx_code rev_code; 466 machine_mode mode; 467 rtx rev_cond; 468 469 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 470 operands[3], 471 gen_rtx_SET (operands[0], operands[1]))); 472 rev_code = GET_CODE (operands[3]); 473 mode = GET_MODE (operands[4]); 474 if (mode == CCFPmode || mode == CCFPEmode) 475 rev_code = reverse_condition_maybe_unordered (rev_code); 476 else 477 rev_code = reverse_condition (rev_code); 478 479 rev_cond = gen_rtx_fmt_ee (rev_code, 480 VOIDmode, 481 gen_rtx_REG (mode, CC_REGNUM), 482 const0_rtx); 483 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 484 rev_cond, 485 gen_rtx_SET (operands[0], operands[2]))); 486 DONE; 487 } 488 [(set_attr "length" "4,4,6,6,6,6,10,8,10,10,10,6") 489 (set_attr "enabled_for_short_it" "yes,yes,no,no,no,no,no,no,no,no,no,yes") 490 (set_attr "conds" "use") 491 (set_attr_alternative "type" 492 [(if_then_else (match_operand 2 "const_int_operand" "") 493 (const_string "mov_imm") 494 (const_string "mov_reg")) 495 (if_then_else (match_operand 1 "const_int_operand" "") 496 (const_string "mov_imm") 497 (const_string "mov_reg")) 498 (if_then_else (match_operand 2 "const_int_operand" "") 499 (const_string "mov_imm") 500 (const_string "mov_reg")) 501 (const_string "mvn_imm") 502 (if_then_else (match_operand 1 "const_int_operand" "") 503 (const_string "mov_imm") 504 (const_string "mov_reg")) 505 (const_string "mvn_imm") 506 (const_string "multiple") 507 (const_string "multiple") 508 (const_string "multiple") 509 (const_string "multiple") 510 (const_string "multiple") 511 (const_string "multiple")])] 512) 513 514(define_insn "*thumb2_movsfcc_soft_insn" 515 [(set (match_operand:SF 0 "s_register_operand" "=r,r") 516 (if_then_else:SF (match_operator 3 "arm_comparison_operator" 517 [(match_operand 4 "cc_register" "") (const_int 0)]) 518 (match_operand:SF 1 "s_register_operand" "0,r") 519 (match_operand:SF 2 "s_register_operand" "r,0")))] 520 "TARGET_THUMB2 && TARGET_SOFT_FLOAT && !TARGET_HAVE_MVE" 521 "@ 522 it\\t%D3\;mov%D3\\t%0, %2 523 it\\t%d3\;mov%d3\\t%0, %1" 524 [(set_attr "length" "6,6") 525 (set_attr "conds" "use") 526 (set_attr "type" "multiple")] 527) 528 529(define_insn "*call_reg_thumb2" 530 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 531 (match_operand 1 "" "")) 532 (use (match_operand 2 "" "")) 533 (clobber (reg:SI LR_REGNUM))] 534 "TARGET_THUMB2" 535 "blx%?\\t%0" 536 [(set_attr "type" "call")] 537) 538 539(define_insn "*nonsecure_call_reg_thumb2_fpcxt" 540 [(call (unspec:SI [(mem:SI (match_operand:SI 0 "s_register_operand" "l*r"))] 541 UNSPEC_NONSECURE_MEM) 542 (match_operand 1 "" "")) 543 (use (match_operand 2 "" "")) 544 (clobber (reg:SI LR_REGNUM))] 545 "TARGET_THUMB2 && use_cmse && TARGET_HAVE_FPCXT_CMSE" 546 "blxns\\t%0" 547 [(set_attr "length" "4") 548 (set_attr "type" "call")] 549) 550 551(define_insn "*nonsecure_call_reg_thumb2" 552 [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))] 553 UNSPEC_NONSECURE_MEM) 554 (match_operand 0 "" "")) 555 (use (match_operand 1 "" "")) 556 (clobber (reg:SI LR_REGNUM))] 557 "TARGET_THUMB2 && use_cmse && !TARGET_HAVE_FPCXT_CMSE" 558 "bl\\t__gnu_cmse_nonsecure_call" 559 [(set_attr "length" "4") 560 (set_attr "type" "call")] 561) 562 563(define_insn "*call_value_reg_thumb2" 564 [(set (match_operand 0 "" "") 565 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 566 (match_operand 2 "" ""))) 567 (use (match_operand 3 "" "")) 568 (clobber (reg:SI LR_REGNUM))] 569 "TARGET_THUMB2" 570 "blx\\t%1" 571 [(set_attr "type" "call")] 572) 573 574(define_insn "*nonsecure_call_value_reg_thumb2_fpcxt" 575 [(set (match_operand 0 "" "") 576 (call 577 (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))] 578 UNSPEC_NONSECURE_MEM) 579 (match_operand 2 "" ""))) 580 (use (match_operand 3 "" "")) 581 (clobber (reg:SI LR_REGNUM))] 582 "TARGET_THUMB2 && use_cmse && TARGET_HAVE_FPCXT_CMSE" 583 "blxns\\t%1" 584 [(set_attr "length" "4") 585 (set_attr "type" "call")] 586) 587 588(define_insn "*nonsecure_call_value_reg_thumb2" 589 [(set (match_operand 0 "" "") 590 (call 591 (unspec:SI [(mem:SI (reg:SI R4_REGNUM))] UNSPEC_NONSECURE_MEM) 592 (match_operand 1 "" ""))) 593 (use (match_operand 2 "" "")) 594 (clobber (reg:SI LR_REGNUM))] 595 "TARGET_THUMB2 && use_cmse && !TARGET_HAVE_FPCXT_CMSE" 596 "bl\\t__gnu_cmse_nonsecure_call" 597 [(set_attr "length" "4") 598 (set_attr "type" "call")] 599) 600 601(define_insn "*thumb2_indirect_jump" 602 [(set (pc) 603 (match_operand:SI 0 "register_operand" "l*r"))] 604 "TARGET_THUMB2" 605 "bx\\t%0" 606 [(set_attr "conds" "clob") 607 (set_attr "type" "branch")] 608) 609;; Don't define thumb2_load_indirect_jump because we can't guarantee label 610;; addresses will have the thumb bit set correctly. 611 612 613(define_insn_and_split "*thumb2_and_scc" 614 [(set (match_operand:SI 0 "s_register_operand" "=Ts") 615 (and:SI (match_operator:SI 1 "arm_comparison_operator" 616 [(match_operand 2 "cc_register" "") (const_int 0)]) 617 (match_operand:SI 3 "s_register_operand" "r")))] 618 "TARGET_THUMB2" 619 "#" ; "and\\t%0, %3, #1\;it\\t%D1\;mov%D1\\t%0, #0" 620 "&& reload_completed" 621 [(set (match_dup 0) 622 (and:SI (match_dup 3) (const_int 1))) 623 (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))] 624 { 625 machine_mode mode = GET_MODE (operands[2]); 626 enum rtx_code rc = GET_CODE (operands[1]); 627 628 if (mode == CCFPmode || mode == CCFPEmode) 629 rc = reverse_condition_maybe_unordered (rc); 630 else 631 rc = reverse_condition (rc); 632 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx); 633 } 634 [(set_attr "conds" "use") 635 (set_attr "type" "multiple") 636 (set (attr "length") (if_then_else (match_test "arm_restrict_it") 637 (const_int 8) 638 (const_int 10)))] 639) 640 641(define_insn_and_split "*thumb2_ior_scc" 642 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 643 (ior:SI (match_operator:SI 1 "arm_comparison_operator" 644 [(match_operand 2 "cc_register" "") (const_int 0)]) 645 (match_operand:SI 3 "s_register_operand" "0,?r")))] 646 "TARGET_THUMB2 && !arm_restrict_it" 647 "@ 648 it\\t%d1\;orr%d1\\t%0, %3, #1 649 #" 650 ; alt 1: ite\\t%D1\;mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1 651 "&& reload_completed 652 && REGNO (operands [0]) != REGNO (operands[3])" 653 [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3))) 654 (cond_exec (match_dup 4) (set (match_dup 0) 655 (ior:SI (match_dup 3) (const_int 1))))] 656 { 657 machine_mode mode = GET_MODE (operands[2]); 658 enum rtx_code rc = GET_CODE (operands[1]); 659 660 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx); 661 if (mode == CCFPmode || mode == CCFPEmode) 662 rc = reverse_condition_maybe_unordered (rc); 663 else 664 rc = reverse_condition (rc); 665 operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx); 666 } 667 [(set_attr "conds" "use") 668 (set_attr "length" "6,10") 669 (set_attr "type" "multiple")] 670) 671 672(define_insn_and_split "*thumb2_ior_scc_strict_it" 673 [(set (match_operand:SI 0 "s_register_operand" "=&r") 674 (ior:SI (match_operator:SI 2 "arm_comparison_operator" 675 [(match_operand 3 "cc_register" "") (const_int 0)]) 676 (match_operand:SI 1 "s_register_operand" "r")))] 677 "TARGET_THUMB2 && arm_restrict_it" 678 "#" ; orr\\t%0, %1, #1\;it\\t%D2\;mov%D2\\t%0, %1 679 "&& reload_completed" 680 [(set (match_dup 0) (ior:SI (match_dup 1) (const_int 1))) 681 (cond_exec (match_dup 4) 682 (set (match_dup 0) (match_dup 1)))] 683 { 684 machine_mode mode = GET_MODE (operands[3]); 685 rtx_code rc = GET_CODE (operands[2]); 686 687 if (mode == CCFPmode || mode == CCFPEmode) 688 rc = reverse_condition_maybe_unordered (rc); 689 else 690 rc = reverse_condition (rc); 691 operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx); 692 } 693 [(set_attr "conds" "use") 694 (set_attr "length" "8") 695 (set_attr "type" "multiple")] 696) 697 698(define_insn "*thumb2_cond_move" 699 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 700 (if_then_else:SI (match_operator 3 "equality_operator" 701 [(match_operator 4 "arm_comparison_operator" 702 [(match_operand 5 "cc_register" "") (const_int 0)]) 703 (const_int 0)]) 704 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 705 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 706 "TARGET_THUMB2" 707 "* 708 if (GET_CODE (operands[3]) == NE) 709 { 710 if (which_alternative != 1) 711 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands); 712 if (which_alternative != 0) 713 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands); 714 return \"\"; 715 } 716 switch (which_alternative) 717 { 718 case 0: 719 output_asm_insn (\"it\\t%d4\", operands); 720 break; 721 case 1: 722 output_asm_insn (\"it\\t%D4\", operands); 723 break; 724 case 2: 725 if (arm_restrict_it) 726 output_asm_insn (\"it\\t%D4\", operands); 727 else 728 output_asm_insn (\"ite\\t%D4\", operands); 729 break; 730 default: 731 abort(); 732 } 733 if (which_alternative != 0) 734 { 735 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 736 if (arm_restrict_it && which_alternative == 2) 737 output_asm_insn (\"it\\t%d4\", operands); 738 } 739 if (which_alternative != 1) 740 output_asm_insn (\"mov%d4\\t%0, %2\", operands); 741 return \"\"; 742 " 743 [(set_attr "conds" "use") 744 (set_attr "length" "6,6,10") 745 (set_attr "type" "multiple")] 746) 747 748(define_insn "*thumb2_cond_arith" 749 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 750 (match_operator:SI 5 "shiftable_operator" 751 [(match_operator:SI 4 "arm_comparison_operator" 752 [(match_operand:SI 2 "s_register_operand" "r,r") 753 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 754 (match_operand:SI 1 "s_register_operand" "0,?r")])) 755 (clobber (reg:CC CC_REGNUM))] 756 "TARGET_THUMB2 && !arm_restrict_it" 757 "* 758 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 759 return \"%i5\\t%0, %1, %2, lsr #31\"; 760 761 output_asm_insn (\"cmp\\t%2, %3\", operands); 762 if (GET_CODE (operands[5]) == AND) 763 { 764 output_asm_insn (\"ite\\t%D4\", operands); 765 output_asm_insn (\"mov%D4\\t%0, #0\", operands); 766 } 767 else if (GET_CODE (operands[5]) == MINUS) 768 { 769 output_asm_insn (\"ite\\t%D4\", operands); 770 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 771 } 772 else if (which_alternative != 0) 773 { 774 output_asm_insn (\"ite\\t%D4\", operands); 775 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 776 } 777 else 778 output_asm_insn (\"it\\t%d4\", operands); 779 return \"%i5%d4\\t%0, %1, #1\"; 780 " 781 [(set_attr "conds" "clob") 782 (set_attr "length" "14") 783 (set_attr "type" "multiple")] 784) 785 786(define_insn_and_split "*thumb2_cond_arith_strict_it" 787 [(set (match_operand:SI 0 "s_register_operand" "=l") 788 (match_operator:SI 5 "shiftable_operator_strict_it" 789 [(match_operator:SI 4 "arm_comparison_operator" 790 [(match_operand:SI 2 "s_register_operand" "r") 791 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 792 (match_operand:SI 1 "s_register_operand" "0")])) 793 (clobber (reg:CC CC_REGNUM))] 794 "TARGET_THUMB2 && arm_restrict_it" 795 "#" 796 "&& reload_completed" 797 [(const_int 0)] 798 { 799 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 800 { 801 /* %i5 %0, %1, %2, lsr #31 */ 802 rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31)); 803 rtx op = NULL_RTX; 804 805 switch (GET_CODE (operands[5])) 806 { 807 case AND: 808 op = gen_rtx_AND (SImode, shifted_op, operands[1]); 809 break; 810 case PLUS: 811 op = gen_rtx_PLUS (SImode, shifted_op, operands[1]); 812 break; 813 default: gcc_unreachable (); 814 } 815 emit_insn (gen_rtx_SET (operands[0], op)); 816 DONE; 817 } 818 819 /* "cmp %2, %3" */ 820 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM), 821 gen_rtx_COMPARE (CCmode, operands[2], 822 operands[3]))); 823 824 if (GET_CODE (operands[5]) == AND) 825 { 826 /* %i5 %0, %1, #1 827 it%D4 828 mov%D4 %0, #0 */ 829 enum rtx_code rc = reverse_condition (GET_CODE (operands[4])); 830 emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1], 831 GEN_INT (1)))); 832 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 833 gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx), 834 gen_rtx_SET (operands[0], const0_rtx))); 835 DONE; 836 } 837 else 838 { 839 /* it\\t%d4 840 %i5%d4\\t%0, %1, #1 */ 841 emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]), 842 VOIDmode, 843 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx), 844 gen_rtx_SET (operands[0], 845 gen_rtx_PLUS (SImode, 846 operands[1], 847 GEN_INT (1))))); 848 DONE; 849 } 850 FAIL; 851 } 852 [(set_attr "conds" "clob") 853 (set_attr "length" "12") 854 (set_attr "type" "multiple")] 855) 856 857(define_insn "*thumb2_cond_sub" 858 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts") 859 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts") 860 (match_operator:SI 4 "arm_comparison_operator" 861 [(match_operand:SI 2 "s_register_operand" "r,r") 862 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 863 (clobber (reg:CC CC_REGNUM))] 864 "TARGET_THUMB2" 865 "* 866 output_asm_insn (\"cmp\\t%2, %3\", operands); 867 if (which_alternative != 0) 868 { 869 if (arm_restrict_it) 870 { 871 output_asm_insn (\"mov\\t%0, %1\", operands); 872 output_asm_insn (\"it\\t%d4\", operands); 873 } 874 else 875 { 876 output_asm_insn (\"ite\\t%D4\", operands); 877 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 878 } 879 } 880 else 881 output_asm_insn (\"it\\t%d4\", operands); 882 return \"sub%d4\\t%0, %1, #1\"; 883 " 884 [(set_attr "conds" "clob") 885 (set_attr "length" "10,14") 886 (set_attr "type" "multiple")] 887) 888 889(define_insn_and_split "*thumb2_negscc" 890 [(set (match_operand:SI 0 "s_register_operand" "=Ts") 891 (neg:SI (match_operator 3 "arm_comparison_operator" 892 [(match_operand:SI 1 "s_register_operand" "r") 893 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 894 (clobber (reg:CC CC_REGNUM))] 895 "TARGET_THUMB2" 896 "#" 897 "&& reload_completed" 898 [(const_int 0)] 899 { 900 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); 901 902 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx) 903 { 904 /* Emit asr\\t%0, %1, #31 */ 905 emit_insn (gen_rtx_SET (operands[0], 906 gen_rtx_ASHIFTRT (SImode, 907 operands[1], 908 GEN_INT (31)))); 909 DONE; 910 } 911 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it) 912 { 913 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */ 914 if (CONST_INT_P (operands[2])) 915 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2], 916 gen_int_mode (-INTVAL (operands[2]), 917 SImode))); 918 else 919 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2])); 920 921 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 922 gen_rtx_NE (SImode, 923 cc_reg, 924 const0_rtx), 925 gen_rtx_SET (operands[0], 926 GEN_INT (~0)))); 927 DONE; 928 } 929 else 930 { 931 /* Emit: cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/ 932 enum rtx_code rc = reverse_condition (GET_CODE (operands[3])); 933 machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]); 934 rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM); 935 936 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1], 937 operands[2]))); 938 939 emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0))); 940 941 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 942 gen_rtx_fmt_ee (rc, 943 VOIDmode, 944 tmp1, 945 const0_rtx), 946 gen_rtx_SET (operands[0], const0_rtx))); 947 DONE; 948 } 949 FAIL; 950 } 951 [(set_attr "conds" "clob") 952 (set_attr "length" "14") 953 (set_attr "type" "multiple")] 954) 955 956(define_insn "*thumb2_movcond" 957 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts") 958 (if_then_else:SI 959 (match_operator 5 "arm_comparison_operator" 960 [(match_operand:SI 3 "s_register_operand" "r,r,r") 961 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 962 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI") 963 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI"))) 964 (clobber (reg:CC CC_REGNUM))] 965 "TARGET_THUMB2" 966 "* 967 if (GET_CODE (operands[5]) == LT 968 && (operands[4] == const0_rtx)) 969 { 970 if (which_alternative != 1 && REG_P (operands[1])) 971 { 972 if (operands[2] == const0_rtx) 973 return \"and\\t%0, %1, %3, asr #31\"; 974 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\"; 975 } 976 else if (which_alternative != 0 && REG_P (operands[2])) 977 { 978 if (operands[1] == const0_rtx) 979 return \"bic\\t%0, %2, %3, asr #31\"; 980 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\"; 981 } 982 /* The only case that falls through to here is when both ops 1 & 2 983 are constants. */ 984 } 985 986 if (GET_CODE (operands[5]) == GE 987 && (operands[4] == const0_rtx)) 988 { 989 if (which_alternative != 1 && REG_P (operands[1])) 990 { 991 if (operands[2] == const0_rtx) 992 return \"bic\\t%0, %1, %3, asr #31\"; 993 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\"; 994 } 995 else if (which_alternative != 0 && REG_P (operands[2])) 996 { 997 if (operands[1] == const0_rtx) 998 return \"and\\t%0, %2, %3, asr #31\"; 999 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\"; 1000 } 1001 /* The only case that falls through to here is when both ops 1 & 2 1002 are constants. */ 1003 } 1004 if (CONST_INT_P (operands[4]) 1005 && !const_ok_for_arm (INTVAL (operands[4]))) 1006 output_asm_insn (\"cmn\\t%3, #%n4\", operands); 1007 else 1008 output_asm_insn (\"cmp\\t%3, %4\", operands); 1009 switch (which_alternative) 1010 { 1011 case 0: 1012 output_asm_insn (\"it\\t%D5\", operands); 1013 break; 1014 case 1: 1015 output_asm_insn (\"it\\t%d5\", operands); 1016 break; 1017 case 2: 1018 if (arm_restrict_it) 1019 { 1020 output_asm_insn (\"mov\\t%0, %1\", operands); 1021 output_asm_insn (\"it\\t%D5\", operands); 1022 } 1023 else 1024 output_asm_insn (\"ite\\t%d5\", operands); 1025 break; 1026 default: 1027 abort(); 1028 } 1029 if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2)) 1030 output_asm_insn (\"mov%d5\\t%0, %1\", operands); 1031 if (which_alternative != 1) 1032 output_asm_insn (\"mov%D5\\t%0, %2\", operands); 1033 return \"\"; 1034 " 1035 [(set_attr "conds" "clob") 1036 (set_attr "length" "10,10,14") 1037 (set_attr "type" "multiple")] 1038) 1039 1040;; Zero and sign extension instructions. 1041 1042;; All supported Thumb2 implementations are armv6, so only that case is 1043;; provided. 1044(define_insn "*thumb2_extendqisi_v6" 1045 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1046 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 1047 "TARGET_THUMB2 && arm_arch6" 1048 "@ 1049 sxtb%?\\t%0, %1 1050 ldrsb%?\\t%0, %1" 1051 [(set_attr "type" "extend,load_byte") 1052 (set_attr "predicable" "yes") 1053 (set_attr "pool_range" "*,4094") 1054 (set_attr "neg_pool_range" "*,250")] 1055) 1056 1057(define_insn "*thumb2_zero_extendhisi2_v6" 1058 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1059 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] 1060 "TARGET_THUMB2 && arm_arch6" 1061 "@ 1062 uxth%?\\t%0, %1 1063 ldrh%?\\t%0, %1" 1064 [(set_attr "type" "extend,load_byte") 1065 (set_attr "predicable" "yes") 1066 (set_attr "pool_range" "*,4094") 1067 (set_attr "neg_pool_range" "*,250")] 1068) 1069 1070(define_insn "thumb2_zero_extendqisi2_v6" 1071 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1072 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 1073 "TARGET_THUMB2 && arm_arch6" 1074 "@ 1075 uxtb%?\\t%0, %1 1076 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2" 1077 [(set_attr "type" "extend,load_byte") 1078 (set_attr "predicable" "yes") 1079 (set_attr "pool_range" "*,4094") 1080 (set_attr "neg_pool_range" "*,250")] 1081) 1082 1083(define_expand "thumb2_casesi_internal" 1084 [(parallel [(set (pc) 1085 (if_then_else 1086 (leu (match_operand:SI 0 "s_register_operand") 1087 (match_operand:SI 1 "arm_rhs_operand")) 1088 (match_dup 4) 1089 (label_ref:SI (match_operand 3 "")))) 1090 (clobber (reg:CC CC_REGNUM)) 1091 (clobber (match_scratch:SI 5)) 1092 (use (label_ref:SI (match_operand 2 "")))])] 1093 "TARGET_THUMB2 && !flag_pic" 1094{ 1095 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4)); 1096 operands[4] = gen_rtx_PLUS (SImode, operands[4], 1097 gen_rtx_LABEL_REF (SImode, operands[2])); 1098 operands[4] = gen_rtx_MEM (SImode, operands[4]); 1099 MEM_READONLY_P (operands[4]) = 1; 1100 MEM_NOTRAP_P (operands[4]) = 1; 1101}) 1102 1103(define_insn "*thumb2_casesi_internal" 1104 [(parallel [(set (pc) 1105 (if_then_else 1106 (leu (match_operand:SI 0 "s_register_operand" "r") 1107 (match_operand:SI 1 "arm_rhs_operand" "rI")) 1108 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 1109 (label_ref:SI (match_operand 2 "" "")))) 1110 (label_ref:SI (match_operand 3 "" "")))) 1111 (clobber (reg:CC CC_REGNUM)) 1112 (clobber (match_scratch:SI 4 "=&r")) 1113 (use (label_ref:SI (match_dup 2)))])] 1114 "TARGET_THUMB2 && !flag_pic" 1115 "* return thumb2_output_casesi(operands);" 1116 [(set_attr "conds" "clob") 1117 (set_attr "length" "16") 1118 (set_attr "type" "multiple")] 1119) 1120 1121(define_expand "thumb2_casesi_internal_pic" 1122 [(parallel [(set (pc) 1123 (if_then_else 1124 (leu (match_operand:SI 0 "s_register_operand") 1125 (match_operand:SI 1 "arm_rhs_operand")) 1126 (match_dup 4) 1127 (label_ref:SI (match_operand 3 "")))) 1128 (clobber (reg:CC CC_REGNUM)) 1129 (clobber (match_scratch:SI 5)) 1130 (clobber (match_scratch:SI 6)) 1131 (use (label_ref:SI (match_operand 2 "")))])] 1132 "TARGET_THUMB2 && flag_pic" 1133{ 1134 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4)); 1135 operands[4] = gen_rtx_PLUS (SImode, operands[4], 1136 gen_rtx_LABEL_REF (SImode, operands[2])); 1137 operands[4] = gen_rtx_MEM (SImode, operands[4]); 1138 MEM_READONLY_P (operands[4]) = 1; 1139 MEM_NOTRAP_P (operands[4]) = 1; 1140}) 1141 1142(define_insn "*thumb2_casesi_internal_pic" 1143 [(parallel [(set (pc) 1144 (if_then_else 1145 (leu (match_operand:SI 0 "s_register_operand" "r") 1146 (match_operand:SI 1 "arm_rhs_operand" "rI")) 1147 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 1148 (label_ref:SI (match_operand 2 "" "")))) 1149 (label_ref:SI (match_operand 3 "" "")))) 1150 (clobber (reg:CC CC_REGNUM)) 1151 (clobber (match_scratch:SI 4 "=&r")) 1152 (clobber (match_scratch:SI 5 "=r")) 1153 (use (label_ref:SI (match_dup 2)))])] 1154 "TARGET_THUMB2 && flag_pic" 1155 "* return thumb2_output_casesi(operands);" 1156 [(set_attr "conds" "clob") 1157 (set_attr "length" "20") 1158 (set_attr "type" "multiple")] 1159) 1160 1161(define_insn "*thumb2_return" 1162 [(simple_return)] 1163 "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())" 1164 "* return output_return_instruction (const_true_rtx, true, false, true);" 1165 [(set_attr "type" "branch") 1166 (set_attr "length" "4")] 1167) 1168 1169(define_insn "*thumb2_cmse_entry_return" 1170 [(simple_return)] 1171 "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())" 1172 "* return output_return_instruction (const_true_rtx, true, false, true);" 1173 [(set_attr "type" "branch") 1174 ; This is a return from a cmse_nonsecure_entry function so code will be 1175 ; added to clear the APSR and potentially the FPSCR if VFP is available, so 1176 ; we adapt the length accordingly. 1177 (set (attr "length") 1178 (if_then_else (match_test "TARGET_HARD_FLOAT") 1179 (const_int 34) 1180 (const_int 8))) 1181 ; We do not support predicate execution of returns from cmse_nonsecure_entry 1182 ; functions because we need to clear the APSR. Since predicable has to be 1183 ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry 1184 ; functions. 1185 (set_attr "predicable" "no")] 1186) 1187 1188(define_insn_and_split "thumb2_eh_return" 1189 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")] 1190 VUNSPEC_EH_RETURN) 1191 (clobber (match_scratch:SI 1 "=&r"))] 1192 "TARGET_THUMB2" 1193 "#" 1194 "&& reload_completed" 1195 [(const_int 0)] 1196 " 1197 { 1198 thumb_set_return_address (operands[0], operands[1]); 1199 DONE; 1200 }" 1201) 1202 1203(define_insn "*thumb2_alusi3_short" 1204 [(set (match_operand:SI 0 "s_register_operand" "=l") 1205 (match_operator:SI 3 "thumb_16bit_operator" 1206 [(match_operand:SI 1 "s_register_operand" "0") 1207 (match_operand:SI 2 "s_register_operand" "l")])) 1208 (clobber (reg:CC CC_REGNUM))] 1209 "TARGET_THUMB2 && reload_completed 1210 && GET_CODE(operands[3]) != PLUS 1211 && GET_CODE(operands[3]) != MINUS" 1212 "%I3%!\\t%0, %1, %2" 1213 [(set_attr "predicable" "yes") 1214 (set_attr "length" "2") 1215 (set_attr "type" "alu_sreg")] 1216) 1217 1218(define_insn "*thumb2_shiftsi3_short" 1219 [(set (match_operand:SI 0 "low_register_operand" "=l,l") 1220 (match_operator:SI 3 "shift_operator" 1221 [(match_operand:SI 1 "low_register_operand" "0,l") 1222 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")])) 1223 (clobber (reg:CC CC_REGNUM))] 1224 "TARGET_THUMB2 && reload_completed 1225 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) 1226 || REG_P (operands[2]))" 1227 "* return arm_output_shift(operands, 2);" 1228 [(set_attr "predicable" "yes") 1229 (set_attr "shift" "1") 1230 (set_attr "length" "2") 1231 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 1232 (const_string "alu_shift_imm") 1233 (const_string "alu_shift_reg")))] 1234) 1235 1236(define_insn "*thumb2_mov<mode>_shortim" 1237 [(set (match_operand:QHSI 0 "low_register_operand" "=l") 1238 (match_operand:QHSI 1 "const_int_operand" "I")) 1239 (clobber (reg:CC CC_REGNUM))] 1240 "TARGET_THUMB2 && reload_completed" 1241 "mov%!\t%0, %1" 1242 [(set_attr "predicable" "yes") 1243 (set_attr "length" "2") 1244 (set_attr "type" "mov_imm")] 1245) 1246 1247(define_insn "*thumb2_addsi_short" 1248 [(set (match_operand:SI 0 "low_register_operand" "=l,l") 1249 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0") 1250 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps"))) 1251 (clobber (reg:CC CC_REGNUM))] 1252 "TARGET_THUMB2 && reload_completed" 1253 "* 1254 HOST_WIDE_INT val; 1255 1256 if (CONST_INT_P (operands[2])) 1257 val = INTVAL(operands[2]); 1258 else 1259 val = 0; 1260 1261 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */ 1262 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val))) 1263 return \"sub%!\\t%0, %1, #%n2\"; 1264 else 1265 return \"add%!\\t%0, %1, %2\"; 1266 " 1267 [(set_attr "predicable" "yes") 1268 (set_attr "length" "2") 1269 (set_attr_alternative "type" 1270 [(if_then_else (match_operand 2 "const_int_operand" "") 1271 (const_string "alu_imm") 1272 (const_string "alu_sreg")) 1273 (const_string "alu_imm")])] 1274) 1275 1276(define_insn "*thumb2_subsi_short" 1277 [(set (match_operand:SI 0 "low_register_operand" "=l") 1278 (minus:SI (match_operand:SI 1 "low_register_operand" "l") 1279 (match_operand:SI 2 "low_register_operand" "l"))) 1280 (clobber (reg:CC CC_REGNUM))] 1281 "TARGET_THUMB2 && reload_completed" 1282 "sub%!\\t%0, %1, %2" 1283 [(set_attr "predicable" "yes") 1284 (set_attr "length" "2") 1285 (set_attr "type" "alu_sreg")] 1286) 1287 1288(define_peephole2 1289 [(set (match_operand:CC 0 "cc_register" "") 1290 (compare:CC (match_operand:SI 1 "low_register_operand" "") 1291 (match_operand:SI 2 "const_int_operand" "")))] 1292 "TARGET_THUMB2 1293 && peep2_reg_dead_p (1, operands[1]) 1294 && satisfies_constraint_Pw (operands[2])" 1295 [(parallel 1296 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2))) 1297 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])] 1298 "operands[3] = GEN_INT (- INTVAL (operands[2]));" 1299) 1300 1301(define_peephole2 1302 [(match_scratch:SI 3 "l") 1303 (set (match_operand:CC 0 "cc_register" "") 1304 (compare:CC (match_operand:SI 1 "low_register_operand" "") 1305 (match_operand:SI 2 "const_int_operand" "")))] 1306 "TARGET_THUMB2 1307 && satisfies_constraint_Px (operands[2])" 1308 [(parallel 1309 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2))) 1310 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])] 1311 "operands[4] = GEN_INT (- INTVAL (operands[2]));" 1312) 1313 1314(define_insn "thumb2_addsi3_compare0" 1315 [(set (reg:CC_NZ CC_REGNUM) 1316 (compare:CC_NZ 1317 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r") 1318 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL")) 1319 (const_int 0))) 1320 (set (match_operand:SI 0 "s_register_operand" "=l,l,r") 1321 (plus:SI (match_dup 1) (match_dup 2)))] 1322 "TARGET_THUMB2" 1323 "* 1324 HOST_WIDE_INT val; 1325 1326 if (CONST_INT_P (operands[2])) 1327 val = INTVAL (operands[2]); 1328 else 1329 val = 0; 1330 1331 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val))) 1332 return \"subs\\t%0, %1, #%n2\"; 1333 else 1334 return \"adds\\t%0, %1, %2\"; 1335 " 1336 [(set_attr "conds" "set") 1337 (set_attr "length" "2,2,4") 1338 (set_attr_alternative "type" 1339 [(if_then_else (match_operand 2 "const_int_operand" "") 1340 (const_string "alus_imm") 1341 (const_string "alus_sreg")) 1342 (const_string "alus_imm") 1343 (if_then_else (match_operand 2 "const_int_operand" "") 1344 (const_string "alus_imm") 1345 (const_string "alus_sreg"))])] 1346) 1347 1348(define_insn "*thumb2_addsi3_compare0_scratch" 1349 [(set (reg:CC_NZ CC_REGNUM) 1350 (compare:CC_NZ 1351 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r") 1352 (match_operand:SI 1 "arm_add_operand" "lPv,rIL")) 1353 (const_int 0)))] 1354 "TARGET_THUMB2" 1355 "* 1356 HOST_WIDE_INT val; 1357 1358 if (CONST_INT_P (operands[1])) 1359 val = INTVAL (operands[1]); 1360 else 1361 val = 0; 1362 1363 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val))) 1364 return \"cmp\\t%0, #%n1\"; 1365 else 1366 return \"cmn\\t%0, %1\"; 1367 " 1368 [(set_attr "conds" "set") 1369 (set_attr "length" "2,4") 1370 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "") 1371 (const_string "alus_imm") 1372 (const_string "alus_sreg")))] 1373) 1374 1375(define_insn "*thumb2_mulsi_short" 1376 [(set (match_operand:SI 0 "low_register_operand" "=l") 1377 (mult:SI (match_operand:SI 1 "low_register_operand" "%0") 1378 (match_operand:SI 2 "low_register_operand" "l"))) 1379 (clobber (reg:CC CC_REGNUM))] 1380 "TARGET_THUMB2 && optimize_size && reload_completed" 1381 "mul%!\\t%0, %2, %0" 1382 [(set_attr "predicable" "yes") 1383 (set_attr "length" "2") 1384 (set_attr "type" "muls")]) 1385 1386(define_insn "*thumb2_mulsi_short_compare0" 1387 [(set (reg:CC_NZ CC_REGNUM) 1388 (compare:CC_NZ 1389 (mult:SI (match_operand:SI 1 "register_operand" "%0") 1390 (match_operand:SI 2 "register_operand" "l")) 1391 (const_int 0))) 1392 (set (match_operand:SI 0 "register_operand" "=l") 1393 (mult:SI (match_dup 1) (match_dup 2)))] 1394 "TARGET_THUMB2 && optimize_size" 1395 "muls\\t%0, %2, %0" 1396 [(set_attr "length" "2") 1397 (set_attr "type" "muls")]) 1398 1399(define_insn "*thumb2_mulsi_short_compare0_scratch" 1400 [(set (reg:CC_NZ CC_REGNUM) 1401 (compare:CC_NZ 1402 (mult:SI (match_operand:SI 1 "register_operand" "%0") 1403 (match_operand:SI 2 "register_operand" "l")) 1404 (const_int 0))) 1405 (clobber (match_scratch:SI 0 "=l"))] 1406 "TARGET_THUMB2 && optimize_size" 1407 "muls\\t%0, %2, %0" 1408 [(set_attr "length" "2") 1409 (set_attr "type" "muls")]) 1410 1411(define_insn "*thumb2_cbz" 1412 [(set (pc) (if_then_else 1413 (eq (match_operand:SI 0 "s_register_operand" "l,?r") 1414 (const_int 0)) 1415 (label_ref (match_operand 1 "" "")) 1416 (pc))) 1417 (clobber (reg:CC CC_REGNUM))] 1418 "TARGET_THUMB2" 1419 "* 1420 if (get_attr_length (insn) == 2) 1421 return \"cbz\\t%0, %l1\"; 1422 else 1423 return \"cmp\\t%0, #0\;beq\\t%l1\"; 1424 " 1425 [(set (attr "length") 1426 (if_then_else 1427 (and (ge (minus (match_dup 1) (pc)) (const_int 2)) 1428 (le (minus (match_dup 1) (pc)) (const_int 128)) 1429 (not (match_test "which_alternative"))) 1430 (const_int 2) 1431 (const_int 8))) 1432 (set_attr "type" "branch,multiple")] 1433) 1434 1435(define_insn "*thumb2_cbnz" 1436 [(set (pc) (if_then_else 1437 (ne (match_operand:SI 0 "s_register_operand" "l,?r") 1438 (const_int 0)) 1439 (label_ref (match_operand 1 "" "")) 1440 (pc))) 1441 (clobber (reg:CC CC_REGNUM))] 1442 "TARGET_THUMB2" 1443 "* 1444 if (get_attr_length (insn) == 2) 1445 return \"cbnz\\t%0, %l1\"; 1446 else 1447 return \"cmp\\t%0, #0\;bne\\t%l1\"; 1448 " 1449 [(set (attr "length") 1450 (if_then_else 1451 (and (ge (minus (match_dup 1) (pc)) (const_int 2)) 1452 (le (minus (match_dup 1) (pc)) (const_int 128)) 1453 (not (match_test "which_alternative"))) 1454 (const_int 2) 1455 (const_int 8))) 1456 (set_attr "type" "branch,multiple")] 1457) 1458 1459(define_insn "*thumb2_one_cmplsi2_short" 1460 [(set (match_operand:SI 0 "low_register_operand" "=l") 1461 (not:SI (match_operand:SI 1 "low_register_operand" "l"))) 1462 (clobber (reg:CC CC_REGNUM))] 1463 "TARGET_THUMB2 && reload_completed" 1464 "mvn%!\t%0, %1" 1465 [(set_attr "predicable" "yes") 1466 (set_attr "length" "2") 1467 (set_attr "type" "mvn_reg")] 1468) 1469 1470(define_insn "*thumb2_negsi2_short" 1471 [(set (match_operand:SI 0 "low_register_operand" "=l") 1472 (neg:SI (match_operand:SI 1 "low_register_operand" "l"))) 1473 (clobber (reg:CC CC_REGNUM))] 1474 "TARGET_THUMB2 && reload_completed" 1475 "rsb%!\t%0, %1, #0" 1476 [(set_attr "predicable" "yes") 1477 (set_attr "length" "2") 1478 (set_attr "type" "alu_sreg")] 1479) 1480 1481(define_insn "*orsi_notsi_si" 1482 [(set (match_operand:SI 0 "s_register_operand" "=r") 1483 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 1484 (match_operand:SI 1 "s_register_operand" "r")))] 1485 "TARGET_THUMB2" 1486 "orn%?\\t%0, %1, %2" 1487 [(set_attr "predicable" "yes") 1488 (set_attr "type" "logic_reg")] 1489) 1490 1491(define_insn "*orsi_not_shiftsi_si" 1492 [(set (match_operand:SI 0 "s_register_operand" "=r") 1493 (ior:SI (not:SI (match_operator:SI 4 "shift_operator" 1494 [(match_operand:SI 2 "s_register_operand" "r") 1495 (match_operand:SI 3 "const_int_operand" "M")])) 1496 (match_operand:SI 1 "s_register_operand" "r")))] 1497 "TARGET_THUMB2" 1498 "orn%?\\t%0, %1, %2%S4" 1499 [(set_attr "predicable" "yes") 1500 (set_attr "shift" "2") 1501 (set_attr "type" "alu_shift_imm")] 1502) 1503 1504(define_peephole2 1505 [(set (match_operand:CC_NZ 0 "cc_register" "") 1506 (compare:CC_NZ (zero_extract:SI 1507 (match_operand:SI 1 "low_register_operand" "") 1508 (const_int 1) 1509 (match_operand:SI 2 "const_int_operand" "")) 1510 (const_int 0))) 1511 (match_scratch:SI 3 "l") 1512 (set (pc) 1513 (if_then_else (match_operator:CC_NZ 4 "equality_operator" 1514 [(match_dup 0) (const_int 0)]) 1515 (match_operand 5 "" "") 1516 (match_operand 6 "" "")))] 1517 "TARGET_THUMB2 1518 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32) 1519 && peep2_reg_dead_p (2, operands[0])" 1520 [(parallel [(set (match_dup 0) 1521 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2)) 1522 (const_int 0))) 1523 (clobber (match_dup 3))]) 1524 (set (pc) 1525 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)]) 1526 (match_dup 5) (match_dup 6)))] 1527 " 1528 operands[2] = GEN_INT (31 - INTVAL (operands[2])); 1529 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE, 1530 VOIDmode, operands[0], const0_rtx); 1531 ") 1532 1533(define_peephole2 1534 [(set (match_operand:CC_NZ 0 "cc_register" "") 1535 (compare:CC_NZ (zero_extract:SI 1536 (match_operand:SI 1 "low_register_operand" "") 1537 (match_operand:SI 2 "const_int_operand" "") 1538 (const_int 0)) 1539 (const_int 0))) 1540 (match_scratch:SI 3 "l") 1541 (set (pc) 1542 (if_then_else (match_operator:CC_NZ 4 "equality_operator" 1543 [(match_dup 0) (const_int 0)]) 1544 (match_operand 5 "" "") 1545 (match_operand 6 "" "")))] 1546 "TARGET_THUMB2 1547 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32) 1548 && peep2_reg_dead_p (2, operands[0])" 1549 [(parallel [(set (match_dup 0) 1550 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2)) 1551 (const_int 0))) 1552 (clobber (match_dup 3))]) 1553 (set (pc) 1554 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)]) 1555 (match_dup 5) (match_dup 6)))] 1556 " 1557 operands[2] = GEN_INT (32 - INTVAL (operands[2])); 1558 ") 1559 1560;; Define the subtract-one-and-jump insns so loop.c 1561;; knows what to generate. 1562(define_expand "doloop_end" 1563 [(use (match_operand 0 "" "")) ; loop pseudo 1564 (use (match_operand 1 "" ""))] ; label 1565 "TARGET_32BIT" 1566 " 1567 { 1568 /* Currently SMS relies on the do-loop pattern to recognize loops 1569 where (1) the control part consists of all insns defining and/or 1570 using a certain 'count' register and (2) the loop count can be 1571 adjusted by modifying this register prior to the loop. 1572 ??? The possible introduction of a new block to initialize the 1573 new IV can potentially affect branch optimizations. */ 1574 if (optimize > 0 && flag_modulo_sched) 1575 { 1576 rtx s0; 1577 rtx bcomp; 1578 rtx loc_ref; 1579 rtx cc_reg; 1580 rtx insn; 1581 rtx cmp; 1582 1583 if (GET_MODE (operands[0]) != SImode) 1584 FAIL; 1585 1586 s0 = operands [0]; 1587 if (TARGET_THUMB2) 1588 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1))); 1589 else 1590 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1))); 1591 1592 cmp = XVECEXP (PATTERN (insn), 0, 0); 1593 cc_reg = SET_DEST (cmp); 1594 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx); 1595 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]); 1596 emit_jump_insn (gen_rtx_SET (pc_rtx, 1597 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, 1598 loc_ref, pc_rtx))); 1599 DONE; 1600 }else 1601 FAIL; 1602 }") 1603 1604(define_insn "*clear_apsr" 1605 [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR) 1606 (clobber (reg:CC CC_REGNUM))] 1607 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse" 1608 "clrm%?\\t{APSR}" 1609 [(set_attr "predicable" "yes")] 1610) 1611 1612;; The operands are validated through the clear_multiple_operation 1613;; match_parallel predicate rather than through constraints so enable it only 1614;; after reload. 1615(define_insn "*clear_multiple" 1616 [(match_parallel 0 "clear_multiple_operation" 1617 [(set (match_operand:SI 1 "register_operand" "") 1618 (const_int 0))])] 1619 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed" 1620 { 1621 char pattern[100]; 1622 int i, num_saves = XVECLEN (operands[0], 0); 1623 1624 strcpy (pattern, \"clrm%?\\t{\"); 1625 for (i = 0; i < num_saves; i++) 1626 { 1627 if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE) 1628 { 1629 strcat (pattern, \"APSR\"); 1630 ++i; 1631 } 1632 else 1633 strcat (pattern, 1634 reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]); 1635 if (i < num_saves - 1) 1636 strcat (pattern, \", %|\"); 1637 } 1638 strcat (pattern, \"}\"); 1639 output_asm_insn (pattern, operands); 1640 return \"\"; 1641 } 1642 [(set_attr "predicable" "yes")] 1643) 1644 1645(define_insn "thumb2_asrl" 1646 [(set (match_operand:DI 0 "arm_general_register_operand" "+r") 1647 (ashiftrt:DI (match_dup 0) 1648 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))] 1649 "TARGET_HAVE_MVE" 1650 "asrl%?\\t%Q0, %R0, %1" 1651 [(set_attr "predicable" "yes")]) 1652 1653(define_insn "thumb2_lsll" 1654 [(set (match_operand:DI 0 "arm_general_register_operand" "+r") 1655 (ashift:DI (match_dup 0) 1656 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))] 1657 "TARGET_HAVE_MVE" 1658 "lsll%?\\t%Q0, %R0, %1" 1659 [(set_attr "predicable" "yes")]) 1660 1661(define_insn "thumb2_lsrl" 1662 [(set (match_operand:DI 0 "arm_general_register_operand" "+r") 1663 (lshiftrt:DI (match_dup 0) 1664 (match_operand:SI 1 "long_shift_imm" "Pg")))] 1665 "TARGET_HAVE_MVE" 1666 "lsrl%?\\t%Q0, %R0, %1" 1667 [(set_attr "predicable" "yes")]) 1668