1;; ARM Thumb-2 Machine Description 2;; Copyright (C) 2007-2022 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 763 if (GET_CODE (operands[5]) == PLUS && TARGET_COND_ARITH) 764 return \"cinc\\t%0, %1, %d4\"; 765 766 if (GET_CODE (operands[5]) == AND) 767 { 768 output_asm_insn (\"ite\\t%D4\", operands); 769 output_asm_insn (\"mov%D4\\t%0, #0\", operands); 770 } 771 else if (GET_CODE (operands[5]) == MINUS) 772 { 773 output_asm_insn (\"ite\\t%D4\", operands); 774 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 775 } 776 else if (which_alternative != 0) 777 { 778 output_asm_insn (\"ite\\t%D4\", operands); 779 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 780 } 781 else 782 output_asm_insn (\"it\\t%d4\", operands); 783 return \"%i5%d4\\t%0, %1, #1\"; 784 " 785 [(set_attr "conds" "clob") 786 (set_attr "length" "14") 787 (set_attr "type" "multiple")] 788) 789 790(define_insn_and_split "*thumb2_cond_arith_strict_it" 791 [(set (match_operand:SI 0 "s_register_operand" "=l") 792 (match_operator:SI 5 "shiftable_operator_strict_it" 793 [(match_operator:SI 4 "arm_comparison_operator" 794 [(match_operand:SI 2 "s_register_operand" "r") 795 (match_operand:SI 3 "arm_rhs_operand" "rI")]) 796 (match_operand:SI 1 "s_register_operand" "0")])) 797 (clobber (reg:CC CC_REGNUM))] 798 "TARGET_THUMB2 && arm_restrict_it" 799 "#" 800 "&& reload_completed" 801 [(const_int 0)] 802 { 803 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 804 { 805 /* %i5 %0, %1, %2, lsr #31 */ 806 rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31)); 807 rtx op = NULL_RTX; 808 809 switch (GET_CODE (operands[5])) 810 { 811 case AND: 812 op = gen_rtx_AND (SImode, shifted_op, operands[1]); 813 break; 814 case PLUS: 815 op = gen_rtx_PLUS (SImode, shifted_op, operands[1]); 816 break; 817 default: gcc_unreachable (); 818 } 819 emit_insn (gen_rtx_SET (operands[0], op)); 820 DONE; 821 } 822 823 /* "cmp %2, %3" */ 824 emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM), 825 gen_rtx_COMPARE (CCmode, operands[2], 826 operands[3]))); 827 828 if (GET_CODE (operands[5]) == AND) 829 { 830 /* %i5 %0, %1, #1 831 it%D4 832 mov%D4 %0, #0 */ 833 enum rtx_code rc = reverse_condition (GET_CODE (operands[4])); 834 emit_insn (gen_rtx_SET (operands[0], gen_rtx_AND (SImode, operands[1], 835 GEN_INT (1)))); 836 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 837 gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx), 838 gen_rtx_SET (operands[0], const0_rtx))); 839 DONE; 840 } 841 else 842 { 843 /* it\\t%d4 844 %i5%d4\\t%0, %1, #1 */ 845 emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]), 846 VOIDmode, 847 gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx), 848 gen_rtx_SET (operands[0], 849 gen_rtx_PLUS (SImode, 850 operands[1], 851 GEN_INT (1))))); 852 DONE; 853 } 854 FAIL; 855 } 856 [(set_attr "conds" "clob") 857 (set_attr "length" "12") 858 (set_attr "type" "multiple")] 859) 860 861(define_insn "*thumb2_cond_sub" 862 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts") 863 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts") 864 (match_operator:SI 4 "arm_comparison_operator" 865 [(match_operand:SI 2 "s_register_operand" "r,r") 866 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 867 (clobber (reg:CC CC_REGNUM))] 868 "TARGET_THUMB2" 869 "* 870 output_asm_insn (\"cmp\\t%2, %3\", operands); 871 if (which_alternative != 0) 872 { 873 if (arm_restrict_it) 874 { 875 output_asm_insn (\"mov\\t%0, %1\", operands); 876 output_asm_insn (\"it\\t%d4\", operands); 877 } 878 else 879 { 880 output_asm_insn (\"ite\\t%D4\", operands); 881 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 882 } 883 } 884 else 885 output_asm_insn (\"it\\t%d4\", operands); 886 return \"sub%d4\\t%0, %1, #1\"; 887 " 888 [(set_attr "conds" "clob") 889 (set_attr "length" "10,14") 890 (set_attr "type" "multiple")] 891) 892 893(define_insn_and_split "*thumb2_negscc" 894 [(set (match_operand:SI 0 "s_register_operand" "=Ts") 895 (neg:SI (match_operator 3 "arm_comparison_operator" 896 [(match_operand:SI 1 "s_register_operand" "r") 897 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 898 (clobber (reg:CC CC_REGNUM))] 899 "TARGET_THUMB2 && !TARGET_COND_ARITH" 900 "#" 901 "&& reload_completed" 902 [(const_int 0)] 903 { 904 rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); 905 906 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx) 907 { 908 /* Emit asr\\t%0, %1, #31 */ 909 emit_insn (gen_rtx_SET (operands[0], 910 gen_rtx_ASHIFTRT (SImode, 911 operands[1], 912 GEN_INT (31)))); 913 DONE; 914 } 915 else if (GET_CODE (operands[3]) == NE && !arm_restrict_it) 916 { 917 /* Emit subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0 */ 918 if (CONST_INT_P (operands[2])) 919 emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2], 920 gen_int_mode (-INTVAL (operands[2]), 921 SImode))); 922 else 923 emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2])); 924 925 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 926 gen_rtx_NE (SImode, 927 cc_reg, 928 const0_rtx), 929 gen_rtx_SET (operands[0], 930 GEN_INT (~0)))); 931 DONE; 932 } 933 else 934 { 935 /* Emit: cmp\\t%1, %2\;mvn\\t%0, #0\;it\\t%D3\;mov%D3\\t%0, #0\;*/ 936 enum rtx_code rc = reverse_condition (GET_CODE (operands[3])); 937 machine_mode mode = SELECT_CC_MODE (rc, operands[1], operands[2]); 938 rtx tmp1 = gen_rtx_REG (mode, CC_REGNUM); 939 940 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (CCmode, operands[1], 941 operands[2]))); 942 943 emit_insn (gen_rtx_SET (operands[0], GEN_INT (~0))); 944 945 emit_insn (gen_rtx_COND_EXEC (VOIDmode, 946 gen_rtx_fmt_ee (rc, 947 VOIDmode, 948 tmp1, 949 const0_rtx), 950 gen_rtx_SET (operands[0], const0_rtx))); 951 DONE; 952 } 953 FAIL; 954 } 955 [(set_attr "conds" "clob") 956 (set_attr "length" "14") 957 (set_attr "type" "multiple")] 958) 959 960(define_insn "*thumb2_csinv" 961 [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r") 962 (if_then_else:SI 963 (match_operand 1 "arm_comparison_operation" "") 964 (not:SI (match_operand:SI 2 "arm_general_register_operand" "r, r")) 965 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))] 966 "TARGET_COND_ARITH" 967 "@ 968 csinv\\t%0, %3, %2, %D1 969 csinv\\t%0, zr, %2, %D1" 970 [(set_attr "type" "csel") 971 (set_attr "predicable" "no")] 972) 973 974(define_insn "*thumb2_csinc" 975 [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r") 976 (if_then_else:SI 977 (match_operand 1 "arm_comparison_operation" "") 978 (plus:SI (match_operand:SI 2 "arm_general_register_operand" "r, r") 979 (const_int 1)) 980 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))] 981 "TARGET_COND_ARITH" 982 "@ 983 csinc\\t%0, %3, %2, %D1 984 csinc\\t%0, zr, %2, %D1" 985 [(set_attr "type" "csel") 986 (set_attr "predicable" "no")] 987) 988 989(define_insn "*thumb2_csneg" 990 [(set (match_operand:SI 0 "arm_general_register_operand" "=r, r") 991 (if_then_else:SI 992 (match_operand 1 "arm_comparison_operation" "") 993 (neg:SI (match_operand:SI 2 "arm_general_register_operand" "r, r")) 994 (match_operand:SI 3 "reg_or_zero_operand" "r, Pz")))] 995 "TARGET_COND_ARITH" 996 "@ 997 csneg\\t%0, %3, %2, %D1 998 csneg\\t%0, zr, %2, %D1" 999 [(set_attr "type" "csel") 1000 (set_attr "predicable" "no")] 1001) 1002 1003(define_insn "*thumb2_movcond" 1004 [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts") 1005 (if_then_else:SI 1006 (match_operator 5 "arm_comparison_operator" 1007 [(match_operand:SI 3 "s_register_operand" "r,r,r") 1008 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 1009 (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI") 1010 (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI"))) 1011 (clobber (reg:CC CC_REGNUM))] 1012 "TARGET_THUMB2 && !TARGET_COND_ARITH" 1013 "* 1014 if (GET_CODE (operands[5]) == LT 1015 && (operands[4] == const0_rtx)) 1016 { 1017 if (which_alternative != 1 && REG_P (operands[1])) 1018 { 1019 if (operands[2] == const0_rtx) 1020 return \"and\\t%0, %1, %3, asr #31\"; 1021 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\"; 1022 } 1023 else if (which_alternative != 0 && REG_P (operands[2])) 1024 { 1025 if (operands[1] == const0_rtx) 1026 return \"bic\\t%0, %2, %3, asr #31\"; 1027 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\"; 1028 } 1029 /* The only case that falls through to here is when both ops 1 & 2 1030 are constants. */ 1031 } 1032 1033 if (GET_CODE (operands[5]) == GE 1034 && (operands[4] == const0_rtx)) 1035 { 1036 if (which_alternative != 1 && REG_P (operands[1])) 1037 { 1038 if (operands[2] == const0_rtx) 1039 return \"bic\\t%0, %1, %3, asr #31\"; 1040 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\"; 1041 } 1042 else if (which_alternative != 0 && REG_P (operands[2])) 1043 { 1044 if (operands[1] == const0_rtx) 1045 return \"and\\t%0, %2, %3, asr #31\"; 1046 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\"; 1047 } 1048 /* The only case that falls through to here is when both ops 1 & 2 1049 are constants. */ 1050 } 1051 if (CONST_INT_P (operands[4]) 1052 && !const_ok_for_arm (INTVAL (operands[4]))) 1053 output_asm_insn (\"cmn\\t%3, #%n4\", operands); 1054 else 1055 output_asm_insn (\"cmp\\t%3, %4\", operands); 1056 switch (which_alternative) 1057 { 1058 case 0: 1059 output_asm_insn (\"it\\t%D5\", operands); 1060 break; 1061 case 1: 1062 output_asm_insn (\"it\\t%d5\", operands); 1063 break; 1064 case 2: 1065 if (arm_restrict_it) 1066 { 1067 output_asm_insn (\"mov\\t%0, %1\", operands); 1068 output_asm_insn (\"it\\t%D5\", operands); 1069 } 1070 else 1071 output_asm_insn (\"ite\\t%d5\", operands); 1072 break; 1073 default: 1074 abort(); 1075 } 1076 if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2)) 1077 output_asm_insn (\"mov%d5\\t%0, %1\", operands); 1078 if (which_alternative != 1) 1079 output_asm_insn (\"mov%D5\\t%0, %2\", operands); 1080 return \"\"; 1081 " 1082 [(set_attr "conds" "clob") 1083 (set_attr "length" "10,10,14") 1084 (set_attr "type" "multiple")] 1085) 1086 1087;; Zero and sign extension instructions. 1088 1089;; All supported Thumb2 implementations are armv6, so only that case is 1090;; provided. 1091(define_insn "*thumb2_extendqisi_v6" 1092 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1093 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 1094 "TARGET_THUMB2 && arm_arch6" 1095 "@ 1096 sxtb%?\\t%0, %1 1097 ldrsb%?\\t%0, %1" 1098 [(set_attr "type" "extend,load_byte") 1099 (set_attr "predicable" "yes") 1100 (set_attr "pool_range" "*,4094") 1101 (set_attr "neg_pool_range" "*,250")] 1102) 1103 1104(define_insn "*thumb2_zero_extendhisi2_v6" 1105 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1106 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] 1107 "TARGET_THUMB2 && arm_arch6" 1108 "@ 1109 uxth%?\\t%0, %1 1110 ldrh%?\\t%0, %1" 1111 [(set_attr "type" "extend,load_byte") 1112 (set_attr "predicable" "yes") 1113 (set_attr "pool_range" "*,4094") 1114 (set_attr "neg_pool_range" "*,250")] 1115) 1116 1117(define_insn "thumb2_zero_extendqisi2_v6" 1118 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1119 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 1120 "TARGET_THUMB2 && arm_arch6" 1121 "@ 1122 uxtb%?\\t%0, %1 1123 ldrb%?\\t%0, %1\\t%@ zero_extendqisi2" 1124 [(set_attr "type" "extend,load_byte") 1125 (set_attr "predicable" "yes") 1126 (set_attr "pool_range" "*,4094") 1127 (set_attr "neg_pool_range" "*,250")] 1128) 1129 1130(define_expand "thumb2_casesi_internal" 1131 [(parallel [(set (pc) 1132 (if_then_else 1133 (leu (match_operand:SI 0 "s_register_operand") 1134 (match_operand:SI 1 "arm_rhs_operand")) 1135 (match_dup 4) 1136 (label_ref:SI (match_operand 3 "")))) 1137 (clobber (reg:CC CC_REGNUM)) 1138 (clobber (match_scratch:SI 5)) 1139 (use (label_ref:SI (match_operand 2 "")))])] 1140 "TARGET_THUMB2 && !flag_pic" 1141{ 1142 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4)); 1143 operands[4] = gen_rtx_PLUS (SImode, operands[4], 1144 gen_rtx_LABEL_REF (SImode, operands[2])); 1145 operands[4] = gen_rtx_MEM (SImode, operands[4]); 1146 MEM_READONLY_P (operands[4]) = 1; 1147 MEM_NOTRAP_P (operands[4]) = 1; 1148}) 1149 1150(define_insn "*thumb2_casesi_internal" 1151 [(parallel [(set (pc) 1152 (if_then_else 1153 (leu (match_operand:SI 0 "s_register_operand" "r") 1154 (match_operand:SI 1 "arm_rhs_operand" "rI")) 1155 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 1156 (label_ref:SI (match_operand 2 "" "")))) 1157 (label_ref:SI (match_operand 3 "" "")))) 1158 (clobber (reg:CC CC_REGNUM)) 1159 (clobber (match_scratch:SI 4 "=&r")) 1160 (use (label_ref:SI (match_dup 2)))])] 1161 "TARGET_THUMB2 && !flag_pic" 1162 "* return thumb2_output_casesi(operands);" 1163 [(set_attr "conds" "clob") 1164 (set_attr "length" "16") 1165 (set_attr "type" "multiple")] 1166) 1167 1168(define_expand "thumb2_casesi_internal_pic" 1169 [(parallel [(set (pc) 1170 (if_then_else 1171 (leu (match_operand:SI 0 "s_register_operand") 1172 (match_operand:SI 1 "arm_rhs_operand")) 1173 (match_dup 4) 1174 (label_ref:SI (match_operand 3 "")))) 1175 (clobber (reg:CC CC_REGNUM)) 1176 (clobber (match_scratch:SI 5)) 1177 (clobber (match_scratch:SI 6)) 1178 (use (label_ref:SI (match_operand 2 "")))])] 1179 "TARGET_THUMB2 && flag_pic" 1180{ 1181 operands[4] = gen_rtx_MULT (SImode, operands[0], GEN_INT (4)); 1182 operands[4] = gen_rtx_PLUS (SImode, operands[4], 1183 gen_rtx_LABEL_REF (SImode, operands[2])); 1184 operands[4] = gen_rtx_MEM (SImode, operands[4]); 1185 MEM_READONLY_P (operands[4]) = 1; 1186 MEM_NOTRAP_P (operands[4]) = 1; 1187}) 1188 1189(define_insn "*thumb2_casesi_internal_pic" 1190 [(parallel [(set (pc) 1191 (if_then_else 1192 (leu (match_operand:SI 0 "s_register_operand" "r") 1193 (match_operand:SI 1 "arm_rhs_operand" "rI")) 1194 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 1195 (label_ref:SI (match_operand 2 "" "")))) 1196 (label_ref:SI (match_operand 3 "" "")))) 1197 (clobber (reg:CC CC_REGNUM)) 1198 (clobber (match_scratch:SI 4 "=&r")) 1199 (clobber (match_scratch:SI 5 "=r")) 1200 (use (label_ref:SI (match_dup 2)))])] 1201 "TARGET_THUMB2 && flag_pic" 1202 "* return thumb2_output_casesi(operands);" 1203 [(set_attr "conds" "clob") 1204 (set_attr "length" "20") 1205 (set_attr "type" "multiple")] 1206) 1207 1208(define_insn "*thumb2_return" 1209 [(simple_return)] 1210 "TARGET_THUMB2 && !IS_CMSE_ENTRY (arm_current_func_type ())" 1211 "* return output_return_instruction (const_true_rtx, true, false, true);" 1212 [(set_attr "type" "branch") 1213 (set_attr "length" "4")] 1214) 1215 1216(define_insn "*thumb2_cmse_entry_return" 1217 [(simple_return)] 1218 "TARGET_THUMB2 && IS_CMSE_ENTRY (arm_current_func_type ())" 1219 "* return output_return_instruction (const_true_rtx, true, false, true);" 1220 [(set_attr "type" "branch") 1221 ; This is a return from a cmse_nonsecure_entry function so code will be 1222 ; added to clear the APSR and potentially the FPSCR if VFP is available, so 1223 ; we adapt the length accordingly. 1224 (set (attr "length") 1225 (if_then_else (match_test "TARGET_HARD_FLOAT") 1226 (const_int 34) 1227 (const_int 8))) 1228 ; We do not support predicate execution of returns from cmse_nonsecure_entry 1229 ; functions because we need to clear the APSR. Since predicable has to be 1230 ; a constant, we had to duplicate the thumb2_return pattern for CMSE entry 1231 ; functions. 1232 (set_attr "predicable" "no")] 1233) 1234 1235(define_insn_and_split "thumb2_eh_return" 1236 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")] 1237 VUNSPEC_EH_RETURN) 1238 (clobber (match_scratch:SI 1 "=&r"))] 1239 "TARGET_THUMB2" 1240 "#" 1241 "&& reload_completed" 1242 [(const_int 0)] 1243 " 1244 { 1245 thumb_set_return_address (operands[0], operands[1]); 1246 DONE; 1247 }" 1248) 1249 1250(define_insn "*thumb2_alusi3_short" 1251 [(set (match_operand:SI 0 "s_register_operand" "=l") 1252 (match_operator:SI 3 "thumb_16bit_operator" 1253 [(match_operand:SI 1 "s_register_operand" "0") 1254 (match_operand:SI 2 "s_register_operand" "l")])) 1255 (clobber (reg:CC CC_REGNUM))] 1256 "TARGET_THUMB2 && reload_completed 1257 && GET_CODE(operands[3]) != PLUS 1258 && GET_CODE(operands[3]) != MINUS" 1259 "%I3%!\\t%0, %1, %2" 1260 [(set_attr "predicable" "yes") 1261 (set_attr "length" "2") 1262 (set_attr "type" "alu_sreg")] 1263) 1264 1265(define_insn "*thumb2_shiftsi3_short" 1266 [(set (match_operand:SI 0 "low_register_operand" "=l,l") 1267 (match_operator:SI 3 "shift_operator" 1268 [(match_operand:SI 1 "low_register_operand" "0,l") 1269 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")])) 1270 (clobber (reg:CC CC_REGNUM))] 1271 "TARGET_THUMB2 && reload_completed 1272 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) 1273 || REG_P (operands[2]))" 1274 "* return arm_output_shift(operands, 2);" 1275 [(set_attr "predicable" "yes") 1276 (set_attr "shift" "1") 1277 (set_attr "length" "2") 1278 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 1279 (if_then_else (match_operand 3 "alu_shift_operator_lsl_1_to_4") 1280 (const_string "alu_shift_imm_lsl_1to4") 1281 (const_string "alu_shift_imm_other")) 1282 (const_string "alu_shift_reg")))] 1283) 1284 1285(define_insn "*thumb2_mov<mode>_shortim" 1286 [(set (match_operand:QHSI 0 "low_register_operand" "=l") 1287 (match_operand:QHSI 1 "const_int_operand" "I")) 1288 (clobber (reg:CC CC_REGNUM))] 1289 "TARGET_THUMB2 && reload_completed" 1290 "mov%!\t%0, %1" 1291 [(set_attr "predicable" "yes") 1292 (set_attr "length" "2") 1293 (set_attr "type" "mov_imm")] 1294) 1295 1296(define_insn "*thumb2_addsi_short" 1297 [(set (match_operand:SI 0 "low_register_operand" "=l,l") 1298 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0") 1299 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps"))) 1300 (clobber (reg:CC CC_REGNUM))] 1301 "TARGET_THUMB2 && reload_completed" 1302 "* 1303 HOST_WIDE_INT val; 1304 1305 if (CONST_INT_P (operands[2])) 1306 val = INTVAL(operands[2]); 1307 else 1308 val = 0; 1309 1310 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */ 1311 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val))) 1312 return \"sub%!\\t%0, %1, #%n2\"; 1313 else 1314 return \"add%!\\t%0, %1, %2\"; 1315 " 1316 [(set_attr "predicable" "yes") 1317 (set_attr "length" "2") 1318 (set_attr_alternative "type" 1319 [(if_then_else (match_operand 2 "const_int_operand" "") 1320 (const_string "alu_imm") 1321 (const_string "alu_sreg")) 1322 (const_string "alu_imm")])] 1323) 1324 1325(define_insn "*thumb2_subsi_short" 1326 [(set (match_operand:SI 0 "low_register_operand" "=l") 1327 (minus:SI (match_operand:SI 1 "low_register_operand" "l") 1328 (match_operand:SI 2 "low_register_operand" "l"))) 1329 (clobber (reg:CC CC_REGNUM))] 1330 "TARGET_THUMB2 && reload_completed" 1331 "sub%!\\t%0, %1, %2" 1332 [(set_attr "predicable" "yes") 1333 (set_attr "length" "2") 1334 (set_attr "type" "alu_sreg")] 1335) 1336 1337(define_peephole2 1338 [(set (match_operand:CC 0 "cc_register" "") 1339 (compare:CC (match_operand:SI 1 "low_register_operand" "") 1340 (match_operand:SI 2 "const_int_operand" "")))] 1341 "TARGET_THUMB2 1342 && peep2_reg_dead_p (1, operands[1]) 1343 && satisfies_constraint_Pw (operands[2])" 1344 [(parallel 1345 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2))) 1346 (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 3)))])] 1347 "operands[3] = GEN_INT (- INTVAL (operands[2]));" 1348) 1349 1350(define_peephole2 1351 [(match_scratch:SI 3 "l") 1352 (set (match_operand:CC 0 "cc_register" "") 1353 (compare:CC (match_operand:SI 1 "low_register_operand" "") 1354 (match_operand:SI 2 "const_int_operand" "")))] 1355 "TARGET_THUMB2 1356 && satisfies_constraint_Px (operands[2])" 1357 [(parallel 1358 [(set (match_dup 0) (compare:CC (match_dup 1) (match_dup 2))) 1359 (set (match_dup 3) (plus:SI (match_dup 1) (match_dup 4)))])] 1360 "operands[4] = GEN_INT (- INTVAL (operands[2]));" 1361) 1362 1363(define_insn "thumb2_addsi3_compare0" 1364 [(set (reg:CC_NZ CC_REGNUM) 1365 (compare:CC_NZ 1366 (plus:SI (match_operand:SI 1 "s_register_operand" "l, 0, r") 1367 (match_operand:SI 2 "arm_add_operand" "lPt,Ps,rIL")) 1368 (const_int 0))) 1369 (set (match_operand:SI 0 "s_register_operand" "=l,l,r") 1370 (plus:SI (match_dup 1) (match_dup 2)))] 1371 "TARGET_THUMB2" 1372 "* 1373 HOST_WIDE_INT val; 1374 1375 if (CONST_INT_P (operands[2])) 1376 val = INTVAL (operands[2]); 1377 else 1378 val = 0; 1379 1380 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val))) 1381 return \"subs\\t%0, %1, #%n2\"; 1382 else 1383 return \"adds\\t%0, %1, %2\"; 1384 " 1385 [(set_attr "conds" "set") 1386 (set_attr "length" "2,2,4") 1387 (set_attr_alternative "type" 1388 [(if_then_else (match_operand 2 "const_int_operand" "") 1389 (const_string "alus_imm") 1390 (const_string "alus_sreg")) 1391 (const_string "alus_imm") 1392 (if_then_else (match_operand 2 "const_int_operand" "") 1393 (const_string "alus_imm") 1394 (const_string "alus_sreg"))])] 1395) 1396 1397(define_insn "*thumb2_addsi3_compare0_scratch" 1398 [(set (reg:CC_NZ CC_REGNUM) 1399 (compare:CC_NZ 1400 (plus:SI (match_operand:SI 0 "s_register_operand" "l, r") 1401 (match_operand:SI 1 "arm_add_operand" "lPv,rIL")) 1402 (const_int 0)))] 1403 "TARGET_THUMB2" 1404 "* 1405 HOST_WIDE_INT val; 1406 1407 if (CONST_INT_P (operands[1])) 1408 val = INTVAL (operands[1]); 1409 else 1410 val = 0; 1411 1412 if (val < 0 && const_ok_for_arm (ARM_SIGN_EXTEND (-val))) 1413 return \"cmp\\t%0, #%n1\"; 1414 else 1415 return \"cmn\\t%0, %1\"; 1416 " 1417 [(set_attr "conds" "set") 1418 (set_attr "length" "2,4") 1419 (set (attr "type") (if_then_else (match_operand 1 "const_int_operand" "") 1420 (const_string "alus_imm") 1421 (const_string "alus_sreg")))] 1422) 1423 1424(define_insn "*thumb2_mulsi_short" 1425 [(set (match_operand:SI 0 "low_register_operand" "=l") 1426 (mult:SI (match_operand:SI 1 "low_register_operand" "%0") 1427 (match_operand:SI 2 "low_register_operand" "l"))) 1428 (clobber (reg:CC CC_REGNUM))] 1429 "TARGET_THUMB2 && optimize_size && reload_completed" 1430 "mul%!\\t%0, %2, %0" 1431 [(set_attr "predicable" "yes") 1432 (set_attr "length" "2") 1433 (set_attr "type" "muls")]) 1434 1435(define_insn "*thumb2_mulsi_short_compare0" 1436 [(set (reg:CC_NZ CC_REGNUM) 1437 (compare:CC_NZ 1438 (mult:SI (match_operand:SI 1 "register_operand" "%0") 1439 (match_operand:SI 2 "register_operand" "l")) 1440 (const_int 0))) 1441 (set (match_operand:SI 0 "register_operand" "=l") 1442 (mult:SI (match_dup 1) (match_dup 2)))] 1443 "TARGET_THUMB2 && optimize_size" 1444 "muls\\t%0, %2, %0" 1445 [(set_attr "length" "2") 1446 (set_attr "type" "muls")]) 1447 1448(define_insn "*thumb2_mulsi_short_compare0_scratch" 1449 [(set (reg:CC_NZ CC_REGNUM) 1450 (compare:CC_NZ 1451 (mult:SI (match_operand:SI 1 "register_operand" "%0") 1452 (match_operand:SI 2 "register_operand" "l")) 1453 (const_int 0))) 1454 (clobber (match_scratch:SI 0 "=l"))] 1455 "TARGET_THUMB2 && optimize_size" 1456 "muls\\t%0, %2, %0" 1457 [(set_attr "length" "2") 1458 (set_attr "type" "muls")]) 1459 1460(define_insn "*thumb2_cbz" 1461 [(set (pc) (if_then_else 1462 (eq (match_operand:SI 0 "s_register_operand" "l,?r") 1463 (const_int 0)) 1464 (label_ref (match_operand 1 "" "")) 1465 (pc))) 1466 (clobber (reg:CC CC_REGNUM))] 1467 "TARGET_THUMB2" 1468 "* 1469 if (get_attr_length (insn) == 2) 1470 return \"cbz\\t%0, %l1\"; 1471 else 1472 return \"cmp\\t%0, #0\;beq\\t%l1\"; 1473 " 1474 [(set (attr "length") 1475 (if_then_else 1476 (and (ge (minus (match_dup 1) (pc)) (const_int 2)) 1477 (le (minus (match_dup 1) (pc)) (const_int 128)) 1478 (not (match_test "which_alternative"))) 1479 (const_int 2) 1480 (const_int 8))) 1481 (set_attr "type" "branch,multiple")] 1482) 1483 1484(define_insn "*thumb2_cbnz" 1485 [(set (pc) (if_then_else 1486 (ne (match_operand:SI 0 "s_register_operand" "l,?r") 1487 (const_int 0)) 1488 (label_ref (match_operand 1 "" "")) 1489 (pc))) 1490 (clobber (reg:CC CC_REGNUM))] 1491 "TARGET_THUMB2" 1492 "* 1493 if (get_attr_length (insn) == 2) 1494 return \"cbnz\\t%0, %l1\"; 1495 else 1496 return \"cmp\\t%0, #0\;bne\\t%l1\"; 1497 " 1498 [(set (attr "length") 1499 (if_then_else 1500 (and (ge (minus (match_dup 1) (pc)) (const_int 2)) 1501 (le (minus (match_dup 1) (pc)) (const_int 128)) 1502 (not (match_test "which_alternative"))) 1503 (const_int 2) 1504 (const_int 8))) 1505 (set_attr "type" "branch,multiple")] 1506) 1507 1508(define_insn "*thumb2_one_cmplsi2_short" 1509 [(set (match_operand:SI 0 "low_register_operand" "=l") 1510 (not:SI (match_operand:SI 1 "low_register_operand" "l"))) 1511 (clobber (reg:CC CC_REGNUM))] 1512 "TARGET_THUMB2 && reload_completed" 1513 "mvn%!\t%0, %1" 1514 [(set_attr "predicable" "yes") 1515 (set_attr "length" "2") 1516 (set_attr "type" "mvn_reg")] 1517) 1518 1519(define_insn "*thumb2_negsi2_short" 1520 [(set (match_operand:SI 0 "low_register_operand" "=l") 1521 (neg:SI (match_operand:SI 1 "low_register_operand" "l"))) 1522 (clobber (reg:CC CC_REGNUM))] 1523 "TARGET_THUMB2 && reload_completed" 1524 "rsb%!\t%0, %1, #0" 1525 [(set_attr "predicable" "yes") 1526 (set_attr "length" "2") 1527 (set_attr "type" "alu_sreg")] 1528) 1529 1530(define_insn "*orsi_notsi_si" 1531 [(set (match_operand:SI 0 "s_register_operand" "=r") 1532 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 1533 (match_operand:SI 1 "s_register_operand" "r")))] 1534 "TARGET_THUMB2" 1535 "orn%?\\t%0, %1, %2" 1536 [(set_attr "predicable" "yes") 1537 (set_attr "type" "logic_reg")] 1538) 1539 1540(define_insn "*orsi_not_shiftsi_si" 1541 [(set (match_operand:SI 0 "s_register_operand" "=r") 1542 (ior:SI (not:SI (match_operator:SI 4 "shift_operator" 1543 [(match_operand:SI 2 "s_register_operand" "r") 1544 (match_operand:SI 3 "const_int_operand" "M")])) 1545 (match_operand:SI 1 "s_register_operand" "r")))] 1546 "TARGET_THUMB2" 1547 "orn%?\\t%0, %1, %2%S4" 1548 [(set_attr "predicable" "yes") 1549 (set_attr "shift" "2") 1550 (set_attr "autodetect_type" "alu_shift_operator4")] 1551) 1552 1553(define_peephole2 1554 [(set (match_operand:CC_NZ 0 "cc_register" "") 1555 (compare:CC_NZ (zero_extract:SI 1556 (match_operand:SI 1 "low_register_operand" "") 1557 (const_int 1) 1558 (match_operand:SI 2 "const_int_operand" "")) 1559 (const_int 0))) 1560 (match_scratch:SI 3 "l") 1561 (set (pc) 1562 (if_then_else (match_operator:CC_NZ 4 "equality_operator" 1563 [(match_dup 0) (const_int 0)]) 1564 (match_operand 5 "" "") 1565 (match_operand 6 "" "")))] 1566 "TARGET_THUMB2 1567 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32) 1568 && peep2_reg_dead_p (2, operands[0])" 1569 [(parallel [(set (match_dup 0) 1570 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2)) 1571 (const_int 0))) 1572 (clobber (match_dup 3))]) 1573 (set (pc) 1574 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)]) 1575 (match_dup 5) (match_dup 6)))] 1576 " 1577 operands[2] = GEN_INT (31 - INTVAL (operands[2])); 1578 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]) == NE ? LT : GE, 1579 VOIDmode, operands[0], const0_rtx); 1580 ") 1581 1582(define_peephole2 1583 [(set (match_operand:CC_NZ 0 "cc_register" "") 1584 (compare:CC_NZ (zero_extract:SI 1585 (match_operand:SI 1 "low_register_operand" "") 1586 (match_operand:SI 2 "const_int_operand" "") 1587 (const_int 0)) 1588 (const_int 0))) 1589 (match_scratch:SI 3 "l") 1590 (set (pc) 1591 (if_then_else (match_operator:CC_NZ 4 "equality_operator" 1592 [(match_dup 0) (const_int 0)]) 1593 (match_operand 5 "" "") 1594 (match_operand 6 "" "")))] 1595 "TARGET_THUMB2 1596 && (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 32) 1597 && peep2_reg_dead_p (2, operands[0])" 1598 [(parallel [(set (match_dup 0) 1599 (compare:CC_NZ (ashift:SI (match_dup 1) (match_dup 2)) 1600 (const_int 0))) 1601 (clobber (match_dup 3))]) 1602 (set (pc) 1603 (if_then_else (match_op_dup 4 [(match_dup 0) (const_int 0)]) 1604 (match_dup 5) (match_dup 6)))] 1605 " 1606 operands[2] = GEN_INT (32 - INTVAL (operands[2])); 1607 ") 1608 1609;; Define the subtract-one-and-jump insns so loop.c 1610;; knows what to generate. 1611(define_expand "doloop_end" 1612 [(use (match_operand 0 "" "")) ; loop pseudo 1613 (use (match_operand 1 "" ""))] ; label 1614 "TARGET_32BIT" 1615 " 1616 { 1617 /* Currently SMS relies on the do-loop pattern to recognize loops 1618 where (1) the control part consists of all insns defining and/or 1619 using a certain 'count' register and (2) the loop count can be 1620 adjusted by modifying this register prior to the loop. 1621 ??? The possible introduction of a new block to initialize the 1622 new IV can potentially affect branch optimizations. 1623 1624 Also used to implement the low over head loops feature, which is part of 1625 the Armv8.1-M Mainline Low Overhead Branch (LOB) extension. */ 1626 if (optimize > 0 && (flag_modulo_sched || TARGET_HAVE_LOB)) 1627 { 1628 rtx s0; 1629 rtx bcomp; 1630 rtx loc_ref; 1631 rtx cc_reg; 1632 rtx insn; 1633 rtx cmp; 1634 1635 if (GET_MODE (operands[0]) != SImode) 1636 FAIL; 1637 1638 s0 = operands [0]; 1639 1640 /* Low over head loop instructions require the first operand to be LR. */ 1641 if (TARGET_HAVE_LOB && arm_target_insn_ok_for_lob (operands [1])) 1642 s0 = gen_rtx_REG (SImode, LR_REGNUM); 1643 1644 if (TARGET_THUMB2) 1645 insn = emit_insn (gen_thumb2_addsi3_compare0 (s0, s0, GEN_INT (-1))); 1646 else 1647 insn = emit_insn (gen_addsi3_compare0 (s0, s0, GEN_INT (-1))); 1648 1649 cmp = XVECEXP (PATTERN (insn), 0, 0); 1650 cc_reg = SET_DEST (cmp); 1651 bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx); 1652 loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]); 1653 emit_jump_insn (gen_rtx_SET (pc_rtx, 1654 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, 1655 loc_ref, pc_rtx))); 1656 DONE; 1657 } 1658 else 1659 FAIL; 1660 }") 1661 1662(define_insn "*clear_apsr" 1663 [(unspec_volatile:SI [(const_int 0)] VUNSPEC_CLRM_APSR) 1664 (clobber (reg:CC CC_REGNUM))] 1665 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse" 1666 "clrm%?\\t{APSR}" 1667 [(set_attr "predicable" "yes")] 1668) 1669 1670;; The operands are validated through the clear_multiple_operation 1671;; match_parallel predicate rather than through constraints so enable it only 1672;; after reload. 1673(define_insn "*clear_multiple" 1674 [(match_parallel 0 "clear_multiple_operation" 1675 [(set (match_operand:SI 1 "register_operand" "") 1676 (const_int 0))])] 1677 "TARGET_THUMB2 && TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed" 1678 { 1679 char pattern[100]; 1680 int i, num_saves = XVECLEN (operands[0], 0); 1681 1682 strcpy (pattern, \"clrm%?\\t{\"); 1683 for (i = 0; i < num_saves; i++) 1684 { 1685 if (GET_CODE (XVECEXP (operands[0], 0, i)) == UNSPEC_VOLATILE) 1686 { 1687 strcat (pattern, \"APSR\"); 1688 ++i; 1689 } 1690 else 1691 strcat (pattern, 1692 reg_names[REGNO (XEXP (XVECEXP (operands[0], 0, i), 0))]); 1693 if (i < num_saves - 1) 1694 strcat (pattern, \", %|\"); 1695 } 1696 strcat (pattern, \"}\"); 1697 output_asm_insn (pattern, operands); 1698 return \"\"; 1699 } 1700 [(set_attr "predicable" "yes")] 1701) 1702 1703(define_insn "thumb2_asrl" 1704 [(set (match_operand:DI 0 "arm_general_register_operand" "+r") 1705 (ashiftrt:DI (match_dup 0) 1706 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))] 1707 "TARGET_HAVE_MVE" 1708 "asrl%?\\t%Q0, %R0, %1" 1709 [(set_attr "predicable" "yes")]) 1710 1711(define_insn "thumb2_lsll" 1712 [(set (match_operand:DI 0 "arm_general_register_operand" "+r") 1713 (ashift:DI (match_dup 0) 1714 (match_operand:SI 1 "arm_reg_or_long_shift_imm" "rPg")))] 1715 "TARGET_HAVE_MVE" 1716 "lsll%?\\t%Q0, %R0, %1" 1717 [(set_attr "predicable" "yes")]) 1718 1719(define_insn "thumb2_lsrl" 1720 [(set (match_operand:DI 0 "arm_general_register_operand" "+r") 1721 (lshiftrt:DI (match_dup 0) 1722 (match_operand:SI 1 "long_shift_imm" "Pg")))] 1723 "TARGET_HAVE_MVE" 1724 "lsrl%?\\t%Q0, %R0, %1" 1725 [(set_attr "predicable" "yes")]) 1726 1727;; Originally expanded by 'doloop_end'. 1728(define_insn "*doloop_end_internal" 1729 [(set (pc) 1730 (if_then_else 1731 (ne (reg:SI LR_REGNUM) (const_int 1)) 1732 (label_ref (match_operand 0 "" "")) 1733 (pc))) 1734 (set (reg:SI LR_REGNUM) 1735 (plus:SI (reg:SI LR_REGNUM) (const_int -1))) 1736 (clobber (reg:CC CC_REGNUM))] 1737 "TARGET_32BIT && TARGET_HAVE_LOB" 1738 { 1739 if (get_attr_length (insn) == 4) 1740 return "le\t%|lr, %l0"; 1741 else 1742 return "subs\t%|lr, #1;bne\t%l0"; 1743 } 1744 [(set (attr "length") 1745 (if_then_else 1746 (ltu (minus (pc) (match_dup 0)) (const_int 1024)) 1747 (const_int 4) 1748 (const_int 6))) 1749 (set_attr "type" "branch")]) 1750 1751(define_expand "doloop_begin" 1752 [(match_operand 0 "" "") 1753 (match_operand 1 "" "")] 1754 "TARGET_32BIT && TARGET_HAVE_LOB" 1755 { 1756 if (REGNO (operands[0]) == LR_REGNUM) 1757 { 1758 emit_insn (gen_dls_insn (operands[0])); 1759 DONE; 1760 } 1761 else 1762 FAIL; 1763 }) 1764 1765(define_insn "dls_insn" 1766 [(set (reg:SI LR_REGNUM) 1767 (unspec:SI [(match_operand:SI 0 "s_register_operand" "r")] UNSPEC_DLS))] 1768 "TARGET_32BIT && TARGET_HAVE_LOB" 1769 "dls\t%|lr, %0") 1770