1;; ARM Thumb-2 Machine Description 2;; Copyright (C) 2007, 2008 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(define_insn "*thumb2_incscc" 28 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 29 (plus:SI (match_operator:SI 2 "arm_comparison_operator" 30 [(match_operand:CC 3 "cc_register" "") (const_int 0)]) 31 (match_operand:SI 1 "s_register_operand" "0,?r")))] 32 "TARGET_THUMB2" 33 "@ 34 it\\t%d2\;add%d2\\t%0, %1, #1 35 ite\\t%D2\;mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1" 36 [(set_attr "conds" "use") 37 (set_attr "length" "6,10")] 38) 39 40(define_insn "*thumb2_decscc" 41 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 42 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 43 (match_operator:SI 2 "arm_comparison_operator" 44 [(match_operand 3 "cc_register" "") (const_int 0)])))] 45 "TARGET_THUMB2" 46 "@ 47 it\\t%d2\;sub%d2\\t%0, %1, #1 48 ite\\t%D2\;mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1" 49 [(set_attr "conds" "use") 50 (set_attr "length" "6,10")] 51) 52 53;; Thumb-2 only allows shift by constant on data processing instructions 54(define_insn "*thumb_andsi_not_shiftsi_si" 55 [(set (match_operand:SI 0 "s_register_operand" "=r") 56 (and:SI (not:SI (match_operator:SI 4 "shift_operator" 57 [(match_operand:SI 2 "s_register_operand" "r") 58 (match_operand:SI 3 "const_int_operand" "M")])) 59 (match_operand:SI 1 "s_register_operand" "r")))] 60 "TARGET_THUMB2" 61 "bic%?\\t%0, %1, %2%S4" 62 [(set_attr "predicable" "yes") 63 (set_attr "shift" "2") 64 (set_attr "type" "alu_shift")] 65) 66 67(define_insn "*thumb2_smaxsi3" 68 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 69 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 70 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 71 (clobber (reg:CC CC_REGNUM))] 72 "TARGET_THUMB2" 73 "@ 74 cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2 75 cmp\\t%1, %2\;it\\tge\;movge\\t%0, %1 76 cmp\\t%1, %2\;ite\\tge\;movge\\t%0, %1\;movlt\\t%0, %2" 77 [(set_attr "conds" "clob") 78 (set_attr "length" "10,10,14")] 79) 80 81(define_insn "*thumb2_sminsi3" 82 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 83 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 84 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 85 (clobber (reg:CC CC_REGNUM))] 86 "TARGET_THUMB2" 87 "@ 88 cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2 89 cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %1 90 cmp\\t%1, %2\;ite\\tlt\;movlt\\t%0, %1\;movge\\t%0, %2" 91 [(set_attr "conds" "clob") 92 (set_attr "length" "10,10,14")] 93) 94 95(define_insn "*thumb32_umaxsi3" 96 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 97 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 98 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 99 (clobber (reg:CC CC_REGNUM))] 100 "TARGET_THUMB2" 101 "@ 102 cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2 103 cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %1 104 cmp\\t%1, %2\;ite\\tcs\;movcs\\t%0, %1\;movcc\\t%0, %2" 105 [(set_attr "conds" "clob") 106 (set_attr "length" "10,10,14")] 107) 108 109(define_insn "*thumb2_uminsi3" 110 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 111 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r") 112 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 113 (clobber (reg:CC CC_REGNUM))] 114 "TARGET_THUMB2" 115 "@ 116 cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2 117 cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %1 118 cmp\\t%1, %2\;ite\\tcc\;movcc\\t%0, %1\;movcs\\t%0, %2" 119 [(set_attr "conds" "clob") 120 (set_attr "length" "10,10,14")] 121) 122 123(define_insn "*thumb2_notsi_shiftsi" 124 [(set (match_operand:SI 0 "s_register_operand" "=r") 125 (not:SI (match_operator:SI 3 "shift_operator" 126 [(match_operand:SI 1 "s_register_operand" "r") 127 (match_operand:SI 2 "const_int_operand" "M")])))] 128 "TARGET_THUMB2" 129 "mvn%?\\t%0, %1%S3" 130 [(set_attr "predicable" "yes") 131 (set_attr "shift" "1") 132 (set_attr "type" "alu_shift")] 133) 134 135(define_insn "*thumb2_notsi_shiftsi_compare0" 136 [(set (reg:CC_NOOV CC_REGNUM) 137 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 138 [(match_operand:SI 1 "s_register_operand" "r") 139 (match_operand:SI 2 "const_int_operand" "M")])) 140 (const_int 0))) 141 (set (match_operand:SI 0 "s_register_operand" "=r") 142 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] 143 "TARGET_THUMB2" 144 "mvn%.\\t%0, %1%S3" 145 [(set_attr "conds" "set") 146 (set_attr "shift" "1") 147 (set_attr "type" "alu_shift")] 148) 149 150(define_insn "*thumb2_not_shiftsi_compare0_scratch" 151 [(set (reg:CC_NOOV CC_REGNUM) 152 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" 153 [(match_operand:SI 1 "s_register_operand" "r") 154 (match_operand:SI 2 "const_int_operand" "M")])) 155 (const_int 0))) 156 (clobber (match_scratch:SI 0 "=r"))] 157 "TARGET_THUMB2" 158 "mvn%.\\t%0, %1%S3" 159 [(set_attr "conds" "set") 160 (set_attr "shift" "1") 161 (set_attr "type" "alu_shift")] 162) 163 164;; Thumb-2 does not have rsc, so use a clever trick with shifter operands. 165(define_insn "*thumb2_negdi2" 166 [(set (match_operand:DI 0 "s_register_operand" "=&r,r") 167 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0"))) 168 (clobber (reg:CC CC_REGNUM))] 169 "TARGET_THUMB2" 170 "negs\\t%Q0, %Q1\;sbc\\t%R0, %R1, %R1, lsl #1" 171 [(set_attr "conds" "clob") 172 (set_attr "length" "8")] 173) 174 175(define_insn "*thumb2_abssi2" 176 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 177 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))) 178 (clobber (reg:CC CC_REGNUM))] 179 "TARGET_THUMB2" 180 "@ 181 cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0 182 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31" 183 [(set_attr "conds" "clob,*") 184 (set_attr "shift" "1") 185 ;; predicable can't be set based on the variant, so left as no 186 (set_attr "length" "10,8")] 187) 188 189(define_insn "*thumb2_neg_abssi2" 190 [(set (match_operand:SI 0 "s_register_operand" "=r,&r") 191 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))) 192 (clobber (reg:CC CC_REGNUM))] 193 "TARGET_THUMB2" 194 "@ 195 cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0 196 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31" 197 [(set_attr "conds" "clob,*") 198 (set_attr "shift" "1") 199 ;; predicable can't be set based on the variant, so left as no 200 (set_attr "length" "10,8")] 201) 202 203(define_insn "*thumb2_movdi" 204 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m") 205 (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))] 206 "TARGET_THUMB2 207 && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP)) 208 && !TARGET_IWMMXT" 209 "* 210 switch (which_alternative) 211 { 212 case 0: 213 case 1: 214 case 2: 215 return \"#\"; 216 default: 217 return output_move_double (operands); 218 } 219 " 220 [(set_attr "length" "8,12,16,8,8") 221 (set_attr "type" "*,*,*,load2,store2") 222 (set_attr "pool_range" "*,*,*,4096,*") 223 (set_attr "neg_pool_range" "*,*,*,0,*")] 224) 225 226(define_insn "*thumb2_movsi_insn" 227 [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m") 228 (match_operand:SI 1 "general_operand" "rk ,I,K,j,mi,rk"))] 229 "TARGET_THUMB2 && ! TARGET_IWMMXT 230 && !(TARGET_HARD_FLOAT && TARGET_VFP) 231 && ( register_operand (operands[0], SImode) 232 || register_operand (operands[1], SImode))" 233 "@ 234 mov%?\\t%0, %1 235 mov%?\\t%0, %1 236 mvn%?\\t%0, #%B1 237 movw%?\\t%0, %1 238 ldr%?\\t%0, %1 239 str%?\\t%1, %0" 240 [(set_attr "type" "*,*,*,*,load1,store1") 241 (set_attr "predicable" "yes") 242 (set_attr "pool_range" "*,*,*,*,4096,*") 243 (set_attr "neg_pool_range" "*,*,*,*,0,*")] 244) 245 246(define_insn "tls_load_dot_plus_four" 247 [(set (match_operand:SI 0 "register_operand" "=l,l,r,r") 248 (mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1") 249 (const_int 4) 250 (match_operand 3 "" "")] 251 UNSPEC_PIC_BASE))) 252 (clobber (match_scratch:SI 1 "=X,l,X,r"))] 253 "TARGET_THUMB2" 254 "* 255 (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\", 256 INTVAL (operands[3])); 257 return \"add\\t%2, %|pc\;ldr%?\\t%0, [%2]\"; 258 " 259 [(set_attr "length" "4,4,6,6")] 260) 261 262;; Thumb-2 always has load/store halfword instructions, so we can avoid a lot 263;; of the messiness associated with the ARM patterns. 264(define_insn "*thumb2_movhi_insn" 265 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") 266 (match_operand:HI 1 "general_operand" "rI,n,r,m"))] 267 "TARGET_THUMB2" 268 "@ 269 mov%?\\t%0, %1\\t%@ movhi 270 movw%?\\t%0, %L1\\t%@ movhi 271 str%(h%)\\t%1, %0\\t%@ movhi 272 ldr%(h%)\\t%0, %1\\t%@ movhi" 273 [(set_attr "type" "*,*,store1,load1") 274 (set_attr "predicable" "yes") 275 (set_attr "pool_range" "*,*,*,4096") 276 (set_attr "neg_pool_range" "*,*,*,250")] 277) 278 279(define_insn "*thumb2_movsf_soft_insn" 280 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m") 281 (match_operand:SF 1 "general_operand" "r,mE,r"))] 282 "TARGET_THUMB2 283 && TARGET_SOFT_FLOAT 284 && (GET_CODE (operands[0]) != MEM 285 || register_operand (operands[1], SFmode))" 286 "@ 287 mov%?\\t%0, %1 288 ldr%?\\t%0, %1\\t%@ float 289 str%?\\t%1, %0\\t%@ float" 290 [(set_attr "predicable" "yes") 291 (set_attr "type" "*,load1,store1") 292 (set_attr "pool_range" "*,4096,*") 293 (set_attr "neg_pool_range" "*,0,*")] 294) 295 296(define_insn "*thumb2_movdf_soft_insn" 297 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m") 298 (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))] 299 "TARGET_THUMB2 && TARGET_SOFT_FLOAT 300 && ( register_operand (operands[0], DFmode) 301 || register_operand (operands[1], DFmode))" 302 "* 303 switch (which_alternative) 304 { 305 case 0: 306 case 1: 307 case 2: 308 return \"#\"; 309 default: 310 return output_move_double (operands); 311 } 312 " 313 [(set_attr "length" "8,12,16,8,8") 314 (set_attr "type" "*,*,*,load2,store2") 315 (set_attr "pool_range" "1020") 316 (set_attr "neg_pool_range" "0")] 317) 318 319(define_insn "*thumb2_cmpsi_shiftsi" 320 [(set (reg:CC CC_REGNUM) 321 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 322 (match_operator:SI 3 "shift_operator" 323 [(match_operand:SI 1 "s_register_operand" "r") 324 (match_operand:SI 2 "const_int_operand" "M")])))] 325 "TARGET_THUMB2" 326 "cmp%?\\t%0, %1%S3" 327 [(set_attr "conds" "set") 328 (set_attr "shift" "1") 329 (set_attr "type" "alu_shift")] 330) 331 332(define_insn "*thumb2_cmpsi_shiftsi_swp" 333 [(set (reg:CC_SWP CC_REGNUM) 334 (compare:CC_SWP (match_operator:SI 3 "shift_operator" 335 [(match_operand:SI 1 "s_register_operand" "r") 336 (match_operand:SI 2 "const_int_operand" "M")]) 337 (match_operand:SI 0 "s_register_operand" "r")))] 338 "TARGET_THUMB2" 339 "cmp%?\\t%0, %1%S3" 340 [(set_attr "conds" "set") 341 (set_attr "shift" "1") 342 (set_attr "type" "alu_shift")] 343) 344 345(define_insn "*thumb2_cmpsi_neg_shiftsi" 346 [(set (reg:CC CC_REGNUM) 347 (compare:CC (match_operand:SI 0 "s_register_operand" "r") 348 (neg:SI (match_operator:SI 3 "shift_operator" 349 [(match_operand:SI 1 "s_register_operand" "r") 350 (match_operand:SI 2 "const_int_operand" "M")]))))] 351 "TARGET_THUMB2" 352 "cmn%?\\t%0, %1%S3" 353 [(set_attr "conds" "set") 354 (set_attr "shift" "1") 355 (set_attr "type" "alu_shift")] 356) 357 358(define_insn "*thumb2_mov_scc" 359 [(set (match_operand:SI 0 "s_register_operand" "=r") 360 (match_operator:SI 1 "arm_comparison_operator" 361 [(match_operand 2 "cc_register" "") (const_int 0)]))] 362 "TARGET_THUMB2" 363 "ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1" 364 [(set_attr "conds" "use") 365 (set_attr "length" "10")] 366) 367 368(define_insn "*thumb2_mov_negscc" 369 [(set (match_operand:SI 0 "s_register_operand" "=r") 370 (neg:SI (match_operator:SI 1 "arm_comparison_operator" 371 [(match_operand 2 "cc_register" "") (const_int 0)])))] 372 "TARGET_THUMB2" 373 "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0" 374 [(set_attr "conds" "use") 375 (set_attr "length" "10")] 376) 377 378(define_insn "*thumb2_mov_notscc" 379 [(set (match_operand:SI 0 "s_register_operand" "=r") 380 (not:SI (match_operator:SI 1 "arm_comparison_operator" 381 [(match_operand 2 "cc_register" "") (const_int 0)])))] 382 "TARGET_THUMB2" 383 "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1" 384 [(set_attr "conds" "use") 385 (set_attr "length" "10")] 386) 387 388(define_insn "*thumb2_movsicc_insn" 389 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r") 390 (if_then_else:SI 391 (match_operator 3 "arm_comparison_operator" 392 [(match_operand 4 "cc_register" "") (const_int 0)]) 393 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K") 394 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))] 395 "TARGET_THUMB2" 396 "@ 397 it\\t%D3\;mov%D3\\t%0, %2 398 it\\t%D3\;mvn%D3\\t%0, #%B2 399 it\\t%d3\;mov%d3\\t%0, %1 400 it\\t%d3\;mvn%d3\\t%0, #%B1 401 ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2 402 ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2 403 ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2 404 ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2" 405 [(set_attr "length" "6,6,6,6,10,10,10,10") 406 (set_attr "conds" "use")] 407) 408 409(define_insn "*thumb2_movsfcc_soft_insn" 410 [(set (match_operand:SF 0 "s_register_operand" "=r,r") 411 (if_then_else:SF (match_operator 3 "arm_comparison_operator" 412 [(match_operand 4 "cc_register" "") (const_int 0)]) 413 (match_operand:SF 1 "s_register_operand" "0,r") 414 (match_operand:SF 2 "s_register_operand" "r,0")))] 415 "TARGET_THUMB2 && TARGET_SOFT_FLOAT" 416 "@ 417 it\\t%D3\;mov%D3\\t%0, %2 418 it\\t%d3\;mov%d3\\t%0, %1" 419 [(set_attr "length" "6,6") 420 (set_attr "conds" "use")] 421) 422 423(define_insn "*call_reg_thumb2" 424 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) 425 (match_operand 1 "" "")) 426 (use (match_operand 2 "" "")) 427 (clobber (reg:SI LR_REGNUM))] 428 "TARGET_THUMB2" 429 "blx%?\\t%0" 430 [(set_attr "type" "call")] 431) 432 433(define_insn "*call_value_reg_thumb2" 434 [(set (match_operand 0 "" "") 435 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r")) 436 (match_operand 2 "" ""))) 437 (use (match_operand 3 "" "")) 438 (clobber (reg:SI LR_REGNUM))] 439 "TARGET_THUMB2" 440 "blx\\t%1" 441 [(set_attr "type" "call")] 442) 443 444(define_insn "*thumb2_indirect_jump" 445 [(set (pc) 446 (match_operand:SI 0 "register_operand" "l*r"))] 447 "TARGET_THUMB2" 448 "bx\\t%0" 449 [(set_attr "conds" "clob")] 450) 451;; Don't define thumb2_load_indirect_jump because we can't guarantee label 452;; addresses will have the thumb bit set correctly. 453 454 455;; Patterns to allow combination of arithmetic, cond code and shifts 456 457(define_insn "*thumb2_arith_shiftsi" 458 [(set (match_operand:SI 0 "s_register_operand" "=r") 459 (match_operator:SI 1 "shiftable_operator" 460 [(match_operator:SI 3 "shift_operator" 461 [(match_operand:SI 4 "s_register_operand" "r") 462 (match_operand:SI 5 "const_int_operand" "M")]) 463 (match_operand:SI 2 "s_register_operand" "r")]))] 464 "TARGET_THUMB2" 465 "%i1%?\\t%0, %2, %4%S3" 466 [(set_attr "predicable" "yes") 467 (set_attr "shift" "4") 468 (set_attr "type" "alu_shift")] 469) 470 471;; ??? What does this splitter do? Copied from the ARM version 472(define_split 473 [(set (match_operand:SI 0 "s_register_operand" "") 474 (match_operator:SI 1 "shiftable_operator" 475 [(match_operator:SI 2 "shiftable_operator" 476 [(match_operator:SI 3 "shift_operator" 477 [(match_operand:SI 4 "s_register_operand" "") 478 (match_operand:SI 5 "const_int_operand" "")]) 479 (match_operand:SI 6 "s_register_operand" "")]) 480 (match_operand:SI 7 "arm_rhs_operand" "")])) 481 (clobber (match_operand:SI 8 "s_register_operand" ""))] 482 "TARGET_32BIT" 483 [(set (match_dup 8) 484 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 485 (match_dup 6)])) 486 (set (match_dup 0) 487 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))] 488 "") 489 490(define_insn "*thumb2_arith_shiftsi_compare0" 491 [(set (reg:CC_NOOV CC_REGNUM) 492 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 493 [(match_operator:SI 3 "shift_operator" 494 [(match_operand:SI 4 "s_register_operand" "r") 495 (match_operand:SI 5 "const_int_operand" "M")]) 496 (match_operand:SI 2 "s_register_operand" "r")]) 497 (const_int 0))) 498 (set (match_operand:SI 0 "s_register_operand" "=r") 499 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) 500 (match_dup 2)]))] 501 "TARGET_32BIT" 502 "%i1%.\\t%0, %2, %4%S3" 503 [(set_attr "conds" "set") 504 (set_attr "shift" "4") 505 (set_attr "type" "alu_shift")] 506) 507 508(define_insn "*thumb2_arith_shiftsi_compare0_scratch" 509 [(set (reg:CC_NOOV CC_REGNUM) 510 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" 511 [(match_operator:SI 3 "shift_operator" 512 [(match_operand:SI 4 "s_register_operand" "r") 513 (match_operand:SI 5 "const_int_operand" "M")]) 514 (match_operand:SI 2 "s_register_operand" "r")]) 515 (const_int 0))) 516 (clobber (match_scratch:SI 0 "=r"))] 517 "TARGET_THUMB2" 518 "%i1%.\\t%0, %2, %4%S3" 519 [(set_attr "conds" "set") 520 (set_attr "shift" "4") 521 (set_attr "type" "alu_shift")] 522) 523 524(define_insn "*thumb2_sub_shiftsi" 525 [(set (match_operand:SI 0 "s_register_operand" "=r") 526 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 527 (match_operator:SI 2 "shift_operator" 528 [(match_operand:SI 3 "s_register_operand" "r") 529 (match_operand:SI 4 "const_int_operand" "M")])))] 530 "TARGET_THUMB2" 531 "sub%?\\t%0, %1, %3%S2" 532 [(set_attr "predicable" "yes") 533 (set_attr "shift" "3") 534 (set_attr "type" "alu_shift")] 535) 536 537(define_insn "*thumb2_sub_shiftsi_compare0" 538 [(set (reg:CC_NOOV CC_REGNUM) 539 (compare:CC_NOOV 540 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 541 (match_operator:SI 2 "shift_operator" 542 [(match_operand:SI 3 "s_register_operand" "r") 543 (match_operand:SI 4 "const_int_operand" "M")])) 544 (const_int 0))) 545 (set (match_operand:SI 0 "s_register_operand" "=r") 546 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) 547 (match_dup 4)])))] 548 "TARGET_THUMB2" 549 "sub%.\\t%0, %1, %3%S2" 550 [(set_attr "conds" "set") 551 (set_attr "shift" "3") 552 (set_attr "type" "alu_shift")] 553) 554 555(define_insn "*thumb2_sub_shiftsi_compare0_scratch" 556 [(set (reg:CC_NOOV CC_REGNUM) 557 (compare:CC_NOOV 558 (minus:SI (match_operand:SI 1 "s_register_operand" "r") 559 (match_operator:SI 2 "shift_operator" 560 [(match_operand:SI 3 "s_register_operand" "r") 561 (match_operand:SI 4 "const_int_operand" "M")])) 562 (const_int 0))) 563 (clobber (match_scratch:SI 0 "=r"))] 564 "TARGET_THUMB2" 565 "sub%.\\t%0, %1, %3%S2" 566 [(set_attr "conds" "set") 567 (set_attr "shift" "3") 568 (set_attr "type" "alu_shift")] 569) 570 571(define_insn "*thumb2_and_scc" 572 [(set (match_operand:SI 0 "s_register_operand" "=r") 573 (and:SI (match_operator:SI 1 "arm_comparison_operator" 574 [(match_operand 3 "cc_register" "") (const_int 0)]) 575 (match_operand:SI 2 "s_register_operand" "r")))] 576 "TARGET_THUMB2" 577 "ite\\t%D1\;mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1" 578 [(set_attr "conds" "use") 579 (set_attr "length" "10")] 580) 581 582(define_insn "*thumb2_ior_scc" 583 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 584 (ior:SI (match_operator:SI 2 "arm_comparison_operator" 585 [(match_operand 3 "cc_register" "") (const_int 0)]) 586 (match_operand:SI 1 "s_register_operand" "0,?r")))] 587 "TARGET_THUMB2" 588 "@ 589 it\\t%d2\;orr%d2\\t%0, %1, #1 590 ite\\t%D2\;mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1" 591 [(set_attr "conds" "use") 592 (set_attr "length" "6,10")] 593) 594 595(define_insn "*thumb2_compare_scc" 596 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 597 (match_operator:SI 1 "arm_comparison_operator" 598 [(match_operand:SI 2 "s_register_operand" "r,r") 599 (match_operand:SI 3 "arm_add_operand" "rI,L")])) 600 (clobber (reg:CC CC_REGNUM))] 601 "TARGET_THUMB2" 602 "* 603 if (operands[3] == const0_rtx) 604 { 605 if (GET_CODE (operands[1]) == LT) 606 return \"lsr\\t%0, %2, #31\"; 607 608 if (GET_CODE (operands[1]) == GE) 609 return \"mvn\\t%0, %2\;lsr\\t%0, %0, #31\"; 610 611 if (GET_CODE (operands[1]) == EQ) 612 return \"rsbs\\t%0, %2, #1\;it\\tcc\;movcc\\t%0, #0\"; 613 } 614 615 if (GET_CODE (operands[1]) == NE) 616 { 617 if (which_alternative == 1) 618 return \"adds\\t%0, %2, #%n3\;it\\tne\;movne\\t%0, #1\"; 619 return \"subs\\t%0, %2, %3\;it\\tne\;movne\\t%0, #1\"; 620 } 621 if (which_alternative == 1) 622 output_asm_insn (\"cmn\\t%2, #%n3\", operands); 623 else 624 output_asm_insn (\"cmp\\t%2, %3\", operands); 625 return \"ite\\t%D1\;mov%D1\\t%0, #0\;mov%d1\\t%0, #1\"; 626 " 627 [(set_attr "conds" "clob") 628 (set_attr "length" "14")] 629) 630 631(define_insn "*thumb2_cond_move" 632 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 633 (if_then_else:SI (match_operator 3 "equality_operator" 634 [(match_operator 4 "arm_comparison_operator" 635 [(match_operand 5 "cc_register" "") (const_int 0)]) 636 (const_int 0)]) 637 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 638 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))] 639 "TARGET_THUMB2" 640 "* 641 if (GET_CODE (operands[3]) == NE) 642 { 643 if (which_alternative != 1) 644 output_asm_insn (\"it\\t%D4\;mov%D4\\t%0, %2\", operands); 645 if (which_alternative != 0) 646 output_asm_insn (\"it\\t%d4\;mov%d4\\t%0, %1\", operands); 647 return \"\"; 648 } 649 switch (which_alternative) 650 { 651 case 0: 652 output_asm_insn (\"it\\t%d4\", operands); 653 break; 654 case 1: 655 output_asm_insn (\"it\\t%D4\", operands); 656 break; 657 case 2: 658 output_asm_insn (\"ite\\t%D4\", operands); 659 break; 660 default: 661 abort(); 662 } 663 if (which_alternative != 0) 664 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 665 if (which_alternative != 1) 666 output_asm_insn (\"mov%d4\\t%0, %2\", operands); 667 return \"\"; 668 " 669 [(set_attr "conds" "use") 670 (set_attr "length" "6,6,10")] 671) 672 673(define_insn "*thumb2_cond_arith" 674 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 675 (match_operator:SI 5 "shiftable_operator" 676 [(match_operator:SI 4 "arm_comparison_operator" 677 [(match_operand:SI 2 "s_register_operand" "r,r") 678 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]) 679 (match_operand:SI 1 "s_register_operand" "0,?r")])) 680 (clobber (reg:CC CC_REGNUM))] 681 "TARGET_THUMB2" 682 "* 683 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx) 684 return \"%i5\\t%0, %1, %2, lsr #31\"; 685 686 output_asm_insn (\"cmp\\t%2, %3\", operands); 687 if (GET_CODE (operands[5]) == AND) 688 { 689 output_asm_insn (\"ite\\t%D4\", operands); 690 output_asm_insn (\"mov%D4\\t%0, #0\", operands); 691 } 692 else if (GET_CODE (operands[5]) == MINUS) 693 { 694 output_asm_insn (\"ite\\t%D4\", operands); 695 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands); 696 } 697 else if (which_alternative != 0) 698 { 699 output_asm_insn (\"ite\\t%D4\", operands); 700 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 701 } 702 else 703 output_asm_insn (\"it\\t%d4\", operands); 704 return \"%i5%d4\\t%0, %1, #1\"; 705 " 706 [(set_attr "conds" "clob") 707 (set_attr "length" "14")] 708) 709 710(define_insn "*thumb2_cond_sub" 711 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 712 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r") 713 (match_operator:SI 4 "arm_comparison_operator" 714 [(match_operand:SI 2 "s_register_operand" "r,r") 715 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")]))) 716 (clobber (reg:CC CC_REGNUM))] 717 "TARGET_THUMB2" 718 "* 719 output_asm_insn (\"cmp\\t%2, %3\", operands); 720 if (which_alternative != 0) 721 { 722 output_asm_insn (\"ite\\t%D4\", operands); 723 output_asm_insn (\"mov%D4\\t%0, %1\", operands); 724 } 725 else 726 output_asm_insn (\"it\\t%d4\", operands); 727 return \"sub%d4\\t%0, %1, #1\"; 728 " 729 [(set_attr "conds" "clob") 730 (set_attr "length" "10,14")] 731) 732 733(define_insn "*thumb2_negscc" 734 [(set (match_operand:SI 0 "s_register_operand" "=r") 735 (neg:SI (match_operator 3 "arm_comparison_operator" 736 [(match_operand:SI 1 "s_register_operand" "r") 737 (match_operand:SI 2 "arm_rhs_operand" "rI")]))) 738 (clobber (reg:CC CC_REGNUM))] 739 "TARGET_THUMB2" 740 "* 741 if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx) 742 return \"asr\\t%0, %1, #31\"; 743 744 if (GET_CODE (operands[3]) == NE) 745 return \"subs\\t%0, %1, %2\;it\\tne\;mvnne\\t%0, #0\"; 746 747 output_asm_insn (\"cmp\\t%1, %2\", operands); 748 output_asm_insn (\"ite\\t%D3\", operands); 749 output_asm_insn (\"mov%D3\\t%0, #0\", operands); 750 return \"mvn%d3\\t%0, #0\"; 751 " 752 [(set_attr "conds" "clob") 753 (set_attr "length" "14")] 754) 755 756(define_insn "*thumb2_movcond" 757 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 758 (if_then_else:SI 759 (match_operator 5 "arm_comparison_operator" 760 [(match_operand:SI 3 "s_register_operand" "r,r,r") 761 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")]) 762 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI") 763 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))) 764 (clobber (reg:CC CC_REGNUM))] 765 "TARGET_THUMB2" 766 "* 767 if (GET_CODE (operands[5]) == LT 768 && (operands[4] == const0_rtx)) 769 { 770 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 771 { 772 if (operands[2] == const0_rtx) 773 return \"and\\t%0, %1, %3, asr #31\"; 774 return \"ands\\t%0, %1, %3, asr #32\;it\\tcc\;movcc\\t%0, %2\"; 775 } 776 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 777 { 778 if (operands[1] == const0_rtx) 779 return \"bic\\t%0, %2, %3, asr #31\"; 780 return \"bics\\t%0, %2, %3, asr #32\;it\\tcs\;movcs\\t%0, %1\"; 781 } 782 /* The only case that falls through to here is when both ops 1 & 2 783 are constants. */ 784 } 785 786 if (GET_CODE (operands[5]) == GE 787 && (operands[4] == const0_rtx)) 788 { 789 if (which_alternative != 1 && GET_CODE (operands[1]) == REG) 790 { 791 if (operands[2] == const0_rtx) 792 return \"bic\\t%0, %1, %3, asr #31\"; 793 return \"bics\\t%0, %1, %3, asr #32\;it\\tcs\;movcs\\t%0, %2\"; 794 } 795 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG) 796 { 797 if (operands[1] == const0_rtx) 798 return \"and\\t%0, %2, %3, asr #31\"; 799 return \"ands\\t%0, %2, %3, asr #32\;it\tcc\;movcc\\t%0, %1\"; 800 } 801 /* The only case that falls through to here is when both ops 1 & 2 802 are constants. */ 803 } 804 if (GET_CODE (operands[4]) == CONST_INT 805 && !const_ok_for_arm (INTVAL (operands[4]))) 806 output_asm_insn (\"cmn\\t%3, #%n4\", operands); 807 else 808 output_asm_insn (\"cmp\\t%3, %4\", operands); 809 switch (which_alternative) 810 { 811 case 0: 812 output_asm_insn (\"it\\t%D5\", operands); 813 break; 814 case 1: 815 output_asm_insn (\"it\\t%d5\", operands); 816 break; 817 case 2: 818 output_asm_insn (\"ite\\t%d5\", operands); 819 break; 820 default: 821 abort(); 822 } 823 if (which_alternative != 0) 824 output_asm_insn (\"mov%d5\\t%0, %1\", operands); 825 if (which_alternative != 1) 826 output_asm_insn (\"mov%D5\\t%0, %2\", operands); 827 return \"\"; 828 " 829 [(set_attr "conds" "clob") 830 (set_attr "length" "10,10,14")] 831) 832 833;; Zero and sign extension instructions. 834 835(define_insn_and_split "*thumb2_zero_extendsidi2" 836 [(set (match_operand:DI 0 "s_register_operand" "=r") 837 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 838 "TARGET_THUMB2" 839 "mov%?\\t%Q0, %1\;mov%?\\t%R0, #0" 840 "&& reload_completed" 841 [(set (match_dup 0) (match_dup 1))] 842 " 843 { 844 rtx lo_part = gen_lowpart (SImode, operands[0]); 845 if (!REG_P (lo_part) || REGNO (lo_part) != REGNO (operands[1])) 846 emit_move_insn (lo_part, operands[1]); 847 operands[0] = gen_highpart (SImode, operands[0]); 848 operands[1] = const0_rtx; 849 } 850 " 851 [(set_attr "length" "8") 852 (set_attr "ce_count" "2") 853 (set_attr "predicable" "yes")] 854) 855 856(define_insn_and_split "*thumb2_zero_extendhidi2" 857 [(set (match_operand:DI 0 "s_register_operand" "=r,r") 858 (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] 859 "TARGET_THUMB2" 860 "@ 861 uxth%?\\t%Q0, %1\;mov%?\\t%R0, #0 862 ldr%(h%)\\t%Q0, %1\;mov%?\\t%R0, #0" 863 "&& reload_completed" 864 [(set (match_dup 0) (zero_extend:SI (match_dup 1))) 865 (set (match_dup 2) (match_dup 3))] 866 " 867 { 868 operands[2] = gen_highpart (SImode, operands[0]); 869 operands[0] = gen_lowpart (SImode, operands[0]); 870 operands[3] = const0_rtx; 871 } 872 " 873 [(set_attr "length" "8") 874 (set_attr "ce_count" "2") 875 (set_attr "predicable" "yes") 876 (set_attr "type" "*,load_byte") 877 (set_attr "pool_range" "*,4092") 878 (set_attr "neg_pool_range" "*,250")] 879) 880 881(define_insn_and_split "*thumb2_zero_extendqidi2" 882 [(set (match_operand:DI 0 "s_register_operand" "=r,r") 883 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 884 "TARGET_THUMB2" 885 "@ 886 uxtb%?\\t%Q0, %1\;mov%?\\t%R0, #0 887 ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0" 888 "&& reload_completed" 889 [(set (match_dup 0) (zero_extend:SI (match_dup 1))) 890 (set (match_dup 2) (match_dup 3))] 891 " 892 { 893 operands[2] = gen_highpart (SImode, operands[0]); 894 operands[0] = gen_lowpart (SImode, operands[0]); 895 operands[3] = const0_rtx; 896 } 897 " 898 [(set_attr "length" "8") 899 (set_attr "ce_count" "2") 900 (set_attr "predicable" "yes") 901 (set_attr "type" "*,load_byte") 902 (set_attr "pool_range" "*,4092") 903 (set_attr "neg_pool_range" "*,250")] 904) 905 906(define_insn_and_split "*thumb2_extendsidi2" 907 [(set (match_operand:DI 0 "s_register_operand" "=r") 908 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))] 909 "TARGET_THUMB2" 910 "mov%?\\t%Q0, %1\;asr?\\t%R0, %1, #31" 911 "&& reload_completed" 912 [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))] 913 { 914 rtx lo_part = gen_lowpart (SImode, operands[0]); 915 916 if (!REG_P (lo_part) || REGNO (lo_part) != REGNO (operands[1])) 917 emit_move_insn (lo_part, operands[1]); 918 operands[0] = gen_highpart (SImode, operands[0]); 919 } 920 [(set_attr "length" "8") 921 (set_attr "ce_count" "2") 922 (set_attr "shift" "1") 923 (set_attr "predicable" "yes")] 924) 925 926(define_insn_and_split "*thumb2_extendhidi2" 927 [(set (match_operand:DI 0 "s_register_operand" "=r,r") 928 (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] 929 "TARGET_THUMB2" 930 "@ 931 sxth%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31 932 ldrsh%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31" 933 "&& reload_completed" 934 [(set (match_dup 0) (sign_extend:SI (match_dup 1))) 935 (set (match_dup 2) (ashiftrt:SI (match_dup 0) (const_int 31)))] 936 " 937 { 938 operands[2] = gen_highpart (SImode, operands[0]); 939 operands[0] = gen_lowpart (SImode, operands[0]); 940 } 941 " 942 [(set_attr "length" "8") 943 (set_attr "ce_count" "2") 944 (set_attr "predicable" "yes") 945 (set_attr "type" "*,load_byte") 946 (set_attr "pool_range" "*,4092") 947 (set_attr "neg_pool_range" "*,250")] 948) 949 950(define_insn_and_split "*thumb2_extendqidi2" 951 [(set (match_operand:DI 0 "s_register_operand" "=r,r") 952 (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 953 "TARGET_THUMB2" 954 "@ 955 sxtb%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31 956 ldrsb%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31" 957 "&& reload_completed" 958 [(set (match_dup 0) (sign_extend:SI (match_dup 1))) 959 (set (match_dup 2) (ashiftrt:SI (match_dup 0) (const_int 31)))] 960 " 961 { 962 operands[2] = gen_highpart (SImode, operands[0]); 963 operands[0] = gen_lowpart (SImode, operands[0]); 964 } 965 " 966 [(set_attr "length" "8") 967 (set_attr "ce_count" "2") 968 (set_attr "predicable" "yes") 969 (set_attr "type" "*,load_byte") 970 (set_attr "pool_range" "*,4092") 971 (set_attr "neg_pool_range" "*,250")] 972) 973 974;; All supported Thumb2 implementations are armv6, so only that case is 975;; provided. 976(define_insn "*thumb2_extendqisi_v6" 977 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 978 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 979 "TARGET_THUMB2 && arm_arch6" 980 "@ 981 sxtb%?\\t%0, %1 982 ldr%(sb%)\\t%0, %1" 983 [(set_attr "type" "alu_shift,load_byte") 984 (set_attr "predicable" "yes") 985 (set_attr "pool_range" "*,4096") 986 (set_attr "neg_pool_range" "*,250")] 987) 988 989(define_insn "*thumb2_zero_extendhisi2_v6" 990 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 991 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] 992 "TARGET_THUMB2 && arm_arch6" 993 "@ 994 uxth%?\\t%0, %1 995 ldr%(h%)\\t%0, %1" 996 [(set_attr "type" "alu_shift,load_byte") 997 (set_attr "predicable" "yes") 998 (set_attr "pool_range" "*,4096") 999 (set_attr "neg_pool_range" "*,250")] 1000) 1001 1002(define_insn "*thumb2_zero_extendqisi2_v6" 1003 [(set (match_operand:SI 0 "s_register_operand" "=r,r") 1004 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] 1005 "TARGET_THUMB2 && arm_arch6" 1006 "@ 1007 uxtb%(%)\\t%0, %1 1008 ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2" 1009 [(set_attr "type" "alu_shift,load_byte") 1010 (set_attr "predicable" "yes") 1011 (set_attr "pool_range" "*,4096") 1012 (set_attr "neg_pool_range" "*,250")] 1013) 1014 1015(define_insn "thumb2_casesi_internal" 1016 [(parallel [(set (pc) 1017 (if_then_else 1018 (leu (match_operand:SI 0 "s_register_operand" "r") 1019 (match_operand:SI 1 "arm_rhs_operand" "rI")) 1020 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 1021 (label_ref (match_operand 2 "" "")))) 1022 (label_ref (match_operand 3 "" "")))) 1023 (clobber (reg:CC CC_REGNUM)) 1024 (clobber (match_scratch:SI 4 "=&r")) 1025 (use (label_ref (match_dup 2)))])] 1026 "TARGET_THUMB2 && !flag_pic" 1027 "* return thumb2_output_casesi(operands);" 1028 [(set_attr "conds" "clob") 1029 (set_attr "length" "16")] 1030) 1031 1032(define_insn "thumb2_casesi_internal_pic" 1033 [(parallel [(set (pc) 1034 (if_then_else 1035 (leu (match_operand:SI 0 "s_register_operand" "r") 1036 (match_operand:SI 1 "arm_rhs_operand" "rI")) 1037 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4)) 1038 (label_ref (match_operand 2 "" "")))) 1039 (label_ref (match_operand 3 "" "")))) 1040 (clobber (reg:CC CC_REGNUM)) 1041 (clobber (match_scratch:SI 4 "=&r")) 1042 (clobber (match_scratch:SI 5 "=r")) 1043 (use (label_ref (match_dup 2)))])] 1044 "TARGET_THUMB2 && flag_pic" 1045 "* return thumb2_output_casesi(operands);" 1046 [(set_attr "conds" "clob") 1047 (set_attr "length" "20")] 1048) 1049 1050(define_insn_and_split "thumb2_eh_return" 1051 [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")] 1052 VUNSPEC_EH_RETURN) 1053 (clobber (match_scratch:SI 1 "=&r"))] 1054 "TARGET_THUMB2" 1055 "#" 1056 "&& reload_completed" 1057 [(const_int 0)] 1058 " 1059 { 1060 thumb_set_return_address (operands[0], operands[1]); 1061 DONE; 1062 }" 1063) 1064 1065;; Peepholes and insns for 16-bit flag clobbering instructions. 1066;; The conditional forms of these instructions do not clobber CC. 1067;; However by the time peepholes are run it is probably too late to do 1068;; anything useful with this information. 1069(define_peephole2 1070 [(set (match_operand:SI 0 "low_register_operand" "") 1071 (match_operator:SI 3 "thumb_16bit_operator" 1072 [(match_operand:SI 1 "low_register_operand" "") 1073 (match_operand:SI 2 "low_register_operand" "")]))] 1074 "TARGET_THUMB2 1075 && (rtx_equal_p(operands[0], operands[1]) 1076 || GET_CODE(operands[3]) == PLUS 1077 || GET_CODE(operands[3]) == MINUS) 1078 && peep2_regno_dead_p(0, CC_REGNUM)" 1079 [(parallel 1080 [(set (match_dup 0) 1081 (match_op_dup 3 1082 [(match_dup 1) 1083 (match_dup 2)])) 1084 (clobber (reg:CC CC_REGNUM))])] 1085 "" 1086) 1087 1088(define_insn "*thumb2_alusi3_short" 1089 [(set (match_operand:SI 0 "s_register_operand" "=l") 1090 (match_operator:SI 3 "thumb_16bit_operator" 1091 [(match_operand:SI 1 "s_register_operand" "0") 1092 (match_operand:SI 2 "s_register_operand" "l")])) 1093 (clobber (reg:CC CC_REGNUM))] 1094 "TARGET_THUMB2 && reload_completed 1095 && GET_CODE(operands[3]) != PLUS 1096 && GET_CODE(operands[3]) != MINUS" 1097 "%I3%!\\t%0, %1, %2" 1098 [(set_attr "predicable" "yes") 1099 (set_attr "length" "2")] 1100) 1101 1102;; Similarly for 16-bit shift instructions 1103;; There is no 16-bit rotate by immediate instruction. 1104(define_peephole2 1105 [(set (match_operand:SI 0 "low_register_operand" "") 1106 (match_operator:SI 3 "shift_operator" 1107 [(match_operand:SI 1 "low_register_operand" "") 1108 (match_operand:SI 2 "low_reg_or_int_operand" "")]))] 1109 "TARGET_THUMB2 1110 && peep2_regno_dead_p(0, CC_REGNUM) 1111 && (CONST_INT_P (operands[2]) || operands[1] == operands[0]) 1112 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) 1113 || REG_P(operands[2]))" 1114 [(parallel 1115 [(set (match_dup 0) 1116 (match_op_dup 3 1117 [(match_dup 1) 1118 (match_dup 2)])) 1119 (clobber (reg:CC CC_REGNUM))])] 1120 "" 1121) 1122 1123(define_insn "*thumb2_shiftsi3_short" 1124 [(set (match_operand:SI 0 "low_register_operand" "=l,l") 1125 (match_operator:SI 3 "shift_operator" 1126 [(match_operand:SI 1 "low_register_operand" "0,l") 1127 (match_operand:SI 2 "low_reg_or_int_operand" "l,M")])) 1128 (clobber (reg:CC CC_REGNUM))] 1129 "TARGET_THUMB2 && reload_completed 1130 && ((GET_CODE(operands[3]) != ROTATE && GET_CODE(operands[3]) != ROTATERT) 1131 || REG_P(operands[2]))" 1132 "* return arm_output_shift(operands, 2);" 1133 [(set_attr "predicable" "yes") 1134 (set_attr "shift" "1") 1135 (set_attr "length" "2") 1136 (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") 1137 (const_string "alu_shift") 1138 (const_string "alu_shift_reg")))] 1139) 1140 1141;; 16-bit load immediate 1142(define_peephole2 1143 [(set (match_operand:QHSI 0 "low_register_operand" "") 1144 (match_operand:QHSI 1 "const_int_operand" ""))] 1145 "TARGET_THUMB2 1146 && peep2_regno_dead_p(0, CC_REGNUM) 1147 && (unsigned HOST_WIDE_INT) INTVAL(operands[1]) < 256" 1148 [(parallel 1149 [(set (match_dup 0) 1150 (match_dup 1)) 1151 (clobber (reg:CC CC_REGNUM))])] 1152 "" 1153) 1154 1155(define_insn "*thumb2_mov<mode>_shortim" 1156 [(set (match_operand:QHSI 0 "low_register_operand" "=l") 1157 (match_operand:QHSI 1 "const_int_operand" "I")) 1158 (clobber (reg:CC CC_REGNUM))] 1159 "TARGET_THUMB2 && reload_completed" 1160 "mov%!\t%0, %1" 1161 [(set_attr "predicable" "yes") 1162 (set_attr "length" "2")] 1163) 1164 1165;; 16-bit add/sub immediate 1166(define_peephole2 1167 [(set (match_operand:SI 0 "low_register_operand" "") 1168 (plus:SI (match_operand:SI 1 "low_register_operand" "") 1169 (match_operand:SI 2 "const_int_operand" "")))] 1170 "TARGET_THUMB2 1171 && peep2_regno_dead_p(0, CC_REGNUM) 1172 && ((rtx_equal_p(operands[0], operands[1]) 1173 && INTVAL(operands[2]) > -256 && INTVAL(operands[2]) < 256) 1174 || (INTVAL(operands[2]) > -8 && INTVAL(operands[2]) < 8))" 1175 [(parallel 1176 [(set (match_dup 0) 1177 (plus:SI (match_dup 1) 1178 (match_dup 2))) 1179 (clobber (reg:CC CC_REGNUM))])] 1180 "" 1181) 1182 1183(define_insn "*thumb2_addsi_short" 1184 [(set (match_operand:SI 0 "low_register_operand" "=l,l") 1185 (plus:SI (match_operand:SI 1 "low_register_operand" "l,0") 1186 (match_operand:SI 2 "low_reg_or_int_operand" "lPt,Ps"))) 1187 (clobber (reg:CC CC_REGNUM))] 1188 "TARGET_THUMB2 && reload_completed" 1189 "* 1190 HOST_WIDE_INT val; 1191 1192 if (GET_CODE (operands[2]) == CONST_INT) 1193 val = INTVAL(operands[2]); 1194 else 1195 val = 0; 1196 1197 /* We prefer eg. subs rn, rn, #1 over adds rn, rn, #0xffffffff. */ 1198 if (val < 0 && const_ok_for_arm(ARM_SIGN_EXTEND (-val))) 1199 return \"sub%!\\t%0, %1, #%n2\"; 1200 else 1201 return \"add%!\\t%0, %1, %2\"; 1202 " 1203 [(set_attr "predicable" "yes") 1204 (set_attr "length" "2")] 1205) 1206 1207(define_insn "divsi3" 1208 [(set (match_operand:SI 0 "s_register_operand" "=r") 1209 (div:SI (match_operand:SI 1 "s_register_operand" "r") 1210 (match_operand:SI 2 "s_register_operand" "r")))] 1211 "(TARGET_THUMB2 || TARGET_ARM) && arm_arch_hwdiv" 1212 "sdiv%?\t%0, %1, %2" 1213 [(set_attr "predicable" "yes") 1214 (set_attr "insn" "sdiv")] 1215) 1216 1217(define_insn "udivsi3" 1218 [(set (match_operand:SI 0 "s_register_operand" "=r") 1219 (udiv:SI (match_operand:SI 1 "s_register_operand" "r") 1220 (match_operand:SI 2 "s_register_operand" "r")))] 1221 "(TARGET_THUMB2 || TARGET_ARM) && arm_arch_hwdiv" 1222 "udiv%?\t%0, %1, %2" 1223 [(set_attr "predicable" "yes") 1224 (set_attr "insn" "udiv")] 1225) 1226 1227(define_insn "*thumb2_subsi_short" 1228 [(set (match_operand:SI 0 "low_register_operand" "=l") 1229 (minus:SI (match_operand:SI 1 "low_register_operand" "l") 1230 (match_operand:SI 2 "low_register_operand" "l"))) 1231 (clobber (reg:CC CC_REGNUM))] 1232 "TARGET_THUMB2 && reload_completed" 1233 "sub%!\\t%0, %1, %2" 1234 [(set_attr "predicable" "yes") 1235 (set_attr "length" "2")] 1236) 1237 1238;; 16-bit encodings of "muls" and "mul<c>". We only use these when 1239;; optimizing for size since "muls" is slow on all known 1240;; implementations and since "mul<c>" will be generated by 1241;; "*arm_mulsi3_v6" anyhow. The assembler will use a 16-bit encoding 1242;; for "mul<c>" whenever possible anyhow. 1243(define_peephole2 1244 [(set (match_operand:SI 0 "low_register_operand" "") 1245 (mult:SI (match_operand:SI 1 "low_register_operand" "") 1246 (match_dup 0)))] 1247 "TARGET_THUMB2 && optimize_size && peep2_regno_dead_p (0, CC_REGNUM)" 1248 [(parallel 1249 [(set (match_dup 0) 1250 (mult:SI (match_dup 0) (match_dup 1))) 1251 (clobber (reg:CC CC_REGNUM))])] 1252 "" 1253) 1254 1255(define_peephole2 1256 [(set (match_operand:SI 0 "low_register_operand" "") 1257 (mult:SI (match_dup 0) 1258 (match_operand:SI 1 "low_register_operand" "")))] 1259 "TARGET_THUMB2 && optimize_size && peep2_regno_dead_p (0, CC_REGNUM)" 1260 [(parallel 1261 [(set (match_dup 0) 1262 (mult:SI (match_dup 0) (match_dup 1))) 1263 (clobber (reg:CC CC_REGNUM))])] 1264 "" 1265) 1266 1267(define_insn "*thumb2_mulsi_short" 1268 [(set (match_operand:SI 0 "low_register_operand" "=l") 1269 (mult:SI (match_operand:SI 1 "low_register_operand" "%0") 1270 (match_operand:SI 2 "low_register_operand" "l"))) 1271 (clobber (reg:CC CC_REGNUM))] 1272 "TARGET_THUMB2 && optimize_size && reload_completed" 1273 "mul%!\\t%0, %2, %0" 1274 [(set_attr "predicable" "yes") 1275 (set_attr "length" "2") 1276 (set_attr "insn" "muls")]) 1277 1278(define_insn "*thumb2_mulsi_short_compare0" 1279 [(set (reg:CC_NOOV CC_REGNUM) 1280 (compare:CC_NOOV 1281 (mult:SI (match_operand:SI 1 "register_operand" "%0") 1282 (match_operand:SI 2 "register_operand" "l")) 1283 (const_int 0))) 1284 (set (match_operand:SI 0 "register_operand" "=l") 1285 (mult:SI (match_dup 1) (match_dup 2)))] 1286 "TARGET_THUMB2 && optimize_size" 1287 "muls\\t%0, %2, %0" 1288 [(set_attr "length" "2") 1289 (set_attr "insn" "muls")]) 1290 1291(define_insn "*thumb2_mulsi_short_compare0_scratch" 1292 [(set (reg:CC_NOOV CC_REGNUM) 1293 (compare:CC_NOOV 1294 (mult:SI (match_operand:SI 1 "register_operand" "%0") 1295 (match_operand:SI 2 "register_operand" "l")) 1296 (const_int 0))) 1297 (clobber (match_scratch:SI 0 "=l"))] 1298 "TARGET_THUMB2 && optimize_size" 1299 "muls\\t%0, %2, %0" 1300 [(set_attr "length" "2") 1301 (set_attr "insn" "muls")]) 1302 1303(define_insn "*thumb2_cbz" 1304 [(set (pc) (if_then_else 1305 (eq (match_operand:SI 0 "s_register_operand" "l,?r") 1306 (const_int 0)) 1307 (label_ref (match_operand 1 "" "")) 1308 (pc))) 1309 (clobber (reg:CC CC_REGNUM))] 1310 "TARGET_THUMB2" 1311 "* 1312 if (get_attr_length (insn) == 2) 1313 return \"cbz\\t%0, %l1\"; 1314 else 1315 return \"cmp\\t%0, #0\;beq\\t%l1\"; 1316 " 1317 [(set (attr "length") 1318 (if_then_else 1319 (and (ge (minus (match_dup 1) (pc)) (const_int 2)) 1320 (le (minus (match_dup 1) (pc)) (const_int 128)) 1321 (eq (symbol_ref ("which_alternative")) (const_int 0))) 1322 (const_int 2) 1323 (const_int 8)))] 1324) 1325 1326(define_insn "*thumb2_cbnz" 1327 [(set (pc) (if_then_else 1328 (ne (match_operand:SI 0 "s_register_operand" "l,?r") 1329 (const_int 0)) 1330 (label_ref (match_operand 1 "" "")) 1331 (pc))) 1332 (clobber (reg:CC CC_REGNUM))] 1333 "TARGET_THUMB2" 1334 "* 1335 if (get_attr_length (insn) == 2) 1336 return \"cbnz\\t%0, %l1\"; 1337 else 1338 return \"cmp\\t%0, #0\;bne\\t%l1\"; 1339 " 1340 [(set (attr "length") 1341 (if_then_else 1342 (and (ge (minus (match_dup 1) (pc)) (const_int 2)) 1343 (le (minus (match_dup 1) (pc)) (const_int 128)) 1344 (eq (symbol_ref ("which_alternative")) (const_int 0))) 1345 (const_int 2) 1346 (const_int 8)))] 1347) 1348 1349;; 16-bit complement 1350(define_peephole2 1351 [(set (match_operand:SI 0 "low_register_operand" "") 1352 (not:SI (match_operand:SI 1 "low_register_operand" "")))] 1353 "TARGET_THUMB2 1354 && peep2_regno_dead_p(0, CC_REGNUM)" 1355 [(parallel 1356 [(set (match_dup 0) 1357 (not:SI (match_dup 1))) 1358 (clobber (reg:CC CC_REGNUM))])] 1359 "" 1360) 1361 1362(define_insn "*thumb2_one_cmplsi2_short" 1363 [(set (match_operand:SI 0 "low_register_operand" "=l") 1364 (not:SI (match_operand:SI 1 "low_register_operand" "l"))) 1365 (clobber (reg:CC CC_REGNUM))] 1366 "TARGET_THUMB2 && reload_completed" 1367 "mvn%!\t%0, %1" 1368 [(set_attr "predicable" "yes") 1369 (set_attr "length" "2")] 1370) 1371 1372;; 16-bit negate 1373(define_peephole2 1374 [(set (match_operand:SI 0 "low_register_operand" "") 1375 (neg:SI (match_operand:SI 1 "low_register_operand" "")))] 1376 "TARGET_THUMB2 1377 && peep2_regno_dead_p(0, CC_REGNUM)" 1378 [(parallel 1379 [(set (match_dup 0) 1380 (neg:SI (match_dup 1))) 1381 (clobber (reg:CC CC_REGNUM))])] 1382 "" 1383) 1384 1385(define_insn "*thumb2_negsi2_short" 1386 [(set (match_operand:SI 0 "low_register_operand" "=l") 1387 (neg:SI (match_operand:SI 1 "low_register_operand" "l"))) 1388 (clobber (reg:CC CC_REGNUM))] 1389 "TARGET_THUMB2 && reload_completed" 1390 "neg%!\t%0, %1" 1391 [(set_attr "predicable" "yes") 1392 (set_attr "length" "2")] 1393) 1394 1395(define_insn "orsi_notsi_si" 1396 [(set (match_operand:SI 0 "s_register_operand" "=r") 1397 (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) 1398 (match_operand:SI 1 "s_register_operand" "r")))] 1399 "TARGET_THUMB2" 1400 "orn%?\\t%0, %1, %2" 1401 [(set_attr "predicable" "yes")] 1402) 1403 1404(define_insn "*thumb_orsi_not_shiftsi_si" 1405 [(set (match_operand:SI 0 "s_register_operand" "=r") 1406 (ior:SI (not:SI (match_operator:SI 4 "shift_operator" 1407 [(match_operand:SI 2 "s_register_operand" "r") 1408 (match_operand:SI 3 "const_int_operand" "M")])) 1409 (match_operand:SI 1 "s_register_operand" "r")))] 1410 "TARGET_THUMB2" 1411 "orn%?\\t%0, %1, %2%S4" 1412 [(set_attr "predicable" "yes") 1413 (set_attr "shift" "2") 1414 (set_attr "type" "alu_shift")] 1415) 1416 1417(define_insn_and_split "*thumb2_iorsi3" 1418 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") 1419 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,r") 1420 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] 1421 "TARGET_THUMB2" 1422 "@ 1423 orr%?\\t%0, %1, %2 1424 orn%?\\t%0, %1, #%B2 1425 #" 1426 "TARGET_THUMB2 1427 && GET_CODE (operands[2]) == CONST_INT 1428 && !(const_ok_for_arm (INTVAL (operands[2])) 1429 || const_ok_for_arm (~INTVAL (operands[2])))" 1430 [(clobber (const_int 0))] 1431 " 1432 arm_split_constant (IOR, SImode, curr_insn, 1433 INTVAL (operands[2]), operands[0], operands[1], 0); 1434 DONE; 1435 " 1436 [(set_attr "length" "4,4,16") 1437 (set_attr "predicable" "yes")] 1438) 1439