2014-08-07 Marat Zakirov <m.zakirov@samsung.com>
[official-gcc.git] / gcc / config / arm / thumb1.md
blob65d55ddbdcc1beb2f81485423fc2e81a0fb7a4d7
1 ;; ARM Thumb-1 Machine Description
2 ;; Copyright (C) 2007-2014 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 (define_insn "*thumb1_adddi3"
26   [(set (match_operand:DI          0 "register_operand" "=l")
27         (plus:DI (match_operand:DI 1 "register_operand" "%0")
28                  (match_operand:DI 2 "register_operand" "l")))
29    (clobber (reg:CC CC_REGNUM))
30   ]
31   "TARGET_THUMB1"
32   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
33   [(set_attr "length" "4")
34    (set_attr "type" "multiple")]
37 (define_insn_and_split "*thumb1_addsi3"
38   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
39         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
40                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
41   "TARGET_THUMB1"
42   "*
43    static const char * const asms[] =
44    {
45      \"add\\t%0, %0, %2\",
46      \"sub\\t%0, %0, #%n2\",
47      \"add\\t%0, %1, %2\",
48      \"add\\t%0, %0, %2\",
49      \"add\\t%0, %0, %2\",
50      \"add\\t%0, %1, %2\",
51      \"add\\t%0, %1, %2\",
52      \"#\",
53      \"#\",
54      \"#\"
55    };
56    if ((which_alternative == 2 || which_alternative == 6)
57        && CONST_INT_P (operands[2])
58        && INTVAL (operands[2]) < 0)
59      return \"sub\\t%0, %1, #%n2\";
60    return asms[which_alternative];
61   "
62   "&& reload_completed && CONST_INT_P (operands[2])
63    && ((operands[1] != stack_pointer_rtx
64         && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
65        || (operands[1] == stack_pointer_rtx
66            && INTVAL (operands[2]) > 1020))"
67   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
68    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
69   {
70     HOST_WIDE_INT offset = INTVAL (operands[2]);
71     if (operands[1] == stack_pointer_rtx)
72       offset -= 1020;
73     else
74       {
75         if (offset > 255)
76           offset = 255;
77         else if (offset < -255)
78           offset = -255;
79       }
80     operands[3] = GEN_INT (offset);
81     operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
82   }
83   [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")
84    (set_attr "type" "alus_imm,alus_imm,alus_sreg,alus_sreg,alus_sreg,
85                      alus_sreg,alus_sreg,multiple,multiple,multiple")]
88 ;; Reloading and elimination of the frame pointer can
89 ;; sometimes cause this optimization to be missed.
90 (define_peephole2
91   [(set (match_operand:SI 0 "arm_general_register_operand" "")
92         (match_operand:SI 1 "const_int_operand" ""))
93    (set (match_dup 0)
94         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
95   "TARGET_THUMB1
96    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
97    && (INTVAL (operands[1]) & 3) == 0"
98   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
99   ""
102 (define_insn "*thumb_subdi3"
103   [(set (match_operand:DI           0 "register_operand" "=l")
104         (minus:DI (match_operand:DI 1 "register_operand"  "0")
105                   (match_operand:DI 2 "register_operand"  "l")))
106    (clobber (reg:CC CC_REGNUM))]
107   "TARGET_THUMB1"
108   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
109   [(set_attr "length" "4")
110    (set_attr "type" "multiple")]
113 (define_insn "thumb1_subsi3_insn"
114   [(set (match_operand:SI           0 "register_operand" "=l")
115         (minus:SI (match_operand:SI 1 "register_operand" "l")
116                   (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
117   "TARGET_THUMB1"
118   "sub\\t%0, %1, %2"
119   [(set_attr "length" "2")
120    (set_attr "conds" "set")
121    (set_attr "type" "alus_sreg")]
124 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
125 ; 1 and 2; are the same, because reload will make operand 0 match
126 ; operand 1 without realizing that this conflicts with operand 2.  We fix
127 ; this by adding another alternative to match this case, and then `reload'
128 ; it ourselves.  This alternative must come first.
129 (define_insn "*thumb_mulsi3"
130   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
131         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
132                  (match_operand:SI 2 "register_operand" "l,l,l")))]
133  "TARGET_THUMB1 && !arm_arch6"
134   "*
135   if (which_alternative < 2)
136     return \"mov\\t%0, %1\;mul\\t%0, %2\";
137   else
138     return \"mul\\t%0, %2\";
139   "
140   [(set_attr "length" "4,4,2")
141    (set_attr "type" "muls")]
144 (define_insn "*thumb_mulsi3_v6"
145   [(set (match_operand:SI          0 "register_operand" "=l,l,l")
146         (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
147                  (match_operand:SI 2 "register_operand" "l,0,0")))]
148   "TARGET_THUMB1 && arm_arch6"
149   "@
150    mul\\t%0, %2
151    mul\\t%0, %1
152    mul\\t%0, %1"
153   [(set_attr "length" "2")
154    (set_attr "type" "muls")]
157 (define_insn "*thumb1_andsi3_insn"
158   [(set (match_operand:SI         0 "register_operand" "=l")
159         (and:SI (match_operand:SI 1 "register_operand" "%0")
160                 (match_operand:SI 2 "register_operand" "l")))]
161   "TARGET_THUMB1"
162   "and\\t%0, %2"
163   [(set_attr "length" "2")
164    (set_attr "type"  "logic_imm")
165    (set_attr "conds" "set")])
167 (define_split
168   [(set (match_operand:SI 0 "s_register_operand" "")
169         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
170                          (match_operand:SI 2 "const_int_operand" "")
171                          (match_operand:SI 3 "const_int_operand" "")))
172    (clobber (match_operand:SI 4 "s_register_operand" ""))]
173   "TARGET_THUMB1"
174   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
175    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
176   "{
177      HOST_WIDE_INT temp = INTVAL (operands[2]);
179      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
180      operands[3] = GEN_INT (32 - temp);
181    }"
184 (define_split
185   [(set (match_operand:SI 0 "s_register_operand" "")
186         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
187                          (match_operand:SI 2 "const_int_operand" "")
188                          (match_operand:SI 3 "const_int_operand" "")))]
189   "TARGET_THUMB1"
190   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
191    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
192   "{
193      HOST_WIDE_INT temp = INTVAL (operands[2]);
195      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
196      operands[3] = GEN_INT (32 - temp);
197    }"
200 (define_insn "thumb1_bicsi3"
201   [(set (match_operand:SI                 0 "register_operand" "=l")
202         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
203                 (match_operand:SI         2 "register_operand" "0")))]
204   "TARGET_THUMB1"
205   "bic\\t%0, %1"
206   [(set_attr "length" "2")
207    (set_attr "conds" "set")
208    (set_attr "type" "logics_reg")]
211 (define_insn "*thumb1_iorsi3_insn"
212   [(set (match_operand:SI         0 "register_operand" "=l")
213         (ior:SI (match_operand:SI 1 "register_operand" "%0")
214                 (match_operand:SI 2 "register_operand" "l")))]
215   "TARGET_THUMB1"
216   "orr\\t%0, %2"
217   [(set_attr "length" "2")
218    (set_attr "conds" "set")
219    (set_attr "type" "logics_reg")])
221 (define_insn "*thumb1_xorsi3_insn"
222   [(set (match_operand:SI         0 "register_operand" "=l")
223         (xor:SI (match_operand:SI 1 "register_operand" "%0")
224                 (match_operand:SI 2 "register_operand" "l")))]
225   "TARGET_THUMB1"
226   "eor\\t%0, %2"
227   [(set_attr "length" "2")
228    (set_attr "conds" "set")
229    (set_attr "type" "logics_reg")]
232 (define_insn "*thumb1_ashlsi3"
233   [(set (match_operand:SI            0 "register_operand" "=l,l")
234         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
235                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
236   "TARGET_THUMB1"
237   "lsl\\t%0, %1, %2"
238   [(set_attr "length" "2")
239    (set_attr "type" "shift_imm,shift_reg")
240    (set_attr "conds" "set")])
242 (define_insn "*thumb1_ashrsi3"
243   [(set (match_operand:SI              0 "register_operand" "=l,l")
244         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
245                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
246   "TARGET_THUMB1"
247   "asr\\t%0, %1, %2"
248   [(set_attr "length" "2")
249    (set_attr "type" "shift_imm,shift_reg")
250    (set_attr "conds" "set")])
252 (define_insn "*thumb1_lshrsi3"
253   [(set (match_operand:SI              0 "register_operand" "=l,l")
254         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
255                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
256   "TARGET_THUMB1"
257   "lsr\\t%0, %1, %2"
258   [(set_attr "length" "2")
259    (set_attr "type" "shift_imm,shift_reg")
260    (set_attr "conds" "set")])
262 (define_insn "*thumb1_rotrsi3"
263   [(set (match_operand:SI              0 "register_operand" "=l")
264         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
265                      (match_operand:SI 2 "register_operand" "l")))]
266   "TARGET_THUMB1"
267   "ror\\t%0, %0, %2"
268   [(set_attr "type" "shift_reg")
269    (set_attr "length" "2")]
272 (define_insn "*thumb1_negdi2"
273   [(set (match_operand:DI 0 "register_operand" "=&l")
274         (neg:DI (match_operand:DI 1 "register_operand" "l")))
275    (clobber (reg:CC CC_REGNUM))]
276   "TARGET_THUMB1"
277   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
278   [(set_attr "length" "6")
279    (set_attr "type" "multiple")]
282 (define_insn "*thumb1_negsi2"
283   [(set (match_operand:SI         0 "register_operand" "=l")
284         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
285   "TARGET_THUMB1"
286   "neg\\t%0, %1"
287   [(set_attr "length" "2")
288    (set_attr "type" "alu_imm")]
291 (define_insn_and_split "*thumb1_abssi2"
292   [(set (match_operand:SI 0 "s_register_operand" "=l")
293         (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
294    (clobber (match_scratch:SI 2 "=&l"))]
295   "TARGET_THUMB1"
296   "#"
297   "TARGET_THUMB1 && reload_completed"
298   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
299    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
300    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
301   ""
302   [(set_attr "length" "6")
303    (set_attr "type" "multiple")]
306 (define_insn_and_split "*thumb1_neg_abssi2"
307   [(set (match_operand:SI 0 "s_register_operand" "=l")
308         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
309    (clobber (match_scratch:SI 2 "=&l"))]
310   "TARGET_THUMB1"
311   "#"
312   "TARGET_THUMB1 && reload_completed"
313   [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
314    (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
315    (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
316   ""
317   [(set_attr "length" "6")
318    (set_attr "type" "multiple")]
321 (define_insn "*thumb1_one_cmplsi2"
322   [(set (match_operand:SI         0 "register_operand" "=l")
323         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
324   "TARGET_THUMB1"
325   "mvn\\t%0, %1"
326   [(set_attr "length" "2")
327    (set_attr "type" "mvn_reg")]
330 (define_insn "*thumb1_zero_extendhisi2"
331   [(set (match_operand:SI 0 "register_operand" "=l,l")
332         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
333   "TARGET_THUMB1"
335   rtx mem;
337   if (which_alternative == 0 && arm_arch6)
338     return "uxth\t%0, %1";
339   if (which_alternative == 0)
340     return "#";
342   mem = XEXP (operands[1], 0);
344   if (GET_CODE (mem) == CONST)
345     mem = XEXP (mem, 0);
347   if (GET_CODE (mem) == PLUS)
348     {
349       rtx a = XEXP (mem, 0);
351       /* This can happen due to bugs in reload.  */
352       if (REG_P (a) && REGNO (a) == SP_REGNUM)
353         {
354           rtx ops[2];
355           ops[0] = operands[0];
356           ops[1] = a;
358           output_asm_insn ("mov\t%0, %1", ops);
360           XEXP (mem, 0) = operands[0];
361        }
362     }
364   return "ldrh\t%0, %1";
366   [(set_attr_alternative "length"
367                          [(if_then_else (eq_attr "is_arch6" "yes")
368                                        (const_int 2) (const_int 4))
369                          (const_int 4)])
370    (set_attr "type" "extend,load_byte")]
373 (define_insn "*thumb1_zero_extendqisi2"
374   [(set (match_operand:SI 0 "register_operand" "=l,l")
375         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
376   "TARGET_THUMB1 && !arm_arch6"
377   "@
378    #
379    ldrb\\t%0, %1"
380   [(set_attr "length" "4,2")
381    (set_attr "type" "alu_shift_reg,load_byte")
382    (set_attr "pool_range" "*,32")]
385 (define_insn "*thumb1_zero_extendqisi2_v6"
386   [(set (match_operand:SI 0 "register_operand" "=l,l")
387         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
388   "TARGET_THUMB1 && arm_arch6"
389   "@
390    uxtb\\t%0, %1
391    ldrb\\t%0, %1"
392   [(set_attr "length" "2")
393    (set_attr "type" "extend,load_byte")]
396 ;; We used to have an early-clobber on the scratch register here.
397 ;; However, there's a bug somewhere in reload which means that this
398 ;; can be partially ignored during spill allocation if the memory
399 ;; address also needs reloading; this causes us to die later on when
400 ;; we try to verify the operands.  Fortunately, we don't really need
401 ;; the early-clobber: we can always use operand 0 if operand 2
402 ;; overlaps the address.
403 (define_insn "thumb1_extendhisi2"
404   [(set (match_operand:SI 0 "register_operand" "=l,l")
405         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
406    (clobber (match_scratch:SI 2 "=X,l"))]
407   "TARGET_THUMB1"
408   "*
409   {
410     rtx ops[4];
411     rtx mem;
413     if (which_alternative == 0 && !arm_arch6)
414       return \"#\";
415     if (which_alternative == 0)
416       return \"sxth\\t%0, %1\";
418     mem = XEXP (operands[1], 0);
420     /* This code used to try to use 'V', and fix the address only if it was
421        offsettable, but this fails for e.g. REG+48 because 48 is outside the
422        range of QImode offsets, and offsettable_address_p does a QImode
423        address check.  */
425     if (GET_CODE (mem) == CONST)
426       mem = XEXP (mem, 0);
428     if (GET_CODE (mem) == LABEL_REF)
429       return \"ldr\\t%0, %1\";
431     if (GET_CODE (mem) == PLUS)
432       {
433         rtx a = XEXP (mem, 0);
434         rtx b = XEXP (mem, 1);
436         if (GET_CODE (a) == LABEL_REF
437             && CONST_INT_P (b))
438           return \"ldr\\t%0, %1\";
440         if (REG_P (b))
441           return \"ldrsh\\t%0, %1\";
443         ops[1] = a;
444         ops[2] = b;
445       }
446     else
447       {
448         ops[1] = mem;
449         ops[2] = const0_rtx;
450       }
452     gcc_assert (REG_P (ops[1]));
454     ops[0] = operands[0];
455     if (reg_mentioned_p (operands[2], ops[1]))
456       ops[3] = ops[0];
457     else
458       ops[3] = operands[2];
459     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
460     return \"\";
461   }"
462   [(set_attr_alternative "length"
463                          [(if_then_else (eq_attr "is_arch6" "yes")
464                                         (const_int 2) (const_int 4))
465                           (const_int 4)])
466    (set_attr "type" "extend,load_byte")
467    (set_attr "pool_range" "*,1018")]
470 (define_split
471   [(set (match_operand:SI 0 "register_operand" "")
472         (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
473   "TARGET_THUMB1 && reload_completed"
474   [(set (match_dup 0) (match_dup 2))
475    (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
477   rtx addr = XEXP (operands[1], 0);
479   if (GET_CODE (addr) == CONST)
480     addr = XEXP (addr, 0);
482   if (GET_CODE (addr) == PLUS
483       && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
484     /* No split necessary.  */
485     FAIL;
487   if (GET_CODE (addr) == PLUS
488       && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
489     FAIL;
491   if (reg_overlap_mentioned_p (operands[0], addr))
492     {
493       rtx t = gen_lowpart (QImode, operands[0]);
494       emit_move_insn (t, operands[1]);
495       emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
496       DONE;
497     }
499   if (REG_P (addr))
500     {
501       addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
502       operands[2] = const0_rtx;
503     }
504   else if (GET_CODE (addr) != PLUS)
505     FAIL;
506   else if (REG_P (XEXP (addr, 0)))
507     {
508       operands[2] = XEXP (addr, 1);
509       addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
510     }
511   else
512     {
513       operands[2] = XEXP (addr, 0);
514       addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
515     }
517   operands[3] = change_address (operands[1], QImode, addr);
520 (define_peephole2
521   [(set (match_operand:SI 0 "register_operand" "")
522         (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
523    (set (match_operand:SI 2 "register_operand" "") (const_int 0))
524    (set (match_operand:SI 3 "register_operand" "")
525         (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
526   "TARGET_THUMB1
527    && GET_CODE (XEXP (operands[4], 0)) == PLUS
528    && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
529    && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
530    && (peep2_reg_dead_p (3, operands[0])
531        || rtx_equal_p (operands[0], operands[3]))
532    && (peep2_reg_dead_p (3, operands[2])
533        || rtx_equal_p (operands[2], operands[3]))"
534   [(set (match_dup 2) (match_dup 1))
535    (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
537   rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
538   operands[4] = change_address (operands[4], QImode, addr);
541 (define_insn "thumb1_extendqisi2"
542   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
543         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
544   "TARGET_THUMB1"
546   rtx addr;
548   if (which_alternative == 0 && arm_arch6)
549     return "sxtb\\t%0, %1";
550   if (which_alternative == 0)
551     return "#";
553   addr = XEXP (operands[1], 0);
554   if (GET_CODE (addr) == PLUS
555       && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
556     return "ldrsb\\t%0, %1";
558   return "#";
560   [(set_attr_alternative "length"
561                          [(if_then_else (eq_attr "is_arch6" "yes")
562                                         (const_int 2) (const_int 4))
563                           (const_int 2)
564                           (if_then_else (eq_attr "is_arch6" "yes")
565                                         (const_int 4) (const_int 6))])
566    (set_attr "type" "extend,load_byte,load_byte")]
569 ;;; ??? This should have alternatives for constants.
570 ;;; ??? This was originally identical to the movdf_insn pattern.
571 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
572 ;;; thumb_reorg with a memory reference.
573 (define_insn "*thumb1_movdi_insn"
574   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
575         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
576   "TARGET_THUMB1
577    && (   register_operand (operands[0], DImode)
578        || register_operand (operands[1], DImode))"
579   "*
580   {
581   switch (which_alternative)
582     {
583     default:
584     case 0:
585       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
586         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
587       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
588     case 1:
589       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
590     case 2:
591       operands[1] = GEN_INT (- INTVAL (operands[1]));
592       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
593     case 3:
594       return \"ldmia\\t%1, {%0, %H0}\";
595     case 4:
596       return \"stmia\\t%0, {%1, %H1}\";
597     case 5:
598       return thumb_load_double_from_address (operands);
599     case 6:
600       operands[2] = gen_rtx_MEM (SImode,
601                              plus_constant (Pmode, XEXP (operands[0], 0), 4));
602       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
603       return \"\";
604     case 7:
605       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
606         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
607       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
608     }
609   }"
610   [(set_attr "length" "4,4,6,2,2,6,4,4")
611    (set_attr "type" "multiple,multiple,multiple,load2,store2,load2,store2,multiple")
612    (set_attr "pool_range" "*,*,*,*,*,1018,*,*")]
615 (define_insn "*thumb1_movsi_insn"
616   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
617         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*l*h*k"))]
618   "TARGET_THUMB1
619    && (   register_operand (operands[0], SImode)
620        || register_operand (operands[1], SImode))"
621   "@
622    mov  %0, %1
623    mov  %0, %1
624    #
625    #
626    ldmia\\t%1, {%0}
627    stmia\\t%0, {%1}
628    ldr\\t%0, %1
629    str\\t%1, %0
630    mov\\t%0, %1"
631   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
632    (set_attr "type" "mov_reg,mov_imm,multiple,multiple,load1,store1,load1,store1,mov_reg")
633    (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")
634    (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
636 ; Split the load of 64-bit constant into two loads for high and low 32-bit parts respectively
637 ; to see if we can load them in fewer instructions or fewer cycles.
638 ; For the small 64-bit integer constants that satisfy constraint J, the instruction pattern
639 ; thumb1_movdi_insn has a better way to handle them.
640 (define_split
641   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
642        (match_operand:ANY64 1 "const_double_operand" ""))]
643   "TARGET_THUMB1 && reload_completed && !satisfies_constraint_J (operands[1])"
644   [(set (match_dup 0) (match_dup 1))
645    (set (match_dup 2) (match_dup 3))]
646   "
647   operands[2] = gen_highpart (SImode, operands[0]);
648   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
649                                   operands[1]);
650   operands[0] = gen_lowpart (SImode, operands[0]);
651   operands[1] = gen_lowpart (SImode, operands[1]);
652   "
655 (define_split
656   [(set (match_operand:SI 0 "register_operand" "")
657         (match_operand:SI 1 "const_int_operand" ""))]
658   "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
659   [(set (match_dup 2) (match_dup 1))
660    (set (match_dup 0) (neg:SI (match_dup 2)))]
661   "
662   {
663     operands[1] = GEN_INT (- INTVAL (operands[1]));
664     operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
665   }"
668 (define_split
669   [(set (match_operand:SI 0 "register_operand" "")
670         (match_operand:SI 1 "const_int_operand" ""))]
671   "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
672   [(set (match_dup 2) (match_dup 1))
673    (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
674   "
675   {
676     unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
677     unsigned HOST_WIDE_INT mask = 0xff;
678     int i;
680     for (i = 0; i < 25; i++)
681       if ((val & (mask << i)) == val)
682         break;
684     /* Don't split if the shift is zero.  */
685     if (i == 0)
686       FAIL;
688     operands[1] = GEN_INT (val >> i);
689     operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
690     operands[3] = GEN_INT (i);
691   }"
694 ;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
695 (define_split
696   [(set (match_operand:SI 0 "register_operand" "")
697         (match_operand:SI 1 "const_int_operand" ""))]
698   "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
699   [(set (match_dup 2) (match_dup 1))
700    (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
701   "
702   {
703     operands[1] = GEN_INT (INTVAL (operands[1]) - 255);
704     operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
705     operands[3] = GEN_INT (255);
706   }"
709 (define_insn "*thumb1_movhi_insn"
710   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,l*r,*h,l")
711         (match_operand:HI 1 "general_operand"       "l,m,l,k*h,*r,I"))]
712   "TARGET_THUMB1
713    && (   register_operand (operands[0], HImode)
714        || register_operand (operands[1], HImode))"
715   "*
716   switch (which_alternative)
717     {
718     case 0: return \"add        %0, %1, #0\";
719     case 2: return \"strh       %1, %0\";
720     case 3: return \"mov        %0, %1\";
721     case 4: return \"mov        %0, %1\";
722     case 5: return \"mov        %0, %1\";
723     default: gcc_unreachable ();
724     case 1:
725       /* The stack pointer can end up being taken as an index register.
726           Catch this case here and deal with it.  */
727       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
728           && REG_P (XEXP (XEXP (operands[1], 0), 0))
729           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
730         {
731           rtx ops[2];
732           ops[0] = operands[0];
733           ops[1] = XEXP (XEXP (operands[1], 0), 0);
735           output_asm_insn (\"mov        %0, %1\", ops);
737           XEXP (XEXP (operands[1], 0), 0) = operands[0];
739         }
740       return \"ldrh     %0, %1\";
741     }"
742   [(set_attr "length" "2,4,2,2,2,2")
743    (set_attr "type" "alus_imm,load1,store1,mov_reg,mov_reg,mov_imm")
744    (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
746 (define_expand "thumb_movhi_clobber"
747   [(set (match_operand:HI     0 "memory_operand"   "")
748         (match_operand:HI     1 "register_operand" ""))
749    (clobber (match_operand:DI 2 "register_operand" ""))]
750   "TARGET_THUMB1"
751   "
752   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
753       && REGNO (operands[1]) <= LAST_LO_REGNUM)
754     {
755       emit_insn (gen_movhi (operands[0], operands[1]));
756       DONE;
757     }
758   /* XXX Fixme, need to handle other cases here as well.  */
759   gcc_unreachable ();
760   "
763 (define_insn "*thumb1_movqi_insn"
764   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,l*r,*h,l")
765         (match_operand:QI 1 "general_operand"       "l,m,l,k*h,*r,I"))]
766   "TARGET_THUMB1
767    && (   register_operand (operands[0], QImode)
768        || register_operand (operands[1], QImode))"
769   "@
770    add\\t%0, %1, #0
771    ldrb\\t%0, %1
772    strb\\t%1, %0
773    mov\\t%0, %1
774    mov\\t%0, %1
775    mov\\t%0, %1"
776   [(set_attr "length" "2")
777    (set_attr "type" "alu_imm,load1,store1,mov_reg,mov_imm,mov_imm")
778    (set_attr "pool_range" "*,32,*,*,*,*")
779    (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
781 (define_insn "*thumb1_movhf"
782   [(set (match_operand:HF     0 "nonimmediate_operand" "=l,l,m,*r,*h")
783         (match_operand:HF     1 "general_operand"      "l,mF,l,*h,*r"))]
784   "TARGET_THUMB1
785    && (   s_register_operand (operands[0], HFmode)
786        || s_register_operand (operands[1], HFmode))"
787   "*
788   switch (which_alternative)
789     {
790     case 1:
791       {
792         rtx addr;
793         gcc_assert (MEM_P (operands[1]));
794         addr = XEXP (operands[1], 0);
795         if (GET_CODE (addr) == LABEL_REF
796             || (GET_CODE (addr) == CONST
797                 && GET_CODE (XEXP (addr, 0)) == PLUS
798                 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
799                 && CONST_INT_P (XEXP (XEXP (addr, 0), 1))))
800           {
801             /* Constant pool entry.  */
802             return \"ldr\\t%0, %1\";
803           }
804         return \"ldrh\\t%0, %1\";
805       }
806     case 2: return \"strh\\t%1, %0\";
807     default: return \"mov\\t%0, %1\";
808     }
809   "
810   [(set_attr "length" "2")
811    (set_attr "type" "mov_reg,load1,store1,mov_reg,mov_reg")
812    (set_attr "pool_range" "*,1018,*,*,*")
813    (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
814 ;;; ??? This should have alternatives for constants.
815 (define_insn "*thumb1_movsf_insn"
816   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
817         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
818   "TARGET_THUMB1
819    && (   register_operand (operands[0], SFmode)
820        || register_operand (operands[1], SFmode))"
821   "@
822    add\\t%0, %1, #0
823    ldmia\\t%1, {%0}
824    stmia\\t%0, {%1}
825    ldr\\t%0, %1
826    str\\t%1, %0
827    mov\\t%0, %1
828    mov\\t%0, %1"
829   [(set_attr "length" "2")
830    (set_attr "type" "alus_imm,load1,store1,load1,store1,mov_reg,mov_reg")
831    (set_attr "pool_range" "*,*,*,1018,*,*,*")
832    (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
835 ;;; ??? This should have alternatives for constants.
836 ;;; ??? This was originally identical to the movdi_insn pattern.
837 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
838 ;;; thumb_reorg with a memory reference.
839 (define_insn "*thumb_movdf_insn"
840   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
841         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
842   "TARGET_THUMB1
843    && (   register_operand (operands[0], DFmode)
844        || register_operand (operands[1], DFmode))"
845   "*
846   switch (which_alternative)
847     {
848     default:
849     case 0:
850       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
851         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
852       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
853     case 1:
854       return \"ldmia\\t%1, {%0, %H0}\";
855     case 2:
856       return \"stmia\\t%0, {%1, %H1}\";
857     case 3:
858       return thumb_load_double_from_address (operands);
859     case 4:
860       operands[2] = gen_rtx_MEM (SImode,
861                                  plus_constant (Pmode,
862                                                 XEXP (operands[0], 0), 4));
863       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
864       return \"\";
865     case 5:
866       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
867         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
868       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
869     }
870   "
871   [(set_attr "length" "4,2,2,6,4,4")
872    (set_attr "type" "multiple,load2,store2,load2,store2,multiple")
873    (set_attr "pool_range" "*,*,*,1018,*,*")]
877 ;; Thumb block-move insns
879 (define_insn "movmem12b"
880   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
881         (mem:SI (match_operand:SI 3 "register_operand" "1")))
882    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
883         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
884    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
885         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
886    (set (match_operand:SI 0 "register_operand" "=l")
887         (plus:SI (match_dup 2) (const_int 12)))
888    (set (match_operand:SI 1 "register_operand" "=l")
889         (plus:SI (match_dup 3) (const_int 12)))
890    (clobber (match_scratch:SI 4 "=&l"))
891    (clobber (match_scratch:SI 5 "=&l"))
892    (clobber (match_scratch:SI 6 "=&l"))]
893   "TARGET_THUMB1"
894   "* return thumb_output_move_mem_multiple (3, operands);"
895   [(set_attr "length" "4")
896    ; This isn't entirely accurate...  It loads as well, but in terms of
897    ; scheduling the following insn it is better to consider it as a store
898    (set_attr "type" "store3")]
901 (define_insn "movmem8b"
902   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
903         (mem:SI (match_operand:SI 3 "register_operand" "1")))
904    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
905         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
906    (set (match_operand:SI 0 "register_operand" "=l")
907         (plus:SI (match_dup 2) (const_int 8)))
908    (set (match_operand:SI 1 "register_operand" "=l")
909         (plus:SI (match_dup 3) (const_int 8)))
910    (clobber (match_scratch:SI 4 "=&l"))
911    (clobber (match_scratch:SI 5 "=&l"))]
912   "TARGET_THUMB1"
913   "* return thumb_output_move_mem_multiple (2, operands);"
914   [(set_attr "length" "4")
915    ; This isn't entirely accurate...  It loads as well, but in terms of
916    ; scheduling the following insn it is better to consider it as a store
917    (set_attr "type" "store2")]
921 ;; A pattern to recognize a special situation and optimize for it.
922 ;; On the thumb, zero-extension from memory is preferrable to sign-extension
923 ;; due to the available addressing modes.  Hence, convert a signed comparison
924 ;; with zero into an unsigned comparison with 127 if possible.
925 (define_expand "cbranchqi4"
926   [(set (pc) (if_then_else
927               (match_operator 0 "lt_ge_comparison_operator"
928                [(match_operand:QI 1 "memory_operand" "")
929                 (match_operand:QI 2 "const0_operand" "")])
930               (label_ref (match_operand 3 "" ""))
931               (pc)))]
932   "TARGET_THUMB1"
934   rtx xops[4];
935   xops[1] = gen_reg_rtx (SImode);
936   emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
937   xops[2] = GEN_INT (127);
938   xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
939                             VOIDmode, xops[1], xops[2]);
940   xops[3] = operands[3];
941   emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
942   DONE;
945 (define_insn "cbranchsi4_insn"
946   [(set (pc) (if_then_else
947               (match_operator 0 "arm_comparison_operator"
948                [(match_operand:SI 1 "s_register_operand" "l,l*h")
949                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
950               (label_ref (match_operand 3 "" ""))
951               (pc)))]
952   "TARGET_THUMB1"
954   rtx t = cfun->machine->thumb1_cc_insn;
955   if (t != NULL_RTX)
956     {
957       if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
958           || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
959         t = NULL_RTX;
960       if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
961         {
962           if (!noov_comparison_operator (operands[0], VOIDmode))
963             t = NULL_RTX;
964         }
965       else if (cfun->machine->thumb1_cc_mode != CCmode)
966         t = NULL_RTX;
967     }
968   if (t == NULL_RTX)
969     {
970       output_asm_insn ("cmp\t%1, %2", operands);
971       cfun->machine->thumb1_cc_insn = insn;
972       cfun->machine->thumb1_cc_op0 = operands[1];
973       cfun->machine->thumb1_cc_op1 = operands[2];
974       cfun->machine->thumb1_cc_mode = CCmode;
975     }
976   else
977     /* Ensure we emit the right type of condition code on the jump.  */
978     XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
979                                          CC_REGNUM);
981   switch (get_attr_length (insn))
982     {
983     case 4:  return \"b%d0\\t%l3\";
984     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
985     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
986     }
988   [(set (attr "far_jump")
989         (if_then_else
990             (eq_attr "length" "8")
991             (const_string "yes")
992             (const_string "no")))
993    (set (attr "length")
994         (if_then_else
995             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
996                  (le (minus (match_dup 3) (pc)) (const_int 256)))
997             (const_int 4)
998             (if_then_else
999                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1000                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
1001                 (const_int 6)
1002                 (const_int 8))))
1003    (set_attr "type" "multiple")]
1006 (define_insn "cbranchsi4_scratch"
1007   [(set (pc) (if_then_else
1008               (match_operator 4 "arm_comparison_operator"
1009                [(match_operand:SI 1 "s_register_operand" "l,0")
1010                 (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
1011               (label_ref (match_operand 3 "" ""))
1012               (pc)))
1013    (clobber (match_scratch:SI 0 "=l,l"))]
1014   "TARGET_THUMB1"
1015   "*
1016   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
1018   switch (get_attr_length (insn))
1019     {
1020     case 4:  return \"b%d4\\t%l3\";
1021     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
1022     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
1023     }
1024   "
1025   [(set (attr "far_jump")
1026         (if_then_else
1027             (eq_attr "length" "8")
1028             (const_string "yes")
1029             (const_string "no")))
1030    (set (attr "length")
1031         (if_then_else
1032             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1033                  (le (minus (match_dup 3) (pc)) (const_int 256)))
1034             (const_int 4)
1035             (if_then_else
1036                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1037                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
1038                 (const_int 6)
1039                 (const_int 8))))
1040    (set_attr "type" "multiple")]
1043 (define_insn "*negated_cbranchsi4"
1044   [(set (pc)
1045         (if_then_else
1046          (match_operator 0 "equality_operator"
1047           [(match_operand:SI 1 "s_register_operand" "l")
1048            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
1049          (label_ref (match_operand 3 "" ""))
1050          (pc)))]
1051   "TARGET_THUMB1"
1052   "*
1053   output_asm_insn (\"cmn\\t%1, %2\", operands);
1054   switch (get_attr_length (insn))
1055     {
1056     case 4:  return \"b%d0\\t%l3\";
1057     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
1058     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
1059     }
1060   "
1061   [(set (attr "far_jump")
1062         (if_then_else
1063             (eq_attr "length" "8")
1064             (const_string "yes")
1065             (const_string "no")))
1066    (set (attr "length")
1067         (if_then_else
1068             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1069                  (le (minus (match_dup 3) (pc)) (const_int 256)))
1070             (const_int 4)
1071             (if_then_else
1072                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1073                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
1074                 (const_int 6)
1075                 (const_int 8))))
1076    (set_attr "type" "multiple")]
1079 (define_insn "*tbit_cbranch"
1080   [(set (pc)
1081         (if_then_else
1082          (match_operator 0 "equality_operator"
1083           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
1084                             (const_int 1)
1085                             (match_operand:SI 2 "const_int_operand" "i"))
1086            (const_int 0)])
1087          (label_ref (match_operand 3 "" ""))
1088          (pc)))
1089    (clobber (match_scratch:SI 4 "=l"))]
1090   "TARGET_THUMB1"
1091   "*
1092   {
1093   rtx op[3];
1094   op[0] = operands[4];
1095   op[1] = operands[1];
1096   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
1098   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
1099   switch (get_attr_length (insn))
1100     {
1101     case 4:  return \"b%d0\\t%l3\";
1102     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
1103     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
1104     }
1105   }"
1106   [(set (attr "far_jump")
1107         (if_then_else
1108             (eq_attr "length" "8")
1109             (const_string "yes")
1110             (const_string "no")))
1111    (set (attr "length")
1112         (if_then_else
1113             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1114                  (le (minus (match_dup 3) (pc)) (const_int 256)))
1115             (const_int 4)
1116             (if_then_else
1117                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1118                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
1119                 (const_int 6)
1120                 (const_int 8))))
1121    (set_attr "type" "multiple")]
1124 (define_insn "*tlobits_cbranch"
1125   [(set (pc)
1126         (if_then_else
1127          (match_operator 0 "equality_operator"
1128           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
1129                             (match_operand:SI 2 "const_int_operand" "i")
1130                             (const_int 0))
1131            (const_int 0)])
1132          (label_ref (match_operand 3 "" ""))
1133          (pc)))
1134    (clobber (match_scratch:SI 4 "=l"))]
1135   "TARGET_THUMB1"
1136   "*
1137   {
1138   rtx op[3];
1139   op[0] = operands[4];
1140   op[1] = operands[1];
1141   op[2] = GEN_INT (32 - INTVAL (operands[2]));
1143   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
1144   switch (get_attr_length (insn))
1145     {
1146     case 4:  return \"b%d0\\t%l3\";
1147     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
1148     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
1149     }
1150   }"
1151   [(set (attr "far_jump")
1152         (if_then_else
1153             (eq_attr "length" "8")
1154             (const_string "yes")
1155             (const_string "no")))
1156    (set (attr "length")
1157         (if_then_else
1158             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1159                  (le (minus (match_dup 3) (pc)) (const_int 256)))
1160             (const_int 4)
1161             (if_then_else
1162                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1163                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
1164                 (const_int 6)
1165                 (const_int 8))))
1166    (set_attr "type" "multiple")]
1169 (define_insn "*tstsi3_cbranch"
1170   [(set (pc)
1171         (if_then_else
1172          (match_operator 3 "equality_operator"
1173           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
1174                    (match_operand:SI 1 "s_register_operand" "l"))
1175            (const_int 0)])
1176          (label_ref (match_operand 2 "" ""))
1177          (pc)))]
1178   "TARGET_THUMB1"
1179   "*
1180   {
1181   output_asm_insn (\"tst\\t%0, %1\", operands);
1182   switch (get_attr_length (insn))
1183     {
1184     case 4:  return \"b%d3\\t%l2\";
1185     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
1186     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
1187     }
1188   }"
1189   [(set (attr "far_jump")
1190         (if_then_else
1191             (eq_attr "length" "8")
1192             (const_string "yes")
1193             (const_string "no")))
1194    (set (attr "length")
1195         (if_then_else
1196             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
1197                  (le (minus (match_dup 2) (pc)) (const_int 256)))
1198             (const_int 4)
1199             (if_then_else
1200                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
1201                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
1202                 (const_int 6)
1203                 (const_int 8))))
1204    (set_attr "type" "multiple")]
1207 (define_insn "*cbranchne_decr1"
1208   [(set (pc)
1209         (if_then_else (match_operator 3 "equality_operator"
1210                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
1211                         (const_int 0)])
1212                       (label_ref (match_operand 4 "" ""))
1213                       (pc)))
1214    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
1215         (plus:SI (match_dup 2) (const_int -1)))
1216    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
1217   "TARGET_THUMB1"
1218   "*
1219    {
1220      rtx cond[2];
1221      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
1222                                 ? GEU : LTU),
1223                                VOIDmode, operands[2], const1_rtx);
1224      cond[1] = operands[4];
1226      if (which_alternative == 0)
1227        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
1228      else if (which_alternative == 1)
1229        {
1230          /* We must provide an alternative for a hi reg because reload
1231             cannot handle output reloads on a jump instruction, but we
1232             can't subtract into that.  Fortunately a mov from lo to hi
1233             does not clobber the condition codes.  */
1234          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
1235          output_asm_insn (\"mov\\t%0, %1\", operands);
1236        }
1237      else
1238        {
1239          /* Similarly, but the target is memory.  */
1240          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
1241          output_asm_insn (\"str\\t%1, %0\", operands);
1242        }
1244      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
1245        {
1246          case 4:
1247            output_asm_insn (\"b%d0\\t%l1\", cond);
1248            return \"\";
1249          case 6:
1250            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
1251            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
1252          default:
1253            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
1254            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
1255        }
1256    }
1257   "
1258   [(set (attr "far_jump")
1259         (if_then_else
1260             (ior (and (eq (symbol_ref ("which_alternative"))
1261                           (const_int 0))
1262                       (eq_attr "length" "8"))
1263                  (eq_attr "length" "10"))
1264             (const_string "yes")
1265             (const_string "no")))
1266    (set_attr_alternative "length"
1267       [
1268        ;; Alternative 0
1269        (if_then_else
1270          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
1271               (le (minus (match_dup 4) (pc)) (const_int 256)))
1272          (const_int 4)
1273          (if_then_else
1274            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
1275                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1276            (const_int 6)
1277            (const_int 8)))
1278        ;; Alternative 1
1279        (if_then_else
1280          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
1281               (le (minus (match_dup 4) (pc)) (const_int 256)))
1282          (const_int 6)
1283          (if_then_else
1284            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
1285                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1286            (const_int 8)
1287            (const_int 10)))
1288        ;; Alternative 2
1289        (if_then_else
1290          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
1291               (le (minus (match_dup 4) (pc)) (const_int 256)))
1292          (const_int 6)
1293          (if_then_else
1294            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
1295                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1296            (const_int 8)
1297            (const_int 10)))
1298        ;; Alternative 3
1299        (if_then_else
1300          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
1301               (le (minus (match_dup 4) (pc)) (const_int 256)))
1302          (const_int 6)
1303          (if_then_else
1304            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
1305                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1306            (const_int 8)
1307            (const_int 10)))])
1308    (set_attr "type" "multiple")]
1311 (define_insn "*addsi3_cbranch"
1312   [(set (pc)
1313         (if_then_else
1314          (match_operator 4 "arm_comparison_operator"
1315           [(plus:SI
1316             (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
1317             (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
1318            (const_int 0)])
1319          (label_ref (match_operand 5 "" ""))
1320          (pc)))
1321    (set
1322     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
1323     (plus:SI (match_dup 2) (match_dup 3)))
1324    (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
1325   "TARGET_THUMB1
1326    && (GET_CODE (operands[4]) == EQ
1327        || GET_CODE (operands[4]) == NE
1328        || GET_CODE (operands[4]) == GE
1329        || GET_CODE (operands[4]) == LT)"
1330   "*
1331    {
1332      rtx cond[3];
1334      cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
1335      cond[1] = operands[2];
1336      cond[2] = operands[3];
1338      if (CONST_INT_P (cond[2]) && INTVAL (cond[2]) < 0)
1339        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
1340      else
1341        output_asm_insn (\"add\\t%0, %1, %2\", cond);
1343      if (which_alternative >= 2
1344          && which_alternative < 4)
1345        output_asm_insn (\"mov\\t%0, %1\", operands);
1346      else if (which_alternative >= 4)
1347        output_asm_insn (\"str\\t%1, %0\", operands);
1349      switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
1350        {
1351          case 4:
1352            return \"b%d4\\t%l5\";
1353          case 6:
1354            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
1355          default:
1356            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
1357        }
1358    }
1359   "
1360   [(set (attr "far_jump")
1361         (if_then_else
1362             (ior (and (lt (symbol_ref ("which_alternative"))
1363                           (const_int 2))
1364                       (eq_attr "length" "8"))
1365                  (eq_attr "length" "10"))
1366             (const_string "yes")
1367             (const_string "no")))
1368    (set (attr "length")
1369      (if_then_else
1370        (lt (symbol_ref ("which_alternative"))
1371                        (const_int 2))
1372        (if_then_else
1373          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
1374               (le (minus (match_dup 5) (pc)) (const_int 256)))
1375          (const_int 4)
1376          (if_then_else
1377            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
1378                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
1379            (const_int 6)
1380            (const_int 8)))
1381        (if_then_else
1382          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
1383               (le (minus (match_dup 5) (pc)) (const_int 256)))
1384          (const_int 6)
1385          (if_then_else
1386            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
1387                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
1388            (const_int 8)
1389            (const_int 10)))))
1390    (set_attr "type" "multiple")]
1393 (define_insn "*addsi3_cbranch_scratch"
1394   [(set (pc)
1395         (if_then_else
1396          (match_operator 3 "arm_comparison_operator"
1397           [(plus:SI
1398             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
1399             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
1400            (const_int 0)])
1401          (label_ref (match_operand 4 "" ""))
1402          (pc)))
1403    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
1404   "TARGET_THUMB1
1405    && (GET_CODE (operands[3]) == EQ
1406        || GET_CODE (operands[3]) == NE
1407        || GET_CODE (operands[3]) == GE
1408        || GET_CODE (operands[3]) == LT)"
1409   "*
1410    {
1411      switch (which_alternative)
1412        {
1413        case 0:
1414          output_asm_insn (\"cmp\t%1, #%n2\", operands);
1415          break;
1416        case 1:
1417          output_asm_insn (\"cmn\t%1, %2\", operands);
1418          break;
1419        case 2:
1420          if (INTVAL (operands[2]) < 0)
1421            output_asm_insn (\"sub\t%0, %1, %2\", operands);
1422          else
1423            output_asm_insn (\"add\t%0, %1, %2\", operands);
1424          break;
1425        case 3:
1426          if (INTVAL (operands[2]) < 0)
1427            output_asm_insn (\"sub\t%0, %0, %2\", operands);
1428          else
1429            output_asm_insn (\"add\t%0, %0, %2\", operands);
1430          break;
1431        }
1433      switch (get_attr_length (insn))
1434        {
1435          case 4:
1436            return \"b%d3\\t%l4\";
1437          case 6:
1438            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
1439          default:
1440            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
1441        }
1442    }
1443   "
1444   [(set (attr "far_jump")
1445         (if_then_else
1446             (eq_attr "length" "8")
1447             (const_string "yes")
1448             (const_string "no")))
1449    (set (attr "length")
1450        (if_then_else
1451          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
1452               (le (minus (match_dup 4) (pc)) (const_int 256)))
1453          (const_int 4)
1454          (if_then_else
1455            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
1456                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1457            (const_int 6)
1458            (const_int 8))))
1459    (set_attr "type" "multiple")]
1462 (define_insn "*thumb_cmpdi_zero"
1463   [(set (reg:CC_Z CC_REGNUM)
1464         (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
1465                       (const_int 0)))
1466    (clobber (match_scratch:SI 1 "=l"))]
1467   "TARGET_THUMB1"
1468   "orr\\t%1, %Q0, %R0"
1469   [(set_attr "conds" "set")
1470    (set_attr "length" "2")
1471    (set_attr "type" "logics_reg")]
1474 (define_expand "cstoresi_eq0_thumb1"
1475   [(parallel
1476     [(set (match_operand:SI 0 "s_register_operand" "")
1477           (eq:SI (match_operand:SI 1 "s_register_operand" "")
1478                  (const_int 0)))
1479      (clobber (match_dup:SI 2))])]
1480   "TARGET_THUMB1"
1481   "operands[2] = gen_reg_rtx (SImode);"
1484 (define_expand "cstoresi_ne0_thumb1"
1485   [(parallel
1486     [(set (match_operand:SI 0 "s_register_operand" "")
1487           (ne:SI (match_operand:SI 1 "s_register_operand" "")
1488                  (const_int 0)))
1489      (clobber (match_dup:SI 2))])]
1490   "TARGET_THUMB1"
1491   "operands[2] = gen_reg_rtx (SImode);"
1494 (define_insn "*cstoresi_eq0_thumb1_insn"
1495   [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
1496         (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
1497                (const_int 0)))
1498    (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
1499   "TARGET_THUMB1"
1500   "@
1501    neg\\t%0, %1\;adc\\t%0, %0, %1
1502    neg\\t%2, %1\;adc\\t%0, %1, %2"
1503   [(set_attr "length" "4")
1504    (set_attr "type" "multiple")]
1507 (define_insn "*cstoresi_ne0_thumb1_insn"
1508   [(set (match_operand:SI 0 "s_register_operand" "=l")
1509         (ne:SI (match_operand:SI 1 "s_register_operand" "0")
1510                (const_int 0)))
1511    (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
1512   "TARGET_THUMB1"
1513   "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
1514   [(set_attr "length" "4")]
1517 ;; Used as part of the expansion of thumb ltu and gtu sequences
1518 (define_insn "cstoresi_nltu_thumb1"
1519   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
1520         (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
1521                         (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
1522   "TARGET_THUMB1"
1523   "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
1524   [(set_attr "length" "4")
1525    (set_attr "type" "multiple")]
1528 (define_insn_and_split "cstoresi_ltu_thumb1"
1529   [(set (match_operand:SI 0 "s_register_operand" "=l,l")
1530         (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
1531                 (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
1532   "TARGET_THUMB1"
1533   "#"
1534   "TARGET_THUMB1"
1535   [(set (match_dup 3)
1536         (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
1537    (set (match_dup 0) (neg:SI (match_dup 3)))]
1538   "operands[3] = gen_reg_rtx (SImode);"
1539   [(set_attr "length" "4")
1540    (set_attr "type" "multiple")]
1543 ;; Used as part of the expansion of thumb les sequence.
1544 (define_insn "thumb1_addsi3_addgeu"
1545   [(set (match_operand:SI 0 "s_register_operand" "=l")
1546         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
1547                           (match_operand:SI 2 "s_register_operand" "l"))
1548                  (geu:SI (match_operand:SI 3 "s_register_operand" "l")
1549                          (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
1550   "TARGET_THUMB1"
1551   "cmp\\t%3, %4\;adc\\t%0, %1, %2"
1552   [(set_attr "length" "4")
1553    (set_attr "type" "multiple")]
1557 (define_insn "*thumb_jump"
1558   [(set (pc)
1559         (label_ref (match_operand 0 "" "")))]
1560   "TARGET_THUMB1"
1561   "*
1562   if (get_attr_length (insn) == 2)
1563     return \"b\\t%l0\";
1564   return \"bl\\t%l0\\t%@ far jump\";
1565   "
1566   [(set (attr "far_jump")
1567         (if_then_else
1568             (eq_attr "length" "4")
1569             (const_string "yes")
1570             (const_string "no")))
1571    (set (attr "length")
1572         (if_then_else
1573             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
1574                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
1575             (const_int 2)
1576             (const_int 4)))
1577    (set_attr "type" "branch")]
1580 (define_insn "*call_reg_thumb1_v5"
1581   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
1582          (match_operand 1 "" ""))
1583    (use (match_operand 2 "" ""))
1584    (clobber (reg:SI LR_REGNUM))]
1585   "TARGET_THUMB1 && arm_arch5 && !SIBLING_CALL_P (insn)"
1586   "blx\\t%0"
1587   [(set_attr "length" "2")
1588    (set_attr "type" "call")]
1591 (define_insn "*call_reg_thumb1"
1592   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
1593          (match_operand 1 "" ""))
1594    (use (match_operand 2 "" ""))
1595    (clobber (reg:SI LR_REGNUM))]
1596   "TARGET_THUMB1 && !arm_arch5 && !SIBLING_CALL_P (insn)"
1597   "*
1598   {
1599     if (!TARGET_CALLER_INTERWORKING)
1600       return thumb_call_via_reg (operands[0]);
1601     else if (operands[1] == const0_rtx)
1602       return \"bl\\t%__interwork_call_via_%0\";
1603     else if (frame_pointer_needed)
1604       return \"bl\\t%__interwork_r7_call_via_%0\";
1605     else
1606       return \"bl\\t%__interwork_r11_call_via_%0\";
1607   }"
1608   [(set_attr "type" "call")]
1611 (define_insn "*call_value_reg_thumb1_v5"
1612   [(set (match_operand 0 "" "")
1613         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
1614               (match_operand 2 "" "")))
1615    (use (match_operand 3 "" ""))
1616    (clobber (reg:SI LR_REGNUM))]
1617   "TARGET_THUMB1 && arm_arch5"
1618   "blx\\t%1"
1619   [(set_attr "length" "2")
1620    (set_attr "type" "call")]
1623 (define_insn "*call_value_reg_thumb1"
1624   [(set (match_operand 0 "" "")
1625         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
1626               (match_operand 2 "" "")))
1627    (use (match_operand 3 "" ""))
1628    (clobber (reg:SI LR_REGNUM))]
1629   "TARGET_THUMB1 && !arm_arch5"
1630   "*
1631   {
1632     if (!TARGET_CALLER_INTERWORKING)
1633       return thumb_call_via_reg (operands[1]);
1634     else if (operands[2] == const0_rtx)
1635       return \"bl\\t%__interwork_call_via_%1\";
1636     else if (frame_pointer_needed)
1637       return \"bl\\t%__interwork_r7_call_via_%1\";
1638     else
1639       return \"bl\\t%__interwork_r11_call_via_%1\";
1640   }"
1641   [(set_attr "type" "call")]
1644 (define_insn "*call_insn"
1645   [(call (mem:SI (match_operand:SI 0 "" ""))
1646          (match_operand:SI 1 "" ""))
1647    (use (match_operand 2 "" ""))
1648    (clobber (reg:SI LR_REGNUM))]
1649   "TARGET_THUMB1
1650    && GET_CODE (operands[0]) == SYMBOL_REF
1651    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
1652   "bl\\t%a0"
1653   [(set_attr "length" "4")
1654    (set_attr "type" "call")]
1657 (define_insn "*call_value_insn"
1658   [(set (match_operand 0 "" "")
1659         (call (mem:SI (match_operand 1 "" ""))
1660               (match_operand 2 "" "")))
1661    (use (match_operand 3 "" ""))
1662    (clobber (reg:SI LR_REGNUM))]
1663   "TARGET_THUMB1
1664    && GET_CODE (operands[1]) == SYMBOL_REF
1665    && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
1666   "bl\\t%a1"
1667   [(set_attr "length" "4")
1668    (set_attr "type" "call")]
1671 (define_expand "thumb1_casesi_internal_pic"
1672   [(match_operand:SI 0 "s_register_operand" "")
1673    (match_operand:SI 1 "thumb1_cmp_operand" "")
1674    (match_operand 2 "" "")
1675    (match_operand 3 "" "")]
1676   "TARGET_THUMB1"
1677   {
1678     rtx reg0;
1679     rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
1680     emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
1681                                     operands[3]));
1682     reg0 = gen_rtx_REG (SImode, 0);
1683     emit_move_insn (reg0, operands[0]);
1684     emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
1685     DONE;
1686   }
1689 (define_insn "thumb1_casesi_dispatch"
1690   [(parallel [(set (pc) (unspec [(reg:SI 0)
1691                                  (label_ref (match_operand 0 "" ""))
1692 ;;                               (label_ref (match_operand 1 "" ""))
1694                          UNSPEC_THUMB1_CASESI))
1695               (clobber (reg:SI IP_REGNUM))
1696               (clobber (reg:SI LR_REGNUM))])]
1697   "TARGET_THUMB1"
1698   "* return thumb1_output_casesi(operands);"
1699   [(set_attr "length" "4")
1700    (set_attr "type" "multiple")]
1703 ;; NB Never uses BX.
1704 (define_insn "*thumb1_indirect_jump"
1705   [(set (pc)
1706         (match_operand:SI 0 "register_operand" "l*r"))]
1707   "TARGET_THUMB1"
1708   "mov\\tpc, %0"
1709   [(set_attr "conds" "clob")
1710    (set_attr "length" "2")
1711    (set_attr "type" "branch")]
1715 (define_insn "prologue_thumb1_interwork"
1716   [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
1717   "TARGET_THUMB1"
1718   "* return thumb1_output_interwork ();"
1719   [(set_attr "length" "8")
1720    (set_attr "type" "multiple")]
1723 (define_insn "*epilogue_insns"
1724   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
1725   "TARGET_THUMB1"
1726   "*
1727     return thumb1_unexpanded_epilogue ();
1728   "
1729   ; Length is absolute worst case
1730   [(set_attr "length" "44")
1731    (set_attr "type" "block")
1732    ;; We don't clobber the conditions, but the potential length of this
1733    ;; operation is sufficient to make conditionalizing the sequence
1734    ;; unlikely to be profitable.
1735    (set_attr "conds" "clob")]
1738 (define_insn "consttable_1"
1739   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
1740   "TARGET_THUMB1"
1741   "*
1742   making_const_table = TRUE;
1743   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
1744   assemble_zeros (3);
1745   return \"\";
1746   "
1747   [(set_attr "length" "4")
1748    (set_attr "type" "no_insn")]
1751 (define_insn "consttable_2"
1752   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
1753   "TARGET_THUMB1"
1754   "*
1755   making_const_table = TRUE;
1756   gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
1757   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
1758   assemble_zeros (2);
1759   return \"\";
1760   "
1761   [(set_attr "length" "4")
1762    (set_attr "type" "no_insn")]
1765 ;; Miscellaneous Thumb patterns
1766 (define_expand "tablejump"
1767   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
1768               (use (label_ref (match_operand 1 "" "")))])]
1769   "TARGET_THUMB1"
1770   "
1771   if (flag_pic)
1772     {
1773       /* Hopefully, CSE will eliminate this copy.  */
1774       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
1775       rtx reg2 = gen_reg_rtx (SImode);
1777       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
1778       operands[0] = reg2;
1779     }
1780   "
1783 ;; NB never uses BX.
1784 (define_insn "*thumb1_tablejump"
1785   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
1786    (use (label_ref (match_operand 1 "" "")))]
1787   "TARGET_THUMB1"
1788   "mov\\t%|pc, %0"
1789   [(set_attr "length" "2")
1790    (set_attr "type" "no_insn")]
1793 (define_insn_and_split "thumb_eh_return"
1794   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
1795                     VUNSPEC_EH_RETURN)
1796    (clobber (match_scratch:SI 1 "=&l"))]
1797   "TARGET_THUMB1"
1798   "#"
1799   "&& reload_completed"
1800   [(const_int 0)]
1801   "
1802   {
1803     thumb_set_return_address (operands[0], operands[1]);
1804     DONE;
1805   }"
1806   [(set_attr "type" "mov_reg")]