1 ;; ARM Thumb-1 Machine Description
2 ;; Copyright (C) 2007-2014 Free Software Foundation, Inc.
4 ;; This file is part of GCC.
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)
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 ;;---------------------------------------------------------------------------
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))
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")))]
43 static const char * const asms[] =
46 \"sub\\t%0, %0, #%n2\",
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];
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)))]
70 HOST_WIDE_INT offset = INTVAL (operands[2]);
71 if (operands[1] == stack_pointer_rtx)
77 else if (offset < -255)
80 operands[3] = GEN_INT (offset);
81 operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
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.
91 [(set (match_operand:SI 0 "arm_general_register_operand" "")
92 (match_operand:SI 1 "const_int_operand" ""))
94 (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
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)))]
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))]
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")))]
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"
135 if (which_alternative < 2)
136 return \"mov\\t%0, %1\;mul\\t%0, %2\";
138 return \"mul\\t%0, %2\";
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"
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")))]
163 [(set_attr "length" "2")
164 (set_attr "type" "logic_imm")
165 (set_attr "conds" "set")])
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" ""))]
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)))]
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);
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" "")))]
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)))]
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);
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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")))]
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))]
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")))]
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"))]
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)))]
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"))]
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)))]
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")))]
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")))]
337 if (which_alternative == 0 && arm_arch6)
338 return "uxth\t%0, %1";
339 if (which_alternative == 0)
342 mem = XEXP (operands[1], 0);
344 if (GET_CODE (mem) == CONST)
347 if (GET_CODE (mem) == PLUS)
349 rtx a = XEXP (mem, 0);
351 /* This can happen due to bugs in reload. */
352 if (REG_P (a) && REGNO (a) == SP_REGNUM)
355 ops[0] = operands[0];
358 output_asm_insn ("mov\t%0, %1", ops);
360 XEXP (mem, 0) = operands[0];
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))
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"
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"
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"))]
413 if (which_alternative == 0 && !arm_arch6)
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
425 if (GET_CODE (mem) == CONST)
428 if (GET_CODE (mem) == LABEL_REF)
429 return \"ldr\\t%0, %1\";
431 if (GET_CODE (mem) == PLUS)
433 rtx a = XEXP (mem, 0);
434 rtx b = XEXP (mem, 1);
436 if (GET_CODE (a) == LABEL_REF
438 return \"ldr\\t%0, %1\";
441 return \"ldrsh\\t%0, %1\";
452 gcc_assert (REG_P (ops[1]));
454 ops[0] = operands[0];
455 if (reg_mentioned_p (operands[2], ops[1]))
458 ops[3] = operands[2];
459 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
462 [(set_attr_alternative "length"
463 [(if_then_else (eq_attr "is_arch6" "yes")
464 (const_int 2) (const_int 4))
466 (set_attr "type" "extend,load_byte")
467 (set_attr "pool_range" "*,1018")]
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. */
487 if (GET_CODE (addr) == PLUS
488 && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
491 if (reg_overlap_mentioned_p (operands[0], addr))
493 rtx t = gen_lowpart (QImode, operands[0]);
494 emit_move_insn (t, operands[1]);
495 emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
501 addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
502 operands[2] = const0_rtx;
504 else if (GET_CODE (addr) != PLUS)
506 else if (REG_P (XEXP (addr, 0)))
508 operands[2] = XEXP (addr, 1);
509 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
513 operands[2] = XEXP (addr, 0);
514 addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
517 operands[3] = change_address (operands[1], QImode, addr);
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" "")))]
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")))]
548 if (which_alternative == 0 && arm_arch6)
549 return "sxtb\\t%0, %1";
550 if (which_alternative == 0)
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";
560 [(set_attr_alternative "length"
561 [(if_then_else (eq_attr "is_arch6" "yes")
562 (const_int 2) (const_int 4))
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"))]
577 && ( register_operand (operands[0], DImode)
578 || register_operand (operands[1], DImode))"
581 switch (which_alternative)
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\";
589 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
591 operands[1] = GEN_INT (- INTVAL (operands[1]));
592 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
594 return \"ldmia\\t%1, {%0, %H0}\";
596 return \"stmia\\t%0, {%1, %H1}\";
598 return thumb_load_double_from_address (operands);
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);
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\";
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"))]
619 && ( register_operand (operands[0], SImode)
620 || register_operand (operands[1], SImode))"
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.
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))]
647 operands[2] = gen_highpart (SImode, operands[0]);
648 operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
650 operands[0] = gen_lowpart (SImode, operands[0]);
651 operands[1] = gen_lowpart (SImode, operands[1]);
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)))]
663 operands[1] = GEN_INT (- INTVAL (operands[1]));
664 operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
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)))]
676 unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
677 unsigned HOST_WIDE_INT mask = 0xff;
680 for (i = 0; i < 25; i++)
681 if ((val & (mask << i)) == val)
684 /* Don't split if the shift is zero. */
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);
694 ;; For thumb1 split imm move [256-510] into mov [1-255] and add #255
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)))]
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);
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"))]
713 && ( register_operand (operands[0], HImode)
714 || register_operand (operands[1], HImode))"
716 switch (which_alternative)
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 ();
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)
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];
740 return \"ldrh %0, %1\";
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" ""))]
752 if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
753 && REGNO (operands[1]) <= LAST_LO_REGNUM)
755 emit_insn (gen_movhi (operands[0], operands[1]));
758 /* XXX Fixme, need to handle other cases here as well. */
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"))]
767 && ( register_operand (operands[0], QImode)
768 || register_operand (operands[1], QImode))"
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"))]
785 && ( s_register_operand (operands[0], HFmode)
786 || s_register_operand (operands[1], HFmode))"
788 switch (which_alternative)
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))))
801 /* Constant pool entry. */
802 return \"ldr\\t%0, %1\";
804 return \"ldrh\\t%0, %1\";
806 case 2: return \"strh\\t%1, %0\";
807 default: return \"mov\\t%0, %1\";
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"))]
819 && ( register_operand (operands[0], SFmode)
820 || register_operand (operands[1], SFmode))"
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"))]
843 && ( register_operand (operands[0], DFmode)
844 || register_operand (operands[1], DFmode))"
846 switch (which_alternative)
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\";
854 return \"ldmia\\t%1, {%0, %H0}\";
856 return \"stmia\\t%0, {%1, %H1}\";
858 return thumb_load_double_from_address (operands);
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);
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\";
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"))]
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"))]
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 "" ""))
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]));
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 "" ""))
954 rtx t = cfun->machine->thumb1_cc_insn;
957 if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
958 || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
960 if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
962 if (!noov_comparison_operator (operands[0], VOIDmode))
965 else if (cfun->machine->thumb1_cc_mode != CCmode)
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;
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,
981 switch (get_attr_length (insn))
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%=:\";
988 [(set (attr "far_jump")
990 (eq_attr "length" "8")
992 (const_string "no")))
995 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
996 (le (minus (match_dup 3) (pc)) (const_int 256)))
999 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1000 (le (minus (match_dup 3) (pc)) (const_int 2048)))
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 "" ""))
1013 (clobber (match_scratch:SI 0 "=l,l"))]
1016 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
1018 switch (get_attr_length (insn))
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%=:\";
1025 [(set (attr "far_jump")
1027 (eq_attr "length" "8")
1028 (const_string "yes")
1029 (const_string "no")))
1030 (set (attr "length")
1032 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1033 (le (minus (match_dup 3) (pc)) (const_int 256)))
1036 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1037 (le (minus (match_dup 3) (pc)) (const_int 2048)))
1040 (set_attr "type" "multiple")]
1043 (define_insn "*negated_cbranchsi4"
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 "" ""))
1053 output_asm_insn (\"cmn\\t%1, %2\", operands);
1054 switch (get_attr_length (insn))
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%=:\";
1061 [(set (attr "far_jump")
1063 (eq_attr "length" "8")
1064 (const_string "yes")
1065 (const_string "no")))
1066 (set (attr "length")
1068 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1069 (le (minus (match_dup 3) (pc)) (const_int 256)))
1072 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1073 (le (minus (match_dup 3) (pc)) (const_int 2048)))
1076 (set_attr "type" "multiple")]
1079 (define_insn "*tbit_cbranch"
1082 (match_operator 0 "equality_operator"
1083 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
1085 (match_operand:SI 2 "const_int_operand" "i"))
1087 (label_ref (match_operand 3 "" ""))
1089 (clobber (match_scratch:SI 4 "=l"))]
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))
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%=:\";
1106 [(set (attr "far_jump")
1108 (eq_attr "length" "8")
1109 (const_string "yes")
1110 (const_string "no")))
1111 (set (attr "length")
1113 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1114 (le (minus (match_dup 3) (pc)) (const_int 256)))
1117 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1118 (le (minus (match_dup 3) (pc)) (const_int 2048)))
1121 (set_attr "type" "multiple")]
1124 (define_insn "*tlobits_cbranch"
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")
1132 (label_ref (match_operand 3 "" ""))
1134 (clobber (match_scratch:SI 4 "=l"))]
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))
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%=:\";
1151 [(set (attr "far_jump")
1153 (eq_attr "length" "8")
1154 (const_string "yes")
1155 (const_string "no")))
1156 (set (attr "length")
1158 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1159 (le (minus (match_dup 3) (pc)) (const_int 256)))
1162 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
1163 (le (minus (match_dup 3) (pc)) (const_int 2048)))
1166 (set_attr "type" "multiple")]
1169 (define_insn "*tstsi3_cbranch"
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"))
1176 (label_ref (match_operand 2 "" ""))
1181 output_asm_insn (\"tst\\t%0, %1\", operands);
1182 switch (get_attr_length (insn))
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%=:\";
1189 [(set (attr "far_jump")
1191 (eq_attr "length" "8")
1192 (const_string "yes")
1193 (const_string "no")))
1194 (set (attr "length")
1196 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
1197 (le (minus (match_dup 2) (pc)) (const_int 256)))
1200 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
1201 (le (minus (match_dup 2) (pc)) (const_int 2048)))
1204 (set_attr "type" "multiple")]
1207 (define_insn "*cbranchne_decr1"
1209 (if_then_else (match_operator 3 "equality_operator"
1210 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
1212 (label_ref (match_operand 4 "" ""))
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"))]
1221 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
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)
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);
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);
1244 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
1247 output_asm_insn (\"b%d0\\t%l1\", cond);
1250 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
1251 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
1253 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
1254 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
1258 [(set (attr "far_jump")
1260 (ior (and (eq (symbol_ref ("which_alternative"))
1262 (eq_attr "length" "8"))
1263 (eq_attr "length" "10"))
1264 (const_string "yes")
1265 (const_string "no")))
1266 (set_attr_alternative "length"
1270 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
1271 (le (minus (match_dup 4) (pc)) (const_int 256)))
1274 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
1275 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1280 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
1281 (le (minus (match_dup 4) (pc)) (const_int 256)))
1284 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
1285 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1290 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
1291 (le (minus (match_dup 4) (pc)) (const_int 256)))
1294 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
1295 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1300 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
1301 (le (minus (match_dup 4) (pc)) (const_int 256)))
1304 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
1305 (le (minus (match_dup 4) (pc)) (const_int 2048)))
1308 (set_attr "type" "multiple")]
1311 (define_insn "*addsi3_cbranch"
1314 (match_operator 4 "arm_comparison_operator"
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"))
1319 (label_ref (match_operand 5 "" ""))
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"))]
1326 && (GET_CODE (operands[4]) == EQ
1327 || GET_CODE (operands[4]) == NE
1328 || GET_CODE (operands[4]) == GE
1329 || GET_CODE (operands[4]) == LT)"
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);
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))
1352 return \"b%d4\\t%l5\";
1354 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
1356 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
1360 [(set (attr "far_jump")
1362 (ior (and (lt (symbol_ref ("which_alternative"))
1364 (eq_attr "length" "8"))
1365 (eq_attr "length" "10"))
1366 (const_string "yes")
1367 (const_string "no")))
1368 (set (attr "length")
1370 (lt (symbol_ref ("which_alternative"))
1373 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
1374 (le (minus (match_dup 5) (pc)) (const_int 256)))
1377 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
1378 (le (minus (match_dup 5) (pc)) (const_int 2048)))
1382 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
1383 (le (minus (match_dup 5) (pc)) (const_int 256)))
1386 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
1387 (le (minus (match_dup 5) (pc)) (const_int 2048)))
1390 (set_attr "type" "multiple")]
1393 (define_insn "*addsi3_cbranch_scratch"
1396 (match_operator 3 "arm_comparison_operator"
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"))
1401 (label_ref (match_operand 4 "" ""))
1403 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
1405 && (GET_CODE (operands[3]) == EQ
1406 || GET_CODE (operands[3]) == NE
1407 || GET_CODE (operands[3]) == GE
1408 || GET_CODE (operands[3]) == LT)"
1411 switch (which_alternative)
1414 output_asm_insn (\"cmp\t%1, #%n2\", operands);
1417 output_asm_insn (\"cmn\t%1, %2\", operands);
1420 if (INTVAL (operands[2]) < 0)
1421 output_asm_insn (\"sub\t%0, %1, %2\", operands);
1423 output_asm_insn (\"add\t%0, %1, %2\", operands);
1426 if (INTVAL (operands[2]) < 0)
1427 output_asm_insn (\"sub\t%0, %0, %2\", operands);
1429 output_asm_insn (\"add\t%0, %0, %2\", operands);
1433 switch (get_attr_length (insn))
1436 return \"b%d3\\t%l4\";
1438 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
1440 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
1444 [(set (attr "far_jump")
1446 (eq_attr "length" "8")
1447 (const_string "yes")
1448 (const_string "no")))
1449 (set (attr "length")
1451 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
1452 (le (minus (match_dup 4) (pc)) (const_int 256)))
1455 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
1456 (le (minus (match_dup 4) (pc)) (const_int 2048)))
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")
1466 (clobber (match_scratch:SI 1 "=l"))]
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"
1476 [(set (match_operand:SI 0 "s_register_operand" "")
1477 (eq:SI (match_operand:SI 1 "s_register_operand" "")
1479 (clobber (match_dup:SI 2))])]
1481 "operands[2] = gen_reg_rtx (SImode);"
1484 (define_expand "cstoresi_ne0_thumb1"
1486 [(set (match_operand:SI 0 "s_register_operand" "")
1487 (ne:SI (match_operand:SI 1 "s_register_operand" "")
1489 (clobber (match_dup:SI 2))])]
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")
1498 (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
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")
1511 (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
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"))))]
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")))]
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"))))]
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"
1559 (label_ref (match_operand 0 "" "")))]
1562 if (get_attr_length (insn) == 2)
1564 return \"bl\\t%l0\\t%@ far jump\";
1566 [(set (attr "far_jump")
1568 (eq_attr "length" "4")
1569 (const_string "yes")
1570 (const_string "no")))
1571 (set (attr "length")
1573 (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
1574 (le (minus (match_dup 0) (pc)) (const_int 2048)))
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)"
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)"
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\";
1606 return \"bl\\t%__interwork_r11_call_via_%0\";
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"
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"
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\";
1639 return \"bl\\t%__interwork_r11_call_via_%1\";
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))]
1650 && GET_CODE (operands[0]) == SYMBOL_REF
1651 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
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))]
1664 && GET_CODE (operands[1]) == SYMBOL_REF
1665 && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
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 "" "")]
1679 rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
1680 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
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]*/));
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))])]
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"
1706 (match_operand:SI 0 "register_operand" "l*r"))]
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)]
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)]
1727 return thumb1_unexpanded_epilogue ();
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)]
1742 making_const_table = TRUE;
1743 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
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)]
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);
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 "" "")))])]
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));
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 "" "")))]
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")]
1796 (clobber (match_scratch:SI 1 "=&l"))]
1799 "&& reload_completed"
1803 thumb_set_return_address (operands[0], operands[1]);
1806 [(set_attr "type" "mov_reg")]