1 ;; ARM Thumb-1 Machine Description 2 ;; Copyright (C) 2007-2022 Free Software Foundation, Inc. 3 ;; 4 ;; This file is part of GCC. 5 ;; 6 ;; GCC is free software; you can redistribute it and/or modify it 7 ;; under the terms of the GNU General Public License as published by 8 ;; the Free Software Foundation; either version 3, or (at your option) 9 ;; any later version. 10 ;; 11 ;; GCC is distributed in the hope that it will be useful, but 12 ;; WITHOUT ANY WARRANTY; without even the implied warranty of 13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 ;; General Public License for more details. 15 ;; 16 ;; You should have received a copy of the GNU General Public License 17 ;; along with GCC; see the file COPYING3. If not see 18 ;; <http://www.gnu.org/licenses/>. */ 19 20 22 ;;--------------------------------------------------------------------------- 23 ;; Insn patterns 24 ;; 25 26 ;; Beware of splitting Thumb1 patterns that output multiple 27 ;; assembly instructions, in particular instruction such as SBC and 28 ;; ADC which consume flags. For example, in the pattern thumb_subdi3 29 ;; below, the output SUB implicitly sets the flags (assembled to SUBS) 30 ;; and then the Carry flag is used by SBC to compute the correct 31 ;; result. If we split thumb_subdi3 pattern into two separate RTL 32 ;; insns (using define_insn_and_split), the scheduler might place 33 ;; other RTL insns between SUB and SBC, possibly modifying the Carry 34 ;; flag used by SBC. This might happen because most Thumb1 patterns 35 ;; for flag-setting instructions do not have explicit RTL for setting 36 ;; or clobbering the flags. Instead, they have the attribute "conds" 37 ;; with value "set" or "clob". However, this attribute is not used to 38 ;; identify dependencies and therefore the scheduler might reorder 39 ;; these instruction. Currenly, this problem cannot happen because 40 ;; there are no separate Thumb1 patterns for individual instruction 41 ;; that consume flags (except conditional execution, which is treated 42 ;; differently). In particular there is no Thumb1 armv6-m pattern for 43 ;; sbc or adc. 44 45 46 47 (define_insn "*thumb1_adddi3" 48 [(set (match_operand:DI 0 "register_operand" "=l") 49 (plus:DI (match_operand:DI 1 "register_operand" "%0") 50 (match_operand:DI 2 "register_operand" "l"))) 51 (clobber (reg:CC CC_REGNUM)) 52 ] 53 "TARGET_THUMB1" 54 "adds\\t%Q0, %Q0, %Q2\;adcs\\t%R0, %R0, %R2" 55 [(set_attr "length" "4") 56 (set_attr "type" "multiple")] 57 ) 58 59 ;; Changes to the constraints of this pattern must be propagated to those of 60 ;; atomic additions in sync.md and to the logic for bind_old_new in 61 ;; arm_split_atomic_op in arm.cc. These must be at least as strict as the 62 ;; constraints here and aim to be as permissive. 63 (define_insn_and_split "*thumb1_addsi3" 64 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l") 65 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k") 66 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))] 67 "TARGET_THUMB1" 68 "* 69 static const char * const asms[] = 70 { 71 \"adds\\t%0, %0, %2\", 72 \"subs\\t%0, %0, #%n2\", 73 \"adds\\t%0, %1, %2\", 74 \"add\\t%0, %0, %2\", 75 \"add\\t%0, %0, %2\", 76 \"add\\t%0, %1, %2\", 77 \"add\\t%0, %1, %2\", 78 \"#\", 79 \"#\", 80 \"#\" 81 }; 82 if ((which_alternative == 2 || which_alternative == 6) 83 && CONST_INT_P (operands[2]) 84 && INTVAL (operands[2]) < 0) 85 return (which_alternative == 2) ? \"subs\\t%0, %1, #%n2\" : \"sub\\t%0, %1, #%n2\"; 86 return asms[which_alternative]; 87 " 88 "&& reload_completed && CONST_INT_P (operands[2]) 89 && ((operands[1] != stack_pointer_rtx 90 && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255)) 91 || (operands[1] == stack_pointer_rtx 92 && INTVAL (operands[2]) > 1020))" 93 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) 94 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] 95 { 96 HOST_WIDE_INT offset = INTVAL (operands[2]); 97 if (operands[1] == stack_pointer_rtx) 98 offset -= 1020; 99 else 100 { 101 if (offset > 255) 102 offset = 255; 103 else if (offset < -255) 104 offset = -255; 105 } 106 operands[3] = GEN_INT (offset); 107 operands[2] = GEN_INT (INTVAL (operands[2]) - offset); 108 } 109 [(set_attr "length" "2,2,2,2,2,2,2,4,4,4") 110 (set_attr "type" "alus_imm,alus_imm,alus_sreg,alus_sreg,alus_sreg, 111 alus_sreg,alus_sreg,multiple,multiple,multiple")] 112 ) 113 114 ;; Reloading and elimination of the frame pointer can 115 ;; sometimes cause this optimization to be missed. 116 (define_peephole2 117 [(set (match_operand:SI 0 "arm_general_register_operand" "") 118 (match_operand:SI 1 "const_int_operand" "")) 119 (set (match_dup 0) 120 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))] 121 "TARGET_THUMB1 122 && UINTVAL (operands[1]) < 1024 123 && (UINTVAL (operands[1]) & 3) == 0" 124 [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))] 125 "" 126 ) 127 128 (define_insn "*thumb_subdi3" 129 [(set (match_operand:DI 0 "register_operand" "=l") 130 (minus:DI (match_operand:DI 1 "register_operand" "0") 131 (match_operand:DI 2 "register_operand" "l"))) 132 (clobber (reg:CC CC_REGNUM))] 133 "TARGET_THUMB1" 134 "subs\\t%Q0, %Q0, %Q2\;sbcs\\t%R0, %R0, %R2" 135 [(set_attr "length" "4") 136 (set_attr "type" "multiple")] 137 ) 138 139 ;; Changes to the constraints of this pattern must be propagated to those of 140 ;; atomic subtractions in sync.md and to the logic for bind_old_new in 141 ;; arm_split_atomic_op in arm.cc. These must be at least as strict as the 142 ;; constraints here and aim to be as permissive. 143 (define_insn "thumb1_subsi3_insn" 144 [(set (match_operand:SI 0 "register_operand" "=l") 145 (minus:SI (match_operand:SI 1 "register_operand" "l") 146 (match_operand:SI 2 "reg_or_int_operand" "lPd")))] 147 "TARGET_THUMB1" 148 "subs\\t%0, %1, %2" 149 [(set_attr "length" "2") 150 (set_attr "conds" "set") 151 (set_attr "type" "alus_sreg")] 152 ) 153 154 ;; Unfortunately on Thumb the '&'/'0' trick can fail when operands 155 ;; 1 and 2 are the same, because reload will make operand 0 match 156 ;; operand 1 without realizing that this conflicts with operand 2. We fix 157 ;; this by adding another alternative to match this case, and then `reload' 158 ;; it ourselves. This alternative must come first. 159 (define_insn "*thumb_mulsi3" 160 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l") 161 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0") 162 (match_operand:SI 2 "register_operand" "l,l,l")))] 163 "TARGET_THUMB1 && !arm_arch6" 164 "@ 165 movs\\t%0, %1\;muls\\t%0, %2 166 mov\\t%0, %1\;muls\\t%0, %2 167 muls\\t%0, %2" 168 [(set_attr "length" "4,4,2") 169 (set_attr "type" "muls")] 170 ) 171 172 (define_insn "*thumb_mulsi3_v6" 173 [(set (match_operand:SI 0 "register_operand" "=l,l,l") 174 (mult:SI (match_operand:SI 1 "register_operand" "0,l,0") 175 (match_operand:SI 2 "register_operand" "l,0,0")))] 176 "TARGET_THUMB1 && arm_arch6" 177 "@ 178 muls\\t%0, %2 179 muls\\t%0, %1 180 muls\\t%0, %1" 181 [(set_attr "length" "2") 182 (set_attr "type" "muls")] 183 ) 184 185 ;; Changes to the constraints of this pattern must be propagated to those of 186 ;; atomic bitwise ANDs and NANDs in sync.md and to the logic for bind_old_new 187 ;; in arm_split_atomic_op in arm.cc. These must be at least as strict as the 188 ;; constraints here and aim to be as permissive. 189 (define_insn "*thumb1_andsi3_insn" 190 [(set (match_operand:SI 0 "register_operand" "=l") 191 (and:SI (match_operand:SI 1 "register_operand" "%0") 192 (match_operand:SI 2 "register_operand" "l")))] 193 "TARGET_THUMB1" 194 "ands\\t%0, %2" 195 [(set_attr "length" "2") 196 (set_attr "type" "logic_imm") 197 (set_attr "conds" "set")]) 198 199 (define_split 200 [(set (match_operand:SI 0 "s_register_operand" "") 201 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "") 202 (match_operand:SI 2 "const_int_operand" "") 203 (match_operand:SI 3 "const_int_operand" ""))) 204 (clobber (match_operand:SI 4 "s_register_operand" ""))] 205 "TARGET_THUMB1" 206 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2))) 207 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))] 208 "{ 209 HOST_WIDE_INT temp = INTVAL (operands[2]); 210 211 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3])); 212 operands[3] = GEN_INT (32 - temp); 213 }" 214 ) 215 216 (define_split 217 [(set (match_operand:SI 0 "s_register_operand" "") 218 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "") 219 (match_operand:SI 2 "const_int_operand" "") 220 (match_operand:SI 3 "const_int_operand" "")))] 221 "TARGET_THUMB1" 222 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) 223 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))] 224 "{ 225 HOST_WIDE_INT temp = INTVAL (operands[2]); 226 227 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3])); 228 operands[3] = GEN_INT (32 - temp); 229 }" 230 ) 231 232 (define_insn "thumb1_bicsi3" 233 [(set (match_operand:SI 0 "register_operand" "=l") 234 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l")) 235 (match_operand:SI 2 "register_operand" "0")))] 236 "TARGET_THUMB1" 237 "bics\\t%0, %1" 238 [(set_attr "length" "2") 239 (set_attr "conds" "set") 240 (set_attr "type" "logics_reg")] 241 ) 242 243 ;; Changes to the constraints of this pattern must be propagated to those of 244 ;; atomic inclusive ORs in sync.md and to the logic for bind_old_new in 245 ;; arm_split_atomic_op in arm.cc. These must be at least as strict as the 246 ;; constraints here and aim to be as permissive. 247 (define_insn "*thumb1_iorsi3_insn" 248 [(set (match_operand:SI 0 "register_operand" "=l") 249 (ior:SI (match_operand:SI 1 "register_operand" "%0") 250 (match_operand:SI 2 "register_operand" "l")))] 251 "TARGET_THUMB1" 252 "orrs\\t%0, %2" 253 [(set_attr "length" "2") 254 (set_attr "conds" "set") 255 (set_attr "type" "logics_reg")]) 256 257 ;; Changes to the constraints of this pattern must be propagated to those of 258 ;; atomic exclusive ORs in sync.md and to the logic for bind_old_new in 259 ;; arm_split_atomic_op in arm.cc. These must be at least as strict as the 260 ;; constraints here and aim to be as permissive. 261 (define_insn "*thumb1_xorsi3_insn" 262 [(set (match_operand:SI 0 "register_operand" "=l") 263 (xor:SI (match_operand:SI 1 "register_operand" "%0") 264 (match_operand:SI 2 "register_operand" "l")))] 265 "TARGET_THUMB1" 266 "eors\\t%0, %2" 267 [(set_attr "length" "2") 268 (set_attr "conds" "set") 269 (set_attr "type" "logics_reg")] 270 ) 271 272 (define_insn "*thumb1_ashlsi3" 273 [(set (match_operand:SI 0 "register_operand" "=l,l") 274 (ashift:SI (match_operand:SI 1 "register_operand" "l,0") 275 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 276 "TARGET_THUMB1" 277 "lsls\\t%0, %1, %2" 278 [(set_attr "length" "2") 279 (set_attr "type" "shift_imm,shift_reg") 280 (set_attr "conds" "set")]) 281 282 (define_insn "*thumb1_ashrsi3" 283 [(set (match_operand:SI 0 "register_operand" "=l,l") 284 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 285 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 286 "TARGET_THUMB1" 287 "asrs\\t%0, %1, %2" 288 [(set_attr "length" "2") 289 (set_attr "type" "shift_imm,shift_reg") 290 (set_attr "conds" "set")]) 291 292 (define_insn "*thumb1_lshrsi3" 293 [(set (match_operand:SI 0 "register_operand" "=l,l") 294 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0") 295 (match_operand:SI 2 "nonmemory_operand" "N,l")))] 296 "TARGET_THUMB1" 297 "lsrs\\t%0, %1, %2" 298 [(set_attr "length" "2") 299 (set_attr "type" "shift_imm,shift_reg") 300 (set_attr "conds" "set")]) 301 302 (define_insn "*thumb1_rotrsi3" 303 [(set (match_operand:SI 0 "register_operand" "=l") 304 (rotatert:SI (match_operand:SI 1 "register_operand" "0") 305 (match_operand:SI 2 "register_operand" "l")))] 306 "TARGET_THUMB1" 307 "rors\\t%0, %0, %2" 308 [(set_attr "type" "shift_reg") 309 (set_attr "length" "2")] 310 ) 311 312 (define_insn "*thumb1_negdi2" 313 [(set (match_operand:DI 0 "register_operand" "=&l") 314 (neg:DI (match_operand:DI 1 "register_operand" "l"))) 315 (clobber (reg:CC CC_REGNUM))] 316 "TARGET_THUMB1" 317 "movs\\t%R0, #0\;rsbs\\t%Q0, %Q1, #0\;sbcs\\t%R0, %R1" 318 [(set_attr "length" "6") 319 (set_attr "type" "multiple")] 320 ) 321 322 (define_insn "*thumb1_negsi2" 323 [(set (match_operand:SI 0 "register_operand" "=l") 324 (neg:SI (match_operand:SI 1 "register_operand" "l")))] 325 "TARGET_THUMB1" 326 "rsbs\\t%0, %1, #0" 327 [(set_attr "length" "2") 328 (set_attr "type" "alu_imm")] 329 ) 330 331 (define_insn_and_split "*thumb1_abssi2" 332 [(set (match_operand:SI 0 "s_register_operand" "=l") 333 (abs:SI (match_operand:SI 1 "s_register_operand" "l"))) 334 (clobber (match_scratch:SI 2 "=&l"))] 335 "TARGET_THUMB1" 336 "#" 337 "TARGET_THUMB1 && reload_completed" 338 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31))) 339 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) 340 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))] 341 "" 342 [(set_attr "length" "6") 343 (set_attr "type" "multiple")] 344 ) 345 346 (define_insn_and_split "*thumb1_neg_abssi2" 347 [(set (match_operand:SI 0 "s_register_operand" "=l") 348 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l")))) 349 (clobber (match_scratch:SI 2 "=&l"))] 350 "TARGET_THUMB1" 351 "#" 352 "TARGET_THUMB1 && reload_completed" 353 [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31))) 354 (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1))) 355 (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))] 356 "" 357 [(set_attr "length" "6") 358 (set_attr "type" "multiple")] 359 ) 360 361 (define_insn "*thumb1_one_cmplsi2" 362 [(set (match_operand:SI 0 "register_operand" "=l") 363 (not:SI (match_operand:SI 1 "register_operand" "l")))] 364 "TARGET_THUMB1" 365 "mvns\\t%0, %1" 366 [(set_attr "length" "2") 367 (set_attr "type" "mvn_reg")] 368 ) 369 370 (define_insn "*thumb1_zero_extendhisi2" 371 [(set (match_operand:SI 0 "register_operand" "=l,l") 372 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))] 373 "TARGET_THUMB1" 374 { 375 rtx mem; 376 377 if (which_alternative == 0 && arm_arch6) 378 return "uxth\t%0, %1"; 379 if (which_alternative == 0) 380 return "#"; 381 382 mem = XEXP (operands[1], 0); 383 384 if (GET_CODE (mem) == CONST) 385 mem = XEXP (mem, 0); 386 387 if (GET_CODE (mem) == PLUS) 388 { 389 rtx a = XEXP (mem, 0); 390 391 /* This can happen due to bugs in reload. */ 392 if (REG_P (a) && REGNO (a) == SP_REGNUM) 393 { 394 rtx ops[2]; 395 ops[0] = operands[0]; 396 ops[1] = a; 397 398 output_asm_insn ("mov\t%0, %1", ops); 399 400 XEXP (mem, 0) = operands[0]; 401 } 402 } 403 404 return "ldrh\t%0, %1"; 405 } 406 [(set_attr_alternative "length" 407 [(if_then_else (eq_attr "is_arch6" "yes") 408 (const_int 2) (const_int 4)) 409 (const_int 4)]) 410 (set_attr "type" "extend,load_byte")] 411 ) 412 413 (define_insn "*thumb1_zero_extendqisi2" 414 [(set (match_operand:SI 0 "register_operand" "=l,l") 415 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))] 416 "TARGET_THUMB1 && !arm_arch6" 417 "@ 418 # 419 ldrb\\t%0, %1" 420 [(set_attr "length" "4,2") 421 (set_attr "type" "alu_shift_reg,load_byte") 422 (set_attr "pool_range" "*,32")] 423 ) 424 425 (define_insn "*thumb1_zero_extendqisi2_v6" 426 [(set (match_operand:SI 0 "register_operand" "=l,l") 427 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))] 428 "TARGET_THUMB1 && arm_arch6" 429 "@ 430 uxtb\\t%0, %1 431 ldrb\\t%0, %1" 432 [(set_attr "length" "2") 433 (set_attr "type" "extend,load_byte")] 434 ) 435 436 ;; We used to have an early-clobber on the scratch register here. 437 ;; However, there's a bug somewhere in reload which means that this 438 ;; can be partially ignored during spill allocation if the memory 439 ;; address also needs reloading; this causes us to die later on when 440 ;; we try to verify the operands. Fortunately, we don't really need 441 ;; the early-clobber: we can always use operand 0 if operand 2 442 ;; overlaps the address. 443 (define_insn "thumb1_extendhisi2" 444 [(set (match_operand:SI 0 "register_operand" "=l,l") 445 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m"))) 446 (clobber (match_scratch:SI 2 "=X,l"))] 447 "TARGET_THUMB1" 448 "* 449 { 450 rtx ops[4]; 451 rtx mem; 452 453 if (which_alternative == 0 && !arm_arch6) 454 return \"#\"; 455 if (which_alternative == 0) 456 return \"sxth\\t%0, %1\"; 457 458 mem = XEXP (operands[1], 0); 459 460 /* This code used to try to use 'V', and fix the address only if it was 461 offsettable, but this fails for e.g. REG+48 because 48 is outside the 462 range of QImode offsets, and offsettable_address_p does a QImode 463 address check. */ 464 465 if (GET_CODE (mem) == CONST) 466 mem = XEXP (mem, 0); 467 468 if (GET_CODE (mem) == LABEL_REF) 469 return \"ldr\\t%0, %1\"; 470 471 if (GET_CODE (mem) == PLUS) 472 { 473 rtx a = XEXP (mem, 0); 474 rtx b = XEXP (mem, 1); 475 476 if (GET_CODE (a) == LABEL_REF 477 && CONST_INT_P (b)) 478 return \"ldr\\t%0, %1\"; 479 480 if (REG_P (b)) 481 return \"ldrsh\\t%0, %1\"; 482 483 ops[1] = a; 484 ops[2] = b; 485 } 486 else 487 { 488 ops[1] = mem; 489 ops[2] = const0_rtx; 490 } 491 492 gcc_assert (REG_P (ops[1])); 493 494 ops[0] = operands[0]; 495 if (reg_mentioned_p (operands[2], ops[1])) 496 ops[3] = ops[0]; 497 else 498 ops[3] = operands[2]; 499 output_asm_insn (\"movs\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops); 500 return \"\"; 501 }" 502 [(set_attr_alternative "length" 503 [(if_then_else (eq_attr "is_arch6" "yes") 504 (const_int 2) (const_int 4)) 505 (const_int 4)]) 506 (set_attr "type" "extend,load_byte") 507 (set_attr "pool_range" "*,1018")] 508 ) 509 510 (define_split 511 [(set (match_operand:SI 0 "register_operand" "") 512 (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))] 513 "TARGET_THUMB1 && reload_completed" 514 [(set (match_dup 0) (match_dup 2)) 515 (set (match_dup 0) (sign_extend:SI (match_dup 3)))] 516 { 517 rtx addr = XEXP (operands[1], 0); 518 519 if (GET_CODE (addr) == CONST) 520 addr = XEXP (addr, 0); 521 522 if (GET_CODE (addr) == PLUS 523 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1))) 524 /* No split necessary. */ 525 FAIL; 526 527 if (GET_CODE (addr) == PLUS 528 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1))) 529 FAIL; 530 531 if (reg_overlap_mentioned_p (operands[0], addr)) 532 { 533 rtx t = gen_lowpart (QImode, operands[0]); 534 emit_move_insn (t, operands[1]); 535 emit_insn (gen_thumb1_extendqisi2 (operands[0], t)); 536 DONE; 537 } 538 539 if (REG_P (addr)) 540 { 541 addr = gen_rtx_PLUS (Pmode, addr, operands[0]); 542 operands[2] = const0_rtx; 543 } 544 else if (GET_CODE (addr) != PLUS) 545 FAIL; 546 else if (REG_P (XEXP (addr, 0))) 547 { 548 operands[2] = XEXP (addr, 1); 549 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]); 550 } 551 else 552 { 553 operands[2] = XEXP (addr, 0); 554 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]); 555 } 556 557 operands[3] = change_address (operands[1], QImode, addr); 558 }) 559 560 (define_peephole2 561 [(set (match_operand:SI 0 "register_operand" "") 562 (plus:SI (match_dup 0) (match_operand 1 "const_int_operand"))) 563 (set (match_operand:SI 2 "register_operand" "") (const_int 0)) 564 (set (match_operand:SI 3 "register_operand" "") 565 (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))] 566 "TARGET_THUMB1 567 && GET_CODE (XEXP (operands[4], 0)) == PLUS 568 && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0)) 569 && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1)) 570 && (peep2_reg_dead_p (3, operands[0]) 571 || rtx_equal_p (operands[0], operands[3])) 572 && (peep2_reg_dead_p (3, operands[2]) 573 || rtx_equal_p (operands[2], operands[3]))" 574 [(set (match_dup 2) (match_dup 1)) 575 (set (match_dup 3) (sign_extend:SI (match_dup 4)))] 576 { 577 rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]); 578 operands[4] = change_address (operands[4], QImode, addr); 579 }) 580 581 (define_insn "thumb1_extendqisi2" 582 [(set (match_operand:SI 0 "register_operand" "=l,l,l") 583 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))] 584 "TARGET_THUMB1" 585 { 586 rtx addr; 587 588 if (which_alternative == 0 && arm_arch6) 589 return "sxtb\\t%0, %1"; 590 if (which_alternative == 0) 591 return "#"; 592 593 addr = XEXP (operands[1], 0); 594 if (GET_CODE (addr) == PLUS 595 && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1))) 596 return "ldrsb\\t%0, %1"; 597 598 return "#"; 599 } 600 [(set_attr_alternative "length" 601 [(if_then_else (eq_attr "is_arch6" "yes") 602 (const_int 2) (const_int 4)) 603 (const_int 2) 604 (if_then_else (eq_attr "is_arch6" "yes") 605 (const_int 4) (const_int 6))]) 606 (set_attr "type" "extend,load_byte,load_byte")] 607 ) 608 609 ;;; ??? This should have alternatives for constants. 610 ;;; ??? This was originally identical to the movdf_insn pattern. 611 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by 612 ;;; thumb_reorg with a memory reference. 613 (define_insn "*thumb1_movdi_insn" 614 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,r,l,>,l, m,*r") 615 (match_operand:DI 1 "general_operand" "l, I,J,j,>,l,mi,l,*r"))] 616 "TARGET_THUMB1 617 && ( register_operand (operands[0], DImode) 618 || register_operand (operands[1], DImode))" 619 "* 620 { 621 switch (which_alternative) 622 { 623 default: 624 case 0: 625 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 626 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\"; 627 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\"; 628 case 1: 629 return \"movs\\t%Q0, %1\;movs\\t%R0, #0\"; 630 case 2: 631 operands[1] = GEN_INT (- INTVAL (operands[1])); 632 return \"movs\\t%Q0, %1\;rsbs\\t%Q0, %Q0, #0\;asrs\\t%R0, %Q0, #31\"; 633 case 3: 634 gcc_assert (TARGET_HAVE_MOVT); 635 return \"movw\\t%Q0, %L1\;movs\\tR0, #0\"; 636 case 4: 637 return \"ldmia\\t%1, {%0, %H0}\"; 638 case 5: 639 return \"stmia\\t%0, {%1, %H1}\"; 640 case 6: 641 return thumb_load_double_from_address (operands); 642 case 7: 643 operands[2] = gen_rtx_MEM (SImode, 644 plus_constant (Pmode, XEXP (operands[0], 0), 4)); 645 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 646 return \"\"; 647 case 8: 648 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 649 return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 650 return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 651 } 652 }" 653 [(set_attr "length" "4,4,6,6,2,2,6,4,4") 654 (set_attr "type" "multiple,multiple,multiple,multiple,load_8,store_8,load_8,store_8,multiple") 655 (set_attr "arch" "t1,t1,t1,v8mb,t1,t1,t1,t1,t1") 656 (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")] 657 ) 658 659 (define_insn "*thumb1_movsi_insn" 660 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,r,l,l,l,>,l, l, m,*l*h*k") 661 (match_operand:SI 1 "general_operand" "l, I,j,J,K,>,l,i, mi,l,*l*h*k"))] 662 "TARGET_THUMB1 663 && ( register_operand (operands[0], SImode) 664 || register_operand (operands[1], SImode))" 665 { 666 switch (which_alternative) 667 { 668 default: 669 case 0: return "movs\t%0, %1"; 670 case 1: return "movs\t%0, %1"; 671 case 2: return "movw\t%0, %1"; 672 case 3: return "#"; 673 case 4: return "#"; 674 case 5: return "ldmia\t%1, {%0}"; 675 case 6: return "stmia\t%0, {%1}"; 676 case 7: 677 /* pure-code alternative: build the constant byte by byte, 678 instead of loading it from a constant pool. */ 679 if (arm_valid_symbolic_address_p (operands[1])) 680 { 681 output_asm_insn (\"movs\\t%0, #:upper8_15:%1\", operands); 682 output_asm_insn (\"lsls\\t%0, #8\", operands); 683 output_asm_insn (\"adds\\t%0, #:upper0_7:%1\", operands); 684 output_asm_insn (\"lsls\\t%0, #8\", operands); 685 output_asm_insn (\"adds\\t%0, #:lower8_15:%1\", operands); 686 output_asm_insn (\"lsls\\t%0, #8\", operands); 687 output_asm_insn (\"adds\\t%0, #:lower0_7:%1\", operands); 688 return \"\"; 689 } 690 else if (GET_CODE (operands[1]) == CONST_INT) 691 { 692 thumb1_gen_const_int_print (operands[0], INTVAL (operands[1])); 693 return \"\"; 694 } 695 696 gcc_unreachable (); 697 698 case 8: return "ldr\t%0, %1"; 699 case 9: return "str\t%1, %0"; 700 case 10: return "mov\t%0, %1"; 701 } 702 } 703 [(set_attr "length" "2,2,4,4,4,2,2,14,2,2,2") 704 (set_attr "type" "mov_reg,mov_imm,mov_imm,multiple,multiple,load_4,store_4,alu_sreg,load_4,store_4,mov_reg") 705 (set_attr "pool_range" "*,*,*,*,*,*,*, *,1018,*,*") 706 (set_attr "arch" "t1,t1,v8mb,t1,t1,t1,t1,t1,t1,t1,t1") 707 (set_attr "required_for_purecode" "no,no,no,no,no,no,no,yes,no,no,no") 708 (set_attr "conds" "set,clob,nocond,*,*,nocond,nocond,clob,nocond,nocond,nocond")]) 709 710 ; Split the load of 64-bit constant into two loads for high and low 32-bit parts respectively 711 ; to see if we can load them in fewer instructions or fewer cycles. 712 ; For the small 64-bit integer constants that satisfy constraint J, the instruction pattern 713 ; thumb1_movdi_insn has a better way to handle them. 714 (define_split 715 [(set (match_operand:ANY64 0 "arm_general_register_operand" "") 716 (match_operand:ANY64 1 "immediate_operand" ""))] 717 "TARGET_THUMB1 && reload_completed && !satisfies_constraint_J (operands[1])" 718 [(set (match_dup 0) (match_dup 1)) 719 (set (match_dup 2) (match_dup 3))] 720 " 721 operands[2] = gen_highpart (SImode, operands[0]); 722 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]), 723 operands[1]); 724 operands[0] = gen_lowpart (SImode, operands[0]); 725 operands[1] = gen_lowpart (SImode, operands[1]); 726 " 727 ) 728 729 (define_split 730 [(set (match_operand:SI 0 "register_operand" "") 731 (match_operand:SI 1 "const_int_operand" ""))] 732 "TARGET_THUMB1 && satisfies_constraint_J (operands[1])" 733 [(set (match_dup 2) (match_dup 1)) 734 (set (match_dup 0) (neg:SI (match_dup 2)))] 735 " 736 { 737 operands[1] = GEN_INT (- INTVAL (operands[1])); 738 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; 739 }" 740 ) 741 742 (define_split 743 [(set (match_operand:SI 0 "register_operand" "") 744 (match_operand:SI 1 "const_int_operand" ""))] 745 "TARGET_THUMB1 && satisfies_constraint_K (operands[1]) 746 && !(TARGET_HAVE_MOVT && satisfies_constraint_j (operands[1]))" 747 [(set (match_dup 2) (match_dup 1)) 748 (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))] 749 " 750 { 751 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu; 752 unsigned HOST_WIDE_INT mask = 0xff; 753 int i; 754 755 for (i = 0; i < 25; i++) 756 if ((val & (mask << i)) == val) 757 break; 758 759 /* Don't split if the shift is zero. */ 760 if (i == 0) 761 FAIL; 762 763 operands[1] = GEN_INT (val >> i); 764 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; 765 operands[3] = GEN_INT (i); 766 }" 767 ) 768 769 ;; For thumb1 split imm move [256-510] into mov [1-255] and add #255 770 (define_split 771 [(set (match_operand:SI 0 "register_operand" "") 772 (match_operand:SI 1 "const_int_operand" ""))] 773 "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1]) 774 && !(TARGET_HAVE_MOVT && satisfies_constraint_j (operands[1]))" 775 [(set (match_dup 2) (match_dup 1)) 776 (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))] 777 " 778 { 779 operands[1] = GEN_INT (INTVAL (operands[1]) - 255); 780 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; 781 operands[3] = GEN_INT (255); 782 }" 783 ) 784 785 (define_split 786 [(set (match_operand:SI 0 "register_operand" "") 787 (match_operand:SI 1 "const_int_operand" ""))] 788 "TARGET_THUMB1 789 && arm_disable_literal_pool 790 && GET_CODE (operands[1]) == CONST_INT 791 && !TARGET_HAVE_MOVT 792 && !satisfies_constraint_K (operands[1])" 793 [(clobber (const_int 0))] 794 " 795 thumb1_gen_const_int_rtl (operands[0], INTVAL (operands[1])); 796 DONE; 797 " 798 ) 799 800 (define_insn "*thumb1_movhi_insn" 801 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,l*r,*h,l,r") 802 (match_operand:HI 1 "general_operand" "l,m,l,k*h,*r,I,n"))] 803 "TARGET_THUMB1 804 && ( register_operand (operands[0], HImode) 805 || register_operand (operands[1], HImode))" 806 "* 807 switch (which_alternative) 808 { 809 case 0: return \"adds %0, %1, #0\"; 810 case 2: return \"strh %1, %0\"; 811 case 3: return \"mov %0, %1\"; 812 case 4: return \"mov %0, %1\"; 813 case 5: return \"movs %0, %1\"; 814 case 6: gcc_assert (TARGET_HAVE_MOVT); 815 return \"movw %0, %L1\"; 816 default: gcc_unreachable (); 817 case 1: 818 /* The stack pointer can end up being taken as an index register. 819 Catch this case here and deal with it. */ 820 if (GET_CODE (XEXP (operands[1], 0)) == PLUS 821 && REG_P (XEXP (XEXP (operands[1], 0), 0)) 822 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM) 823 { 824 rtx ops[2]; 825 ops[0] = operands[0]; 826 ops[1] = XEXP (XEXP (operands[1], 0), 0); 827 828 output_asm_insn (\"mov %0, %1\", ops); 829 830 XEXP (XEXP (operands[1], 0), 0) = operands[0]; 831 832 } 833 return \"ldrh %0, %1\"; 834 }" 835 [(set_attr "length" "2,4,2,2,2,2,4") 836 (set_attr "type" "alus_imm,load_4,store_4,mov_reg,mov_reg,mov_imm,mov_imm") 837 (set_attr "arch" "t1,t1,t1,t1,t1,t1,v8mb") 838 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob,nocond")]) 839 840 (define_expand "thumb_movhi_clobber" 841 [(set (match_operand:HI 0 "memory_operand") 842 (match_operand:HI 1 "register_operand")) 843 (clobber (match_operand:DI 2 "register_operand"))] 844 "TARGET_THUMB1" 845 " 846 if (strict_memory_address_p (HImode, XEXP (operands[0], 0)) 847 && REGNO (operands[1]) <= LAST_LO_REGNUM) 848 { 849 emit_insn (gen_movhi (operands[0], operands[1])); 850 DONE; 851 } 852 /* XXX Fixme, need to handle other cases here as well. */ 853 gcc_unreachable (); 854 " 855 ) 856 857 (define_insn "*thumb1_movqi_insn" 858 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,l*r,*h,l") 859 (match_operand:QI 1 "general_operand" "l,m,l,k*h,*r,I"))] 860 "TARGET_THUMB1 861 && ( register_operand (operands[0], QImode) 862 || register_operand (operands[1], QImode))" 863 "@ 864 adds\\t%0, %1, #0 865 ldrb\\t%0, %1 866 strb\\t%1, %0 867 mov\\t%0, %1 868 mov\\t%0, %1 869 movs\\t%0, %1" 870 [(set_attr "length" "2") 871 (set_attr "type" "alu_imm,load_4,store_4,mov_reg,mov_imm,mov_imm") 872 (set_attr "pool_range" "*,32,*,*,*,*") 873 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")]) 874 875 (define_insn "*thumb1_movhf" 876 [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,l,m,*r,*h") 877 (match_operand:HF 1 "general_operand" "l, m,F,l,*h,*r"))] 878 "TARGET_THUMB1 879 && ( s_register_operand (operands[0], HFmode) 880 || s_register_operand (operands[1], HFmode))" 881 "* 882 switch (which_alternative) 883 { 884 case 0: 885 return \"movs\\t%0, %1\"; 886 case 1: 887 { 888 rtx addr; 889 gcc_assert (MEM_P (operands[1])); 890 addr = XEXP (operands[1], 0); 891 if (GET_CODE (addr) == LABEL_REF 892 || (GET_CODE (addr) == CONST 893 && GET_CODE (XEXP (addr, 0)) == PLUS 894 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF 895 && CONST_INT_P (XEXP (XEXP (addr, 0), 1)))) 896 { 897 /* Constant pool entry. */ 898 return \"ldr\\t%0, %1\"; 899 } 900 return \"ldrh\\t%0, %1\"; 901 } 902 case 2: 903 { 904 int bits; 905 int high; 906 rtx ops[3]; 907 908 bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), 909 HFmode); 910 ops[0] = operands[0]; 911 high = (bits >> 8) & 0xff; 912 ops[1] = GEN_INT (high); 913 ops[2] = GEN_INT (bits & 0xff); 914 if (high != 0) 915 output_asm_insn (\"movs\\t%0, %1\;lsls\\t%0, #8\;adds\\t%0, %2\", ops); 916 else 917 output_asm_insn (\"movs\\t%0, %2\", ops); 918 919 return \"\"; 920 } 921 case 3: return \"strh\\t%1, %0\"; 922 default: return \"mov\\t%0, %1\"; 923 } 924 " 925 [(set_attr "length" "2,2,6,2,2,2") 926 (set_attr "type" "mov_reg,load_4,mov_reg,store_4,mov_reg,mov_reg") 927 (set_attr "pool_range" "*,1018,*,*,*,*") 928 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond")]) 929 930 ;;; ??? This should have alternatives for constants. 931 (define_insn "*thumb1_movsf_insn" 932 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h") 933 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))] 934 "TARGET_THUMB1 935 && ( register_operand (operands[0], SFmode) 936 || register_operand (operands[1], SFmode))" 937 "@ 938 adds\\t%0, %1, #0 939 ldmia\\t%1, {%0} 940 stmia\\t%0, {%1} 941 ldr\\t%0, %1 942 str\\t%1, %0 943 mov\\t%0, %1 944 mov\\t%0, %1" 945 [(set_attr "length" "2") 946 (set_attr "type" "alus_imm,load_4,store_4,load_4,store_4,mov_reg,mov_reg") 947 (set_attr "pool_range" "*,*,*,1018,*,*,*") 948 (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")] 949 ) 950 951 ;;; ??? This should have alternatives for constants. 952 ;;; ??? This was originally identical to the movdi_insn pattern. 953 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by 954 ;;; thumb_reorg with a memory reference. 955 (define_insn "*thumb_movdf_insn" 956 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r") 957 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))] 958 "TARGET_THUMB1 959 && ( register_operand (operands[0], DFmode) 960 || register_operand (operands[1], DFmode))" 961 "* 962 switch (which_alternative) 963 { 964 default: 965 case 0: 966 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 967 return \"adds\\t%0, %1, #0\;adds\\t%H0, %H1, #0\"; 968 return \"adds\\t%H0, %H1, #0\;adds\\t%0, %1, #0\"; 969 case 1: 970 return \"ldmia\\t%1, {%0, %H0}\"; 971 case 2: 972 return \"stmia\\t%0, {%1, %H1}\"; 973 case 3: 974 return thumb_load_double_from_address (operands); 975 case 4: 976 operands[2] = gen_rtx_MEM (SImode, 977 plus_constant (Pmode, 978 XEXP (operands[0], 0), 4)); 979 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands); 980 return \"\"; 981 case 5: 982 if (REGNO (operands[1]) == REGNO (operands[0]) + 1) 983 return \"mov\\t%0, %1\;mov\\t%H0, %H1\"; 984 return \"mov\\t%H0, %H1\;mov\\t%0, %1\"; 985 } 986 " 987 [(set_attr "length" "4,2,2,6,4,4") 988 (set_attr "type" "multiple,load_8,store_8,load_8,store_8,multiple") 989 (set_attr "pool_range" "*,*,*,1018,*,*")] 990 ) 991 993 994 ;; Thumb block-move insns 995 996 (define_insn "cpymem12b" 997 [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 998 (mem:SI (match_operand:SI 3 "register_operand" "1"))) 999 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 1000 (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 1001 (set (mem:SI (plus:SI (match_dup 2) (const_int 8))) 1002 (mem:SI (plus:SI (match_dup 3) (const_int 8)))) 1003 (set (match_operand:SI 0 "register_operand" "=l") 1004 (plus:SI (match_dup 2) (const_int 12))) 1005 (set (match_operand:SI 1 "register_operand" "=l") 1006 (plus:SI (match_dup 3) (const_int 12))) 1007 (clobber (match_scratch:SI 4 "=&l")) 1008 (clobber (match_scratch:SI 5 "=&l")) 1009 (clobber (match_scratch:SI 6 "=&l"))] 1010 "TARGET_THUMB1" 1011 "* return thumb_output_move_mem_multiple (3, operands);" 1012 [(set_attr "length" "4") 1013 ; This isn't entirely accurate... It loads as well, but in terms of 1014 ; scheduling the following insn it is better to consider it as a store 1015 (set_attr "type" "store_12")] 1016 ) 1017 1018 (define_insn "cpymem8b" 1019 [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) 1020 (mem:SI (match_operand:SI 3 "register_operand" "1"))) 1021 (set (mem:SI (plus:SI (match_dup 2) (const_int 4))) 1022 (mem:SI (plus:SI (match_dup 3) (const_int 4)))) 1023 (set (match_operand:SI 0 "register_operand" "=l") 1024 (plus:SI (match_dup 2) (const_int 8))) 1025 (set (match_operand:SI 1 "register_operand" "=l") 1026 (plus:SI (match_dup 3) (const_int 8))) 1027 (clobber (match_scratch:SI 4 "=&l")) 1028 (clobber (match_scratch:SI 5 "=&l"))] 1029 "TARGET_THUMB1" 1030 "* return thumb_output_move_mem_multiple (2, operands);" 1031 [(set_attr "length" "4") 1032 ; This isn't entirely accurate... It loads as well, but in terms of 1033 ; scheduling the following insn it is better to consider it as a store 1034 (set_attr "type" "store_8")] 1035 ) 1036 1037 1039 ;; A pattern to recognize a special situation and optimize for it. 1040 ;; On the thumb, zero-extension from memory is preferrable to sign-extension 1041 ;; due to the available addressing modes. Hence, convert a signed comparison 1042 ;; with zero into an unsigned comparison with 127 if possible. 1043 (define_expand "cbranchqi4" 1044 [(set (pc) (if_then_else 1045 (match_operator 0 "lt_ge_comparison_operator" 1046 [(match_operand:QI 1 "memory_operand") 1047 (match_operand:QI 2 "const0_operand")]) 1048 (label_ref (match_operand 3 "" "")) 1049 (pc)))] 1050 "TARGET_THUMB1" 1051 { 1052 rtx xops[4]; 1053 xops[1] = gen_reg_rtx (SImode); 1054 emit_insn (gen_zero_extendqisi2 (xops[1], operands[1])); 1055 xops[2] = GEN_INT (127); 1056 xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU, 1057 VOIDmode, xops[1], xops[2]); 1058 xops[3] = operands[3]; 1059 emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3])); 1060 DONE; 1061 }) 1062 1063 ;; A pattern for the CB(N)Z instruction added in ARMv8-M Baseline profile, 1064 ;; adapted from cbranchsi4_insn. Modifying cbranchsi4_insn instead leads to 1065 ;; code generation difference for ARMv6-M because the minimum length of the 1066 ;; instruction becomes 2 even for ARMv6-M due to a limitation in genattrtab's 1067 ;; handling of PC in the length condition. 1068 (define_insn "thumb1_cbz" 1069 [(set (pc) (if_then_else 1070 (match_operator 0 "equality_operator" 1071 [(match_operand:SI 1 "s_register_operand" "l") 1072 (const_int 0)]) 1073 (label_ref (match_operand 2 "" "")) 1074 (pc)))] 1075 "TARGET_THUMB1 && TARGET_HAVE_CBZ" 1076 { 1077 if (get_attr_length (insn) == 2) 1078 { 1079 if (GET_CODE (operands[0]) == EQ) 1080 return "cbz\t%1, %l2"; 1081 else 1082 return "cbnz\t%1, %l2"; 1083 } 1084 else 1085 { 1086 rtx t = cfun->machine->thumb1_cc_insn; 1087 if (t != NULL_RTX) 1088 { 1089 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1]) 1090 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2])) 1091 t = NULL_RTX; 1092 if (cfun->machine->thumb1_cc_mode == CC_NZmode) 1093 { 1094 if (!nz_comparison_operator (operands[0], VOIDmode)) 1095 t = NULL_RTX; 1096 } 1097 else if (cfun->machine->thumb1_cc_mode != CCmode) 1098 t = NULL_RTX; 1099 } 1100 if (t == NULL_RTX) 1101 { 1102 output_asm_insn ("cmp\t%1, #0", operands); 1103 cfun->machine->thumb1_cc_insn = insn; 1104 cfun->machine->thumb1_cc_op0 = operands[1]; 1105 cfun->machine->thumb1_cc_op1 = operands[2]; 1106 cfun->machine->thumb1_cc_mode = CCmode; 1107 } 1108 else 1109 /* Ensure we emit the right type of condition code on the jump. */ 1110 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode, 1111 CC_REGNUM); 1112 1113 switch (get_attr_length (insn)) 1114 { 1115 case 4: return "b%d0\t%l2"; 1116 case 6: return "b%D0\t.LCB%=;b\t%l2\t%@long jump\n.LCB%=:"; 1117 case 8: return "b%D0\t.LCB%=;bl\t%l2\t%@far jump\n.LCB%=:"; 1118 default: gcc_unreachable (); 1119 } 1120 } 1121 } 1122 [(set (attr "far_jump") 1123 (if_then_else 1124 (eq_attr "length" "8") 1125 (const_string "yes") 1126 (const_string "no"))) 1127 (set (attr "length") 1128 (if_then_else 1129 (and (ge (minus (match_dup 2) (pc)) (const_int 2)) 1130 (le (minus (match_dup 2) (pc)) (const_int 128))) 1131 (const_int 2) 1132 (if_then_else 1133 (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 1134 (le (minus (match_dup 2) (pc)) (const_int 256))) 1135 (const_int 4) 1136 (if_then_else 1137 (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) 1138 (le (minus (match_dup 2) (pc)) (const_int 2048))) 1139 (const_int 6) 1140 (const_int 8))))) 1141 (set (attr "type") 1142 (if_then_else 1143 (eq_attr "length" "2") 1144 (const_string "branch") 1145 (const_string "multiple")))] 1146 ) 1147 1148 ;; Changes to the constraints of this pattern must be propagated to those of 1149 ;; atomic compare_and_swap splitters in sync.md. These must be at least as 1150 ;; strict as the constraints here and aim to be as permissive. 1151 (define_insn "cbranchsi4_insn" 1152 [(set (pc) (if_then_else 1153 (match_operator 0 "arm_comparison_operator" 1154 [(match_operand:SI 1 "s_register_operand" "l,l*h") 1155 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")]) 1156 (label_ref (match_operand 3 "" "")) 1157 (pc)))] 1158 "TARGET_THUMB1" 1159 { 1160 rtx t = cfun->machine->thumb1_cc_insn; 1161 if (t != NULL_RTX) 1162 { 1163 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1]) 1164 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2])) 1165 t = NULL_RTX; 1166 if (cfun->machine->thumb1_cc_mode == CC_NZmode) 1167 { 1168 if (!nz_comparison_operator (operands[0], VOIDmode)) 1169 t = NULL_RTX; 1170 } 1171 else if (cfun->machine->thumb1_cc_mode != CCmode) 1172 t = NULL_RTX; 1173 } 1174 if (t == NULL_RTX) 1175 { 1176 output_asm_insn ("cmp\t%1, %2", operands); 1177 cfun->machine->thumb1_cc_insn = insn; 1178 cfun->machine->thumb1_cc_op0 = operands[1]; 1179 cfun->machine->thumb1_cc_op1 = operands[2]; 1180 cfun->machine->thumb1_cc_mode = CCmode; 1181 } 1182 else 1183 /* Ensure we emit the right type of condition code on the jump. */ 1184 XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode, 1185 CC_REGNUM); 1186 1187 switch (get_attr_length (insn)) 1188 { 1189 case 4: return \"b%d0\\t%l3\"; 1190 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 1191 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 1192 } 1193 } 1194 [(set (attr "far_jump") 1195 (if_then_else 1196 (eq_attr "length" "8") 1197 (const_string "yes") 1198 (const_string "no"))) 1199 (set (attr "length") 1200 (if_then_else 1201 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 1202 (le (minus (match_dup 3) (pc)) (const_int 256))) 1203 (const_int 4) 1204 (if_then_else 1205 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 1206 (le (minus (match_dup 3) (pc)) (const_int 2048))) 1207 (const_int 6) 1208 (const_int 8)))) 1209 (set_attr "type" "multiple")] 1210 ) 1211 1212 ;; An expander which makes use of the cbranchsi4_scratch insn, but can 1213 ;; be used safely after RA. 1214 (define_expand "cbranchsi4_neg_late" 1215 [(parallel [ 1216 (set (pc) (if_then_else 1217 (match_operator 4 "arm_comparison_operator" 1218 [(match_operand:SI 1 "s_register_operand") 1219 (match_operand:SI 2 "thumb1_cmpneg_operand")]) 1220 (label_ref (match_operand 3 "" "")) 1221 (pc))) 1222 (clobber (match_operand:SI 0 "s_register_operand")) 1223 ])] 1224 "TARGET_THUMB1" 1225 ) 1226 1227 ;; Changes to the constraints of this pattern must be propagated to those of 1228 ;; atomic compare_and_swap splitters in sync.md. These must be at least as 1229 ;; strict as the constraints here and aim to be as permissive. 1230 (define_insn "cbranchsi4_scratch" 1231 [(set (pc) (if_then_else 1232 (match_operator 4 "arm_comparison_operator" 1233 [(match_operand:SI 1 "s_register_operand" "l,0") 1234 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")]) 1235 (label_ref (match_operand 3 "" "")) 1236 (pc))) 1237 (clobber (match_scratch:SI 0 "=l,l"))] 1238 "TARGET_THUMB1" 1239 "* 1240 output_asm_insn (\"adds\\t%0, %1, #%n2\", operands); 1241 1242 switch (get_attr_length (insn)) 1243 { 1244 case 4: return \"b%d4\\t%l3\"; 1245 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 1246 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 1247 } 1248 " 1249 [(set (attr "far_jump") 1250 (if_then_else 1251 (eq_attr "length" "8") 1252 (const_string "yes") 1253 (const_string "no"))) 1254 (set (attr "length") 1255 (if_then_else 1256 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 1257 (le (minus (match_dup 3) (pc)) (const_int 256))) 1258 (const_int 4) 1259 (if_then_else 1260 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 1261 (le (minus (match_dup 3) (pc)) (const_int 2048))) 1262 (const_int 6) 1263 (const_int 8)))) 1264 (set_attr "type" "multiple")] 1265 ) 1266 1267 (define_insn "*negated_cbranchsi4" 1268 [(set (pc) 1269 (if_then_else 1270 (match_operator 0 "equality_operator" 1271 [(match_operand:SI 1 "s_register_operand" "l") 1272 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))]) 1273 (label_ref (match_operand 3 "" "")) 1274 (pc)))] 1275 "TARGET_THUMB1" 1276 "* 1277 output_asm_insn (\"cmn\\t%1, %2\", operands); 1278 switch (get_attr_length (insn)) 1279 { 1280 case 4: return \"b%d0\\t%l3\"; 1281 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 1282 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 1283 } 1284 " 1285 [(set (attr "far_jump") 1286 (if_then_else 1287 (eq_attr "length" "8") 1288 (const_string "yes") 1289 (const_string "no"))) 1290 (set (attr "length") 1291 (if_then_else 1292 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 1293 (le (minus (match_dup 3) (pc)) (const_int 256))) 1294 (const_int 4) 1295 (if_then_else 1296 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 1297 (le (minus (match_dup 3) (pc)) (const_int 2048))) 1298 (const_int 6) 1299 (const_int 8)))) 1300 (set_attr "type" "multiple")] 1301 ) 1302 1303 (define_insn "*tbit_cbranch" 1304 [(set (pc) 1305 (if_then_else 1306 (match_operator 0 "equality_operator" 1307 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l") 1308 (const_int 1) 1309 (match_operand:SI 2 "const_int_operand" "i")) 1310 (const_int 0)]) 1311 (label_ref (match_operand 3 "" "")) 1312 (pc))) 1313 (clobber (match_scratch:SI 4 "=l"))] 1314 "TARGET_THUMB1" 1315 "* 1316 { 1317 rtx op[3]; 1318 op[0] = operands[4]; 1319 op[1] = operands[1]; 1320 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2])); 1321 1322 output_asm_insn (\"lsls\\t%0, %1, %2\", op); 1323 switch (get_attr_length (insn)) 1324 { 1325 case 4: return \"b%d0\\t%l3\"; 1326 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 1327 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 1328 } 1329 }" 1330 [(set (attr "far_jump") 1331 (if_then_else 1332 (eq_attr "length" "8") 1333 (const_string "yes") 1334 (const_string "no"))) 1335 (set (attr "length") 1336 (if_then_else 1337 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 1338 (le (minus (match_dup 3) (pc)) (const_int 256))) 1339 (const_int 4) 1340 (if_then_else 1341 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 1342 (le (minus (match_dup 3) (pc)) (const_int 2048))) 1343 (const_int 6) 1344 (const_int 8)))) 1345 (set_attr "type" "multiple")] 1346 ) 1347 1348 (define_insn "*tlobits_cbranch" 1349 [(set (pc) 1350 (if_then_else 1351 (match_operator 0 "equality_operator" 1352 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l") 1353 (match_operand:SI 2 "const_int_operand" "i") 1354 (const_int 0)) 1355 (const_int 0)]) 1356 (label_ref (match_operand 3 "" "")) 1357 (pc))) 1358 (clobber (match_scratch:SI 4 "=l"))] 1359 "TARGET_THUMB1" 1360 "* 1361 { 1362 rtx op[3]; 1363 op[0] = operands[4]; 1364 op[1] = operands[1]; 1365 op[2] = GEN_INT (32 - INTVAL (operands[2])); 1366 1367 output_asm_insn (\"lsls\\t%0, %1, %2\", op); 1368 switch (get_attr_length (insn)) 1369 { 1370 case 4: return \"b%d0\\t%l3\"; 1371 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\"; 1372 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\"; 1373 } 1374 }" 1375 [(set (attr "far_jump") 1376 (if_then_else 1377 (eq_attr "length" "8") 1378 (const_string "yes") 1379 (const_string "no"))) 1380 (set (attr "length") 1381 (if_then_else 1382 (and (ge (minus (match_dup 3) (pc)) (const_int -250)) 1383 (le (minus (match_dup 3) (pc)) (const_int 256))) 1384 (const_int 4) 1385 (if_then_else 1386 (and (ge (minus (match_dup 3) (pc)) (const_int -2040)) 1387 (le (minus (match_dup 3) (pc)) (const_int 2048))) 1388 (const_int 6) 1389 (const_int 8)))) 1390 (set_attr "type" "multiple")] 1391 ) 1392 1393 (define_insn "*tstsi3_cbranch" 1394 [(set (pc) 1395 (if_then_else 1396 (match_operator 3 "equality_operator" 1397 [(and:SI (match_operand:SI 0 "s_register_operand" "%l") 1398 (match_operand:SI 1 "s_register_operand" "l")) 1399 (const_int 0)]) 1400 (label_ref (match_operand 2 "" "")) 1401 (pc)))] 1402 "TARGET_THUMB1" 1403 "* 1404 { 1405 output_asm_insn (\"tst\\t%0, %1\", operands); 1406 switch (get_attr_length (insn)) 1407 { 1408 case 4: return \"b%d3\\t%l2\"; 1409 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\"; 1410 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\"; 1411 } 1412 }" 1413 [(set (attr "far_jump") 1414 (if_then_else 1415 (eq_attr "length" "8") 1416 (const_string "yes") 1417 (const_string "no"))) 1418 (set (attr "length") 1419 (if_then_else 1420 (and (ge (minus (match_dup 2) (pc)) (const_int -250)) 1421 (le (minus (match_dup 2) (pc)) (const_int 256))) 1422 (const_int 4) 1423 (if_then_else 1424 (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) 1425 (le (minus (match_dup 2) (pc)) (const_int 2048))) 1426 (const_int 6) 1427 (const_int 8)))) 1428 (set_attr "type" "multiple")] 1429 ) 1430 1431 (define_insn "*cbranchne_decr1" 1432 [(set (pc) 1433 (if_then_else (match_operator 3 "equality_operator" 1434 [(match_operand:SI 2 "s_register_operand" "l,l,1,l") 1435 (const_int 0)]) 1436 (label_ref (match_operand 4 "" "")) 1437 (pc))) 1438 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m") 1439 (plus:SI (match_dup 2) (const_int -1))) 1440 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))] 1441 "TARGET_THUMB1" 1442 "* 1443 { 1444 rtx cond[2]; 1445 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE 1446 ? GEU : LTU), 1447 VOIDmode, operands[2], const1_rtx); 1448 cond[1] = operands[4]; 1449 1450 if (which_alternative == 0) 1451 output_asm_insn (\"subs\\t%0, %2, #1\", operands); 1452 else if (which_alternative == 1) 1453 { 1454 /* We must provide an alternative for a hi reg because reload 1455 cannot handle output reloads on a jump instruction, but we 1456 can't subtract into that. Fortunately a mov from lo to hi 1457 does not clobber the condition codes. */ 1458 output_asm_insn (\"subs\\t%1, %2, #1\", operands); 1459 output_asm_insn (\"mov\\t%0, %1\", operands); 1460 } 1461 else 1462 { 1463 /* Similarly, but the target is memory. */ 1464 output_asm_insn (\"subs\\t%1, %2, #1\", operands); 1465 output_asm_insn (\"str\\t%1, %0\", operands); 1466 } 1467 1468 switch (get_attr_length (insn) - (which_alternative ? 2 : 0)) 1469 { 1470 case 4: 1471 output_asm_insn (\"b%d0\\t%l1\", cond); 1472 return \"\"; 1473 case 6: 1474 output_asm_insn (\"b%D0\\t.LCB%=\", cond); 1475 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\"; 1476 default: 1477 output_asm_insn (\"b%D0\\t.LCB%=\", cond); 1478 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 1479 } 1480 } 1481 " 1482 [(set (attr "far_jump") 1483 (if_then_else 1484 (ior (and (eq (symbol_ref ("which_alternative")) 1485 (const_int 0)) 1486 (eq_attr "length" "8")) 1487 (eq_attr "length" "10")) 1488 (const_string "yes") 1489 (const_string "no"))) 1490 (set_attr_alternative "length" 1491 [ 1492 ;; Alternative 0 1493 (if_then_else 1494 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 1495 (le (minus (match_dup 4) (pc)) (const_int 256))) 1496 (const_int 4) 1497 (if_then_else 1498 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 1499 (le (minus (match_dup 4) (pc)) (const_int 2048))) 1500 (const_int 6) 1501 (const_int 8))) 1502 ;; Alternative 1 1503 (if_then_else 1504 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 1505 (le (minus (match_dup 4) (pc)) (const_int 256))) 1506 (const_int 6) 1507 (if_then_else 1508 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 1509 (le (minus (match_dup 4) (pc)) (const_int 2048))) 1510 (const_int 8) 1511 (const_int 10))) 1512 ;; Alternative 2 1513 (if_then_else 1514 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 1515 (le (minus (match_dup 4) (pc)) (const_int 256))) 1516 (const_int 6) 1517 (if_then_else 1518 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 1519 (le (minus (match_dup 4) (pc)) (const_int 2048))) 1520 (const_int 8) 1521 (const_int 10))) 1522 ;; Alternative 3 1523 (if_then_else 1524 (and (ge (minus (match_dup 4) (pc)) (const_int -248)) 1525 (le (minus (match_dup 4) (pc)) (const_int 256))) 1526 (const_int 6) 1527 (if_then_else 1528 (and (ge (minus (match_dup 4) (pc)) (const_int -2038)) 1529 (le (minus (match_dup 4) (pc)) (const_int 2048))) 1530 (const_int 8) 1531 (const_int 10)))]) 1532 (set_attr "type" "multiple")] 1533 ) 1534 1535 (define_insn "*addsi3_cbranch" 1536 [(set (pc) 1537 (if_then_else 1538 (match_operator 4 "arm_comparison_operator" 1539 [(plus:SI 1540 (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1") 1541 (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ")) 1542 (const_int 0)]) 1543 (label_ref (match_operand 5 "" "")) 1544 (pc))) 1545 (set 1546 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m") 1547 (plus:SI (match_dup 2) (match_dup 3))) 1548 (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))] 1549 "TARGET_THUMB1 1550 && (GET_CODE (operands[4]) == EQ 1551 || GET_CODE (operands[4]) == NE 1552 || GET_CODE (operands[4]) == GE 1553 || GET_CODE (operands[4]) == LT)" 1554 "* 1555 { 1556 rtx cond[3]; 1557 1558 cond[0] = (which_alternative < 2) ? operands[0] : operands[1]; 1559 cond[1] = operands[2]; 1560 cond[2] = operands[3]; 1561 1562 if (CONST_INT_P (cond[2]) && INTVAL (cond[2]) < 0) 1563 output_asm_insn (\"subs\\t%0, %1, #%n2\", cond); 1564 else 1565 output_asm_insn (\"adds\\t%0, %1, %2\", cond); 1566 1567 if (which_alternative >= 2 1568 && which_alternative < 4) 1569 output_asm_insn (\"mov\\t%0, %1\", operands); 1570 else if (which_alternative >= 4) 1571 output_asm_insn (\"str\\t%1, %0\", operands); 1572 1573 switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0)) 1574 { 1575 case 4: 1576 return \"b%d4\\t%l5\"; 1577 case 6: 1578 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\"; 1579 default: 1580 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\"; 1581 } 1582 } 1583 " 1584 [(set (attr "far_jump") 1585 (if_then_else 1586 (ior (and (lt (symbol_ref ("which_alternative")) 1587 (const_int 2)) 1588 (eq_attr "length" "8")) 1589 (eq_attr "length" "10")) 1590 (const_string "yes") 1591 (const_string "no"))) 1592 (set (attr "length") 1593 (if_then_else 1594 (lt (symbol_ref ("which_alternative")) 1595 (const_int 2)) 1596 (if_then_else 1597 (and (ge (minus (match_dup 5) (pc)) (const_int -250)) 1598 (le (minus (match_dup 5) (pc)) (const_int 256))) 1599 (const_int 4) 1600 (if_then_else 1601 (and (ge (minus (match_dup 5) (pc)) (const_int -2040)) 1602 (le (minus (match_dup 5) (pc)) (const_int 2048))) 1603 (const_int 6) 1604 (const_int 8))) 1605 (if_then_else 1606 (and (ge (minus (match_dup 5) (pc)) (const_int -248)) 1607 (le (minus (match_dup 5) (pc)) (const_int 256))) 1608 (const_int 6) 1609 (if_then_else 1610 (and (ge (minus (match_dup 5) (pc)) (const_int -2038)) 1611 (le (minus (match_dup 5) (pc)) (const_int 2048))) 1612 (const_int 8) 1613 (const_int 10))))) 1614 (set_attr "type" "multiple")] 1615 ) 1616 1617 (define_insn "*addsi3_cbranch_scratch" 1618 [(set (pc) 1619 (if_then_else 1620 (match_operator 3 "arm_comparison_operator" 1621 [(plus:SI 1622 (match_operand:SI 1 "s_register_operand" "%l,l,l,0") 1623 (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ")) 1624 (const_int 0)]) 1625 (label_ref (match_operand 4 "" "")) 1626 (pc))) 1627 (clobber (match_scratch:SI 0 "=X,X,l,l"))] 1628 "TARGET_THUMB1 1629 && (GET_CODE (operands[3]) == EQ 1630 || GET_CODE (operands[3]) == NE 1631 || GET_CODE (operands[3]) == GE 1632 || GET_CODE (operands[3]) == LT)" 1633 "* 1634 { 1635 switch (which_alternative) 1636 { 1637 case 0: 1638 output_asm_insn (\"cmp\t%1, #%n2\", operands); 1639 break; 1640 case 1: 1641 output_asm_insn (\"cmn\t%1, %2\", operands); 1642 break; 1643 case 2: 1644 if (INTVAL (operands[2]) < 0) 1645 output_asm_insn (\"subs\t%0, %1, %2\", operands); 1646 else 1647 output_asm_insn (\"adds\t%0, %1, %2\", operands); 1648 break; 1649 case 3: 1650 if (INTVAL (operands[2]) < 0) 1651 output_asm_insn (\"subs\t%0, %0, %2\", operands); 1652 else 1653 output_asm_insn (\"adds\t%0, %0, %2\", operands); 1654 break; 1655 } 1656 1657 switch (get_attr_length (insn)) 1658 { 1659 case 4: 1660 return \"b%d3\\t%l4\"; 1661 case 6: 1662 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\"; 1663 default: 1664 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\"; 1665 } 1666 } 1667 " 1668 [(set (attr "far_jump") 1669 (if_then_else 1670 (eq_attr "length" "8") 1671 (const_string "yes") 1672 (const_string "no"))) 1673 (set (attr "length") 1674 (if_then_else 1675 (and (ge (minus (match_dup 4) (pc)) (const_int -250)) 1676 (le (minus (match_dup 4) (pc)) (const_int 256))) 1677 (const_int 4) 1678 (if_then_else 1679 (and (ge (minus (match_dup 4) (pc)) (const_int -2040)) 1680 (le (minus (match_dup 4) (pc)) (const_int 2048))) 1681 (const_int 6) 1682 (const_int 8)))) 1683 (set_attr "type" "multiple")] 1684 ) 1685 1686 (define_insn "*thumb_cmpdi_zero" 1687 [(set (reg:CC_Z CC_REGNUM) 1688 (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l") 1689 (const_int 0))) 1690 (clobber (match_scratch:SI 1 "=l"))] 1691 "TARGET_THUMB1" 1692 "orrs\\t%1, %Q0, %R0" 1693 [(set_attr "conds" "set") 1694 (set_attr "length" "2") 1695 (set_attr "type" "logics_reg")] 1696 ) 1697 1698 (define_expand "cstoresi_eq0_thumb1" 1699 [(parallel 1700 [(set (match_operand:SI 0 "s_register_operand") 1701 (eq:SI (match_operand:SI 1 "s_register_operand") 1702 (const_int 0))) 1703 (clobber (match_dup:SI 2))])] 1704 "TARGET_THUMB1" 1705 "operands[2] = gen_reg_rtx (SImode);" 1706 ) 1707 1708 (define_expand "cstoresi_ne0_thumb1" 1709 [(parallel 1710 [(set (match_operand:SI 0 "s_register_operand") 1711 (ne:SI (match_operand:SI 1 "s_register_operand") 1712 (const_int 0))) 1713 (clobber (match_dup:SI 2))])] 1714 "TARGET_THUMB1" 1715 "operands[2] = gen_reg_rtx (SImode);" 1716 ) 1717 1718 (define_insn "*cstoresi_eq0_thumb1_insn" 1719 [(set (match_operand:SI 0 "s_register_operand" "=&l,l") 1720 (eq:SI (match_operand:SI 1 "s_register_operand" "l,0") 1721 (const_int 0))) 1722 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))] 1723 "TARGET_THUMB1" 1724 "@ 1725 rsbs\\t%0, %1, #0\;adcs\\t%0, %0, %1 1726 rsbs\\t%2, %1, #0\;adcs\\t%0, %1, %2" 1727 [(set_attr "length" "4") 1728 (set_attr "type" "multiple")] 1729 ) 1730 1731 (define_insn "*cstoresi_ne0_thumb1_insn" 1732 [(set (match_operand:SI 0 "s_register_operand" "=l") 1733 (ne:SI (match_operand:SI 1 "s_register_operand" "0") 1734 (const_int 0))) 1735 (clobber (match_operand:SI 2 "s_register_operand" "=l"))] 1736 "TARGET_THUMB1" 1737 "subs\\t%2, %1, #1\;sbcs\\t%0, %1, %2" 1738 [(set_attr "length" "4")] 1739 ) 1740 1741 ;; Used as part of the expansion of thumb ltu and gtu sequences 1742 (define_insn "cstoresi_nltu_thumb1" 1743 [(set (match_operand:SI 0 "s_register_operand" "=l,l") 1744 (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h") 1745 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))] 1746 "TARGET_THUMB1" 1747 "cmp\\t%1, %2\;sbcs\\t%0, %0, %0" 1748 [(set_attr "length" "4") 1749 (set_attr "type" "multiple")] 1750 ) 1751 1752 (define_insn_and_split "cstoresi_ltu_thumb1" 1753 [(set (match_operand:SI 0 "s_register_operand" "=l,l") 1754 (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h") 1755 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))] 1756 "TARGET_THUMB1" 1757 "#" 1758 "TARGET_THUMB1" 1759 [(set (match_dup 3) 1760 (neg:SI (ltu:SI (match_dup 1) (match_dup 2)))) 1761 (set (match_dup 0) (neg:SI (match_dup 3)))] 1762 "operands[3] = gen_reg_rtx (SImode);" 1763 [(set_attr "length" "4") 1764 (set_attr "type" "multiple")] 1765 ) 1766 1767 ;; Used as part of the expansion of thumb les sequence. 1768 (define_insn "thumb1_addsi3_addgeu" 1769 [(set (match_operand:SI 0 "s_register_operand" "=l") 1770 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0") 1771 (match_operand:SI 2 "s_register_operand" "l")) 1772 (geu:SI (match_operand:SI 3 "s_register_operand" "l") 1773 (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))] 1774 "TARGET_THUMB1" 1775 "cmp\\t%3, %4\;adcs\\t%0, %1, %2" 1776 [(set_attr "length" "4") 1777 (set_attr "type" "multiple")] 1778 ) 1779 1780 1782 (define_insn "*thumb_jump" 1783 [(set (pc) 1784 (label_ref (match_operand 0 "" "")))] 1785 "TARGET_THUMB1" 1786 "* 1787 if (get_attr_length (insn) == 2) 1788 return \"b\\t%l0\"; 1789 return \"bl\\t%l0\\t%@ far jump\"; 1790 " 1791 [(set (attr "far_jump") 1792 (if_then_else 1793 (eq_attr "length" "4") 1794 (const_string "yes") 1795 (const_string "no"))) 1796 (set (attr "length") 1797 (if_then_else 1798 (and (ge (minus (match_dup 0) (pc)) (const_int -2044)) 1799 (le (minus (match_dup 0) (pc)) (const_int 2048))) 1800 (const_int 2) 1801 (const_int 4))) 1802 (set_attr "type" "branch")] 1803 ) 1804 1805 (define_insn "*call_reg_thumb1_v5" 1806 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 1807 (match_operand 1 "" "")) 1808 (use (match_operand 2 "" "")) 1809 (clobber (reg:SI LR_REGNUM))] 1810 "TARGET_THUMB1 && arm_arch5t && !SIBLING_CALL_P (insn)" 1811 "blx\\t%0" 1812 [(set_attr "length" "2") 1813 (set_attr "type" "call")] 1814 ) 1815 1816 (define_insn "*nonsecure_call_reg_thumb1_v5" 1817 [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))] 1818 UNSPEC_NONSECURE_MEM) 1819 (match_operand 0 "" "")) 1820 (use (match_operand 1 "" "")) 1821 (clobber (reg:SI LR_REGNUM))] 1822 "TARGET_THUMB1 && use_cmse && !SIBLING_CALL_P (insn)" 1823 "bl\\t__gnu_cmse_nonsecure_call" 1824 [(set_attr "length" "4") 1825 (set_attr "type" "call")] 1826 ) 1827 1828 (define_insn "*call_reg_thumb1" 1829 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) 1830 (match_operand 1 "" "")) 1831 (use (match_operand 2 "" "")) 1832 (clobber (reg:SI LR_REGNUM))] 1833 "TARGET_THUMB1 && !arm_arch5t && !SIBLING_CALL_P (insn)" 1834 "* 1835 { 1836 if (!TARGET_CALLER_INTERWORKING) 1837 return thumb_call_via_reg (operands[0]); 1838 else if (operands[1] == const0_rtx) 1839 return \"bl\\t%__interwork_call_via_%0\"; 1840 else if (frame_pointer_needed) 1841 return \"bl\\t%__interwork_r7_call_via_%0\"; 1842 else 1843 return \"bl\\t%__interwork_r11_call_via_%0\"; 1844 }" 1845 [(set_attr "type" "call")] 1846 ) 1847 1848 (define_insn "*call_value_reg_thumb1_v5" 1849 [(set (match_operand 0 "" "") 1850 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 1851 (match_operand 2 "" ""))) 1852 (use (match_operand 3 "" "")) 1853 (clobber (reg:SI LR_REGNUM))] 1854 "TARGET_THUMB1 && arm_arch5t" 1855 "blx\\t%1" 1856 [(set_attr "length" "2") 1857 (set_attr "type" "call")] 1858 ) 1859 1860 (define_insn "*nonsecure_call_value_reg_thumb1_v5" 1861 [(set (match_operand 0 "" "") 1862 (call (unspec:SI 1863 [(mem:SI (reg:SI R4_REGNUM))] 1864 UNSPEC_NONSECURE_MEM) 1865 (match_operand 1 "" ""))) 1866 (use (match_operand 2 "" "")) 1867 (clobber (reg:SI LR_REGNUM))] 1868 "TARGET_THUMB1 && use_cmse" 1869 "bl\\t__gnu_cmse_nonsecure_call" 1870 [(set_attr "length" "4") 1871 (set_attr "type" "call")] 1872 ) 1873 1874 (define_insn "*call_value_reg_thumb1" 1875 [(set (match_operand 0 "" "") 1876 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 1877 (match_operand 2 "" ""))) 1878 (use (match_operand 3 "" "")) 1879 (clobber (reg:SI LR_REGNUM))] 1880 "TARGET_THUMB1 && !arm_arch5t" 1881 "* 1882 { 1883 if (!TARGET_CALLER_INTERWORKING) 1884 return thumb_call_via_reg (operands[1]); 1885 else if (operands[2] == const0_rtx) 1886 return \"bl\\t%__interwork_call_via_%1\"; 1887 else if (frame_pointer_needed) 1888 return \"bl\\t%__interwork_r7_call_via_%1\"; 1889 else 1890 return \"bl\\t%__interwork_r11_call_via_%1\"; 1891 }" 1892 [(set_attr "type" "call")] 1893 ) 1894 1895 (define_insn "*call_insn" 1896 [(call (mem:SI (match_operand:SI 0 "" "")) 1897 (match_operand:SI 1 "" "")) 1898 (use (match_operand 2 "" "")) 1899 (clobber (reg:SI LR_REGNUM))] 1900 "TARGET_THUMB1 1901 && GET_CODE (operands[0]) == SYMBOL_REF 1902 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))" 1903 "bl\\t%a0" 1904 [(set_attr "length" "4") 1905 (set_attr "type" "call")] 1906 ) 1907 1908 (define_insn "*call_value_insn" 1909 [(set (match_operand 0 "" "") 1910 (call (mem:SI (match_operand 1 "" "")) 1911 (match_operand 2 "" ""))) 1912 (use (match_operand 3 "" "")) 1913 (clobber (reg:SI LR_REGNUM))] 1914 "TARGET_THUMB1 1915 && GET_CODE (operands[1]) == SYMBOL_REF 1916 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))" 1917 "bl\\t%a1" 1918 [(set_attr "length" "4") 1919 (set_attr "type" "call")] 1920 ) 1921 1922 (define_expand "thumb1_casesi_internal_pic" 1923 [(match_operand:SI 0 "s_register_operand") 1924 (match_operand:SI 1 "thumb1_cmp_operand") 1925 (match_operand 2 "" "") 1926 (match_operand 3 "" "")] 1927 "TARGET_THUMB1" 1928 { 1929 rtx reg0; 1930 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]); 1931 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1], 1932 operands[3])); 1933 reg0 = gen_rtx_REG (SImode, 0); 1934 emit_move_insn (reg0, operands[0]); 1935 emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/)); 1936 DONE; 1937 } 1938 ) 1939 1940 (define_insn "thumb1_casesi_dispatch" 1941 [(parallel [(set (pc) (unspec [(reg:SI 0) 1942 (label_ref (match_operand 0 "" "")) 1943 ;; (label_ref (match_operand 1 "" "")) 1944 ] 1945 UNSPEC_THUMB1_CASESI)) 1946 (clobber (reg:SI IP_REGNUM)) 1947 (clobber (reg:SI LR_REGNUM))])] 1948 "TARGET_THUMB1" 1949 "* return thumb1_output_casesi(operands);" 1950 [(set_attr "length" "4") 1951 (set_attr "type" "multiple")] 1952 ) 1953 1954 ;; NB Never uses BX. 1955 (define_insn "*thumb1_indirect_jump" 1956 [(set (pc) 1957 (match_operand:SI 0 "register_operand" "l*r"))] 1958 "TARGET_THUMB1" 1959 "mov\\tpc, %0" 1960 [(set_attr "conds" "clob") 1961 (set_attr "length" "2") 1962 (set_attr "type" "branch")] 1963 ) 1964 1965 1967 (define_insn "prologue_thumb1_interwork" 1968 [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)] 1969 "TARGET_THUMB1" 1970 "* return thumb1_output_interwork ();" 1971 [(set_attr "length" "8") 1972 (set_attr "type" "multiple")] 1973 ) 1974 1975 (define_insn "*epilogue_insns" 1976 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)] 1977 "TARGET_THUMB1" 1978 "* 1979 return thumb1_unexpanded_epilogue (); 1980 " 1981 ; Length is absolute worst case, when using CMSE and if this is an entry 1982 ; function an extra 4 (MSR) bytes will be added. 1983 [(set (attr "length") 1984 (if_then_else 1985 (match_test "IS_CMSE_ENTRY (arm_current_func_type ())") 1986 (const_int 48) 1987 (const_int 44))) 1988 (set_attr "type" "block") 1989 ;; We don't clobber the conditions, but the potential length of this 1990 ;; operation is sufficient to make conditionalizing the sequence 1991 ;; unlikely to be profitable. 1992 (set_attr "conds" "clob")] 1993 ) 1994 1995 ;; Miscellaneous Thumb patterns 1996 (define_expand "tablejump" 1997 [(parallel [(set (pc) (match_operand:SI 0 "register_operand")) 1998 (use (label_ref (match_operand 1 "" "")))])] 1999 "TARGET_THUMB1" 2000 " 2001 if (flag_pic) 2002 { 2003 /* Hopefully, CSE will eliminate this copy. */ 2004 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); 2005 rtx reg2 = gen_reg_rtx (SImode); 2006 2007 emit_insn (gen_addsi3 (reg2, operands[0], reg1)); 2008 operands[0] = reg2; 2009 } 2010 " 2011 ) 2012 2013 (define_insn "*thumb1_movpc_insn" 2014 [(set (match_operand:SI 0 "s_register_operand" "=l") 2015 (reg:SI PC_REGNUM))] 2016 "TARGET_THUMB1" 2017 "mov\\t%0, pc" 2018 [(set_attr "length" "2") 2019 (set_attr "conds" "nocond") 2020 (set_attr "type" "mov_reg")] 2021 ) 2022 2023 ;; NB never uses BX. 2024 (define_insn "*thumb1_tablejump" 2025 [(set (pc) (match_operand:SI 0 "register_operand" "l*r")) 2026 (use (label_ref (match_operand 1 "" "")))] 2027 "TARGET_THUMB1" 2028 "mov\\t%|pc, %0" 2029 [(set_attr "length" "2") 2030 (set_attr "type" "branch")] 2031 ) 2032 2033 (define_insn_and_split "thumb_eh_return" 2034 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")] 2035 VUNSPEC_EH_RETURN) 2036 (clobber (match_scratch:SI 1 "=&l"))] 2037 "TARGET_THUMB1" 2038 "#" 2039 "&& reload_completed" 2040 [(const_int 0)] 2041 " 2042 { 2043 thumb_set_return_address (operands[0], operands[1]); 2044 DONE; 2045 }" 2046 [(set_attr "type" "mov_reg")] 2047 ) 2048 2049 ;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the 2050 ;; canary value does not live beyond the end of this sequence. 2051 (define_insn "thumb1_stack_protect_test_insn" 2052 [(set (match_operand:SI 0 "register_operand" "=&l") 2053 (unspec:SI [(match_operand:SI 1 "memory_operand" "m") 2054 (mem:SI (match_operand:SI 2 "register_operand" "+l"))] 2055 UNSPEC_SP_TEST)) 2056 (clobber (match_dup 2))] 2057 "TARGET_THUMB1" 2058 "ldr\t%0, [%2]\;ldr\t%2, %1\;eors\t%0, %2, %0\;movs\t%2, #0" 2059 [(set_attr "length" "10") 2060 (set_attr "conds" "clob") 2061 (set_attr "type" "multiple")] 2062 ) 2063 2065