Home | History | Annotate | Line # | Download | only in arm
      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