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