Annotation of src/external/gpl3/gcc.old/dist/gcc/config/arm/arm.md, Revision 1.7
1.1 mrg 1: ;;- Machine description for ARM for GNU compiler
1.7 ! mrg 2: ;; Copyright (C) 1991-2016 Free Software Foundation, Inc.
1.1 mrg 3: ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4: ;; and Martin Simmons (@harleqn.co.uk).
5: ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
6:
7: ;; This file is part of GCC.
8:
9: ;; GCC is free software; you can redistribute it and/or modify it
10: ;; under the terms of the GNU General Public License as published
11: ;; by the Free Software Foundation; either version 3, or (at your
12: ;; option) any later version.
13:
14: ;; GCC is distributed in the hope that it will be useful, but WITHOUT
15: ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16: ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17: ;; License for more details.
18:
19: ;; You should have received a copy of the GNU General Public License
20: ;; along with GCC; see the file COPYING3. If not see
21: ;; <http://www.gnu.org/licenses/>.
22:
23: ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
24:
25:
26: ;;---------------------------------------------------------------------------
27: ;; Constants
28:
1.3 mrg 29: ;; Register numbers -- All machine registers should be defined here
1.1 mrg 30: (define_constants
1.3 mrg 31: [(R0_REGNUM 0) ; First CORE register
32: (R1_REGNUM 1) ; Second CORE register
33: (IP_REGNUM 12) ; Scratch register
34: (SP_REGNUM 13) ; Stack pointer
35: (LR_REGNUM 14) ; Return address register
36: (PC_REGNUM 15) ; Program counter
37: (LAST_ARM_REGNUM 15) ;
38: (CC_REGNUM 100) ; Condition code pseudo register
39: (VFPCC_REGNUM 101) ; VFP Condition code pseudo register
1.1 mrg 40: ]
41: )
42: ;; 3rd operand to select_dominance_cc_mode
43: (define_constants
44: [(DOM_CC_X_AND_Y 0)
45: (DOM_CC_NX_OR_Y 1)
46: (DOM_CC_X_OR_Y 2)
47: ]
48: )
1.3 mrg 49: ;; conditional compare combination
1.1 mrg 50: (define_constants
1.3 mrg 51: [(CMP_CMP 0)
52: (CMN_CMP 1)
53: (CMP_CMN 2)
54: (CMN_CMN 3)
55: (NUM_OF_COND_CMP 4)
1.1 mrg 56: ]
57: )
58:
59:
60: ;;---------------------------------------------------------------------------
61: ;; Attributes
62:
1.3 mrg 63: ;; Processor type. This is created automatically from arm-cores.def.
64: (include "arm-tune.md")
65:
1.5 mrg 66: ;; Instruction classification types
67: (include "types.md")
68:
1.1 mrg 69: ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
70: ; generating ARM code. This is used to control the length of some insn
71: ; patterns that share the same RTL in both ARM and Thumb code.
1.7 ! mrg 72: (define_attr "is_thumb" "yes,no"
! 73: (const (if_then_else (symbol_ref "TARGET_THUMB")
! 74: (const_string "yes") (const_string "no"))))
1.1 mrg 75:
1.3 mrg 76: ; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
77: (define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
1.1 mrg 78:
1.3 mrg 79: ; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
1.7 ! mrg 80: (define_attr "is_thumb1" "yes,no"
! 81: (const (if_then_else (symbol_ref "TARGET_THUMB1")
! 82: (const_string "yes") (const_string "no"))))
1.1 mrg 83:
1.5 mrg 84: ; We use this attribute to disable alternatives that can produce 32-bit
85: ; instructions inside an IT-block in Thumb2 state. ARMv8 deprecates IT blocks
86: ; that contain 32-bit instructions.
87: (define_attr "enabled_for_depr_it" "no,yes" (const_string "yes"))
88:
89: ; This attribute is used to disable a predicated alternative when we have
90: ; arm_restrict_it.
91: (define_attr "predicable_short_it" "no,yes" (const_string "yes"))
92:
1.1 mrg 93: ;; Operand number of an input operand that is shifted. Zero if the
94: ;; given instruction does not shift one of its input operands.
95: (define_attr "shift" "" (const_int 0))
96:
1.5 mrg 97: ;; [For compatibility with AArch64 in pipeline models]
98: ;; Attribute that specifies whether or not the instruction touches fp
99: ;; registers.
100: (define_attr "fp" "no,yes" (const_string "no"))
101:
1.1 mrg 102: ; Floating Point Unit. If we only have floating point emulation, then there
103: ; is no point in scheduling the floating point insns. (Well, for best
104: ; performance we should try and group them together).
1.3 mrg 105: (define_attr "fpu" "none,vfp"
1.1 mrg 106: (const (symbol_ref "arm_fpu_attr")))
107:
1.7 ! mrg 108: ; Predicated means that the insn form is conditionally executed based on a
! 109: ; predicate. We default to 'no' because no Thumb patterns match this rule
! 110: ; and not all ARM insns do.
1.5 mrg 111: (define_attr "predicated" "yes,no" (const_string "no"))
112:
1.1 mrg 113: ; LENGTH of an instruction (in bytes)
1.3 mrg 114: (define_attr "length" ""
115: (const_int 4))
116:
117: ; The architecture which supports the instruction (or alternative).
118: ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
119: ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6"
120: ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
121: ; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is
122: ; used to compute attribute "enabled", use type "any" to enable an
123: ; alternative in all cases.
1.5 mrg 124: (define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3"
1.3 mrg 125: (const_string "any"))
126:
127: (define_attr "arch_enabled" "no,yes"
128: (cond [(eq_attr "arch" "any")
129: (const_string "yes")
130:
131: (and (eq_attr "arch" "a")
132: (match_test "TARGET_ARM"))
133: (const_string "yes")
134:
135: (and (eq_attr "arch" "t")
136: (match_test "TARGET_THUMB"))
137: (const_string "yes")
138:
139: (and (eq_attr "arch" "t1")
140: (match_test "TARGET_THUMB1"))
141: (const_string "yes")
142:
143: (and (eq_attr "arch" "t2")
144: (match_test "TARGET_THUMB2"))
145: (const_string "yes")
146:
147: (and (eq_attr "arch" "32")
148: (match_test "TARGET_32BIT"))
149: (const_string "yes")
150:
151: (and (eq_attr "arch" "v6")
152: (match_test "TARGET_32BIT && arm_arch6"))
153: (const_string "yes")
154:
155: (and (eq_attr "arch" "nov6")
156: (match_test "TARGET_32BIT && !arm_arch6"))
157: (const_string "yes")
158:
159: (and (eq_attr "arch" "v6t2")
160: (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
161: (const_string "yes")
162:
1.5 mrg 163: (and (eq_attr "arch" "avoid_neon_for_64bits")
164: (match_test "TARGET_NEON")
165: (not (match_test "TARGET_PREFER_NEON_64BITS")))
1.3 mrg 166: (const_string "yes")
167:
1.5 mrg 168: (and (eq_attr "arch" "neon_for_64bits")
169: (match_test "TARGET_NEON")
170: (match_test "TARGET_PREFER_NEON_64BITS"))
1.3 mrg 171: (const_string "yes")
172:
1.5 mrg 173: (and (eq_attr "arch" "iwmmxt2")
174: (match_test "TARGET_REALLY_IWMMXT2"))
1.3 mrg 175: (const_string "yes")
176:
1.5 mrg 177: (and (eq_attr "arch" "armv6_or_vfpv3")
178: (match_test "arm_arch6 || TARGET_VFP3"))
1.3 mrg 179: (const_string "yes")
1.5 mrg 180: ]
1.3 mrg 181:
182: (const_string "no")))
183:
184: (define_attr "opt" "any,speed,size"
185: (const_string "any"))
186:
187: (define_attr "opt_enabled" "no,yes"
188: (cond [(eq_attr "opt" "any")
189: (const_string "yes")
190:
191: (and (eq_attr "opt" "speed")
192: (match_test "optimize_function_for_speed_p (cfun)"))
193: (const_string "yes")
194:
195: (and (eq_attr "opt" "size")
196: (match_test "optimize_function_for_size_p (cfun)"))
197: (const_string "yes")]
198: (const_string "no")))
199:
1.5 mrg 200: (define_attr "use_literal_pool" "no,yes"
201: (cond [(and (eq_attr "type" "f_loads,f_loadd")
202: (match_test "CONSTANT_P (operands[1])"))
203: (const_string "yes")]
204: (const_string "no")))
1.3 mrg 205:
206: ; Enable all alternatives that are both arch_enabled and insn_enabled.
1.5 mrg 207: ; FIXME:: opt_enabled has been temporarily removed till the time we have
208: ; an attribute that allows the use of such alternatives.
209: ; This depends on caching of speed_p, size_p on a per
210: ; alternative basis. The problem is that the enabled attribute
211: ; cannot depend on any state that is not cached or is not constant
212: ; for a compilation unit. We probably need a generic "hot/cold"
213: ; alternative which if implemented can help with this. We disable this
214: ; until such a time as this is implemented and / or the improvements or
215: ; regressions with removing this attribute are double checked.
216: ; See ashldi3_neon and <shift>di3_neon in neon.md.
217:
1.3 mrg 218: (define_attr "enabled" "no,yes"
1.5 mrg 219: (cond [(and (eq_attr "predicable_short_it" "no")
220: (and (eq_attr "predicated" "yes")
221: (match_test "arm_restrict_it")))
1.3 mrg 222: (const_string "no")
223:
1.5 mrg 224: (and (eq_attr "enabled_for_depr_it" "no")
225: (match_test "arm_restrict_it"))
226: (const_string "no")
227:
228: (and (eq_attr "use_literal_pool" "yes")
229: (match_test "arm_disable_literal_pool"))
1.3 mrg 230: (const_string "no")
231:
1.5 mrg 232: (eq_attr "arch_enabled" "no")
1.3 mrg 233: (const_string "no")]
234: (const_string "yes")))
1.1 mrg 235:
236: ; POOL_RANGE is how far away from a constant pool entry that this insn
237: ; can be placed. If the distance is zero, then this insn will never
238: ; reference the pool.
1.3 mrg 239: ; Note that for Thumb constant pools the PC value is rounded down to the
240: ; nearest multiple of four. Therefore, THUMB2_POOL_RANGE (and POOL_RANGE for
241: ; Thumb insns) should be set to <max_range> - 2.
1.1 mrg 242: ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
1.3 mrg 243: ; before its address. It is set to <max_range> - (8 + <data_size>).
244: (define_attr "arm_pool_range" "" (const_int 0))
245: (define_attr "thumb2_pool_range" "" (const_int 0))
246: (define_attr "arm_neg_pool_range" "" (const_int 0))
247: (define_attr "thumb2_neg_pool_range" "" (const_int 0))
248:
249: (define_attr "pool_range" ""
250: (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
251: (attr "arm_pool_range")))
252: (define_attr "neg_pool_range" ""
253: (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
254: (attr "arm_neg_pool_range")))
1.1 mrg 255:
256: ; An assembler sequence may clobber the condition codes without us knowing.
257: ; If such an insn references the pool, then we have no way of knowing how,
258: ; so use the most conservative value for pool_range.
259: (define_asm_attributes
260: [(set_attr "conds" "clob")
261: (set_attr "length" "4")
262: (set_attr "pool_range" "250")])
263:
264: ; Load scheduling, set from the arm_ld_sched variable
1.3 mrg 265: ; initialized by arm_option_override()
1.1 mrg 266: (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
267:
268: ; condition codes: this one is used by final_prescan_insn to speed up
269: ; conditionalizing instructions. It saves having to scan the rtl to see if
270: ; it uses or alters the condition codes.
271: ;
272: ; USE means that the condition codes are used by the insn in the process of
273: ; outputting code, this means (at present) that we can't use the insn in
274: ; inlined branches
275: ;
276: ; SET means that the purpose of the insn is to set the condition codes in a
277: ; well defined manner.
278: ;
279: ; CLOB means that the condition codes are altered in an undefined manner, if
280: ; they are altered at all
281: ;
1.3 mrg 282: ; UNCONDITIONAL means the instruction can not be conditionally executed and
283: ; that the instruction does not use or alter the condition codes.
1.1 mrg 284: ;
1.3 mrg 285: ; NOCOND means that the instruction does not use or alter the condition
286: ; codes but can be converted into a conditionally exectuted instruction.
1.1 mrg 287:
288: (define_attr "conds" "use,set,clob,unconditional,nocond"
1.3 mrg 289: (if_then_else
290: (ior (eq_attr "is_thumb1" "yes")
291: (eq_attr "type" "call"))
1.1 mrg 292: (const_string "clob")
1.5 mrg 293: (if_then_else (eq_attr "is_neon_type" "no")
294: (const_string "nocond")
295: (const_string "unconditional"))))
1.1 mrg 296:
297: ; Predicable means that the insn can be conditionally executed based on
298: ; an automatically added predicate (additional patterns are generated by
299: ; gen...). We default to 'no' because no Thumb patterns match this rule
300: ; and not all ARM patterns do.
301: (define_attr "predicable" "no,yes" (const_string "no"))
302:
303: ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
304: ; have one. Later ones, such as StrongARM, have write-back caches, so don't
305: ; suffer blockages enough to warrant modelling this (and it can adversely
306: ; affect the schedule).
307: (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
308:
309: ; WRITE_CONFLICT implies that a read following an unrelated write is likely
310: ; to stall the processor. Used with model_wbuf above.
311: (define_attr "write_conflict" "no,yes"
312: (if_then_else (eq_attr "type"
1.3 mrg 313: "block,call,load1")
1.1 mrg 314: (const_string "yes")
315: (const_string "no")))
316:
317: ; Classify the insns into those that take one cycle and those that take more
318: ; than one on the main cpu execution unit.
319: (define_attr "core_cycles" "single,multi"
320: (if_then_else (eq_attr "type"
1.5 mrg 321: "adc_imm, adc_reg, adcs_imm, adcs_reg, adr, alu_ext, alu_imm, alu_sreg,\
322: alu_shift_imm, alu_shift_reg, alu_dsp_reg, alus_ext, alus_imm, alus_sreg,\
323: alus_shift_imm, alus_shift_reg, bfm, csel, rev, logic_imm, logic_reg,\
324: logic_shift_imm, logic_shift_reg, logics_imm, logics_reg,\
325: logics_shift_imm, logics_shift_reg, extend, shift_imm, float, fcsel,\
326: wmmx_wor, wmmx_wxor, wmmx_wand, wmmx_wandn, wmmx_wmov, wmmx_tmcrr,\
327: wmmx_tmrrc, wmmx_wldr, wmmx_wstr, wmmx_tmcr, wmmx_tmrc, wmmx_wadd,\
328: wmmx_wsub, wmmx_wmul, wmmx_wmac, wmmx_wavg2, wmmx_tinsr, wmmx_textrm,\
329: wmmx_wshufh, wmmx_wcmpeq, wmmx_wcmpgt, wmmx_wmax, wmmx_wmin, wmmx_wpack,\
330: wmmx_wunpckih, wmmx_wunpckil, wmmx_wunpckeh, wmmx_wunpckel, wmmx_wror,\
331: wmmx_wsra, wmmx_wsrl, wmmx_wsll, wmmx_wmadd, wmmx_tmia, wmmx_tmiaph,\
332: wmmx_tmiaxy, wmmx_tbcst, wmmx_tmovmsk, wmmx_wacc, wmmx_waligni,\
333: wmmx_walignr, wmmx_tandc, wmmx_textrc, wmmx_torc, wmmx_torvsc, wmmx_wsad,\
334: wmmx_wabs, wmmx_wabsdiff, wmmx_waddsubhx, wmmx_wsubaddhx, wmmx_wavg4,\
335: wmmx_wmulw, wmmx_wqmulm, wmmx_wqmulwm, wmmx_waddbhus, wmmx_wqmiaxy,\
336: wmmx_wmiaxy, wmmx_wmiawxy, wmmx_wmerge")
1.1 mrg 337: (const_string "single")
338: (const_string "multi")))
339:
340: ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
341: ;; distant label. Only applicable to Thumb code.
342: (define_attr "far_jump" "yes,no" (const_string "no"))
343:
344:
345: ;; The number of machine instructions this pattern expands to.
346: ;; Used for Thumb-2 conditional execution.
347: (define_attr "ce_count" "" (const_int 1))
348:
349: ;;---------------------------------------------------------------------------
1.3 mrg 350: ;; Unspecs
351:
352: (include "unspecs.md")
353:
354: ;;---------------------------------------------------------------------------
1.1 mrg 355: ;; Mode iterators
356:
1.3 mrg 357: (include "iterators.md")
1.1 mrg 358:
359: ;;---------------------------------------------------------------------------
360: ;; Predicates
361:
362: (include "predicates.md")
363: (include "constraints.md")
364:
365: ;;---------------------------------------------------------------------------
366: ;; Pipeline descriptions
367:
368: (define_attr "tune_cortexr4" "yes,no"
369: (const (if_then_else
1.3 mrg 370: (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
1.1 mrg 371: (const_string "yes")
372: (const_string "no"))))
373:
374: ;; True if the generic scheduling description should be used.
375:
376: (define_attr "generic_sched" "yes,no"
1.3 mrg 377: (const (if_then_else
1.5 mrg 378: (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,\
379: arm926ejs,arm1020e,arm1026ejs,arm1136js,\
380: arm1136jfs,cortexa5,cortexa7,cortexa8,\
381: cortexa9,cortexa12,cortexa15,cortexa17,\
382: cortexa53,cortexa57,cortexm4,cortexm7,\
1.7 ! mrg 383: exynosm1,marvell_pj4,xgene1")
1.3 mrg 384: (eq_attr "tune_cortexr4" "yes"))
1.1 mrg 385: (const_string "no")
386: (const_string "yes"))))
387:
388: (define_attr "generic_vfp" "yes,no"
389: (const (if_then_else
390: (and (eq_attr "fpu" "vfp")
1.5 mrg 391: (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa7,\
392: cortexa8,cortexa9,cortexa53,cortexm4,\
393: cortexm7,marvell_pj4,xgene1")
1.1 mrg 394: (eq_attr "tune_cortexr4" "no"))
395: (const_string "yes")
396: (const_string "no"))))
397:
1.3 mrg 398: (include "marvell-f-iwmmxt.md")
1.1 mrg 399: (include "arm-generic.md")
400: (include "arm926ejs.md")
401: (include "arm1020e.md")
402: (include "arm1026ejs.md")
403: (include "arm1136jfs.md")
1.3 mrg 404: (include "fa526.md")
405: (include "fa606te.md")
406: (include "fa626te.md")
407: (include "fmp626.md")
408: (include "fa726te.md")
409: (include "cortex-a5.md")
410: (include "cortex-a7.md")
1.1 mrg 411: (include "cortex-a8.md")
412: (include "cortex-a9.md")
1.3 mrg 413: (include "cortex-a15.md")
1.5 mrg 414: (include "cortex-a17.md")
415: (include "cortex-a53.md")
416: (include "cortex-a57.md")
1.1 mrg 417: (include "cortex-r4.md")
418: (include "cortex-r4f.md")
1.5 mrg 419: (include "cortex-m7.md")
1.3 mrg 420: (include "cortex-m4.md")
421: (include "cortex-m4-fpu.md")
1.7 ! mrg 422: (include "exynos-m1.md")
1.1 mrg 423: (include "vfp11.md")
1.3 mrg 424: (include "marvell-pj4.md")
1.5 mrg 425: (include "xgene1.md")
1.1 mrg 426:
427:
428: ;;---------------------------------------------------------------------------
429: ;; Insn patterns
430: ;;
431: ;; Addition insns.
432:
433: ;; Note: For DImode insns, there is normally no reason why operands should
434: ;; not be in the same register, what we don't want is for something being
435: ;; written to partially overlap something that is an input.
436:
437: (define_expand "adddi3"
438: [(parallel
439: [(set (match_operand:DI 0 "s_register_operand" "")
440: (plus:DI (match_operand:DI 1 "s_register_operand" "")
1.3 mrg 441: (match_operand:DI 2 "arm_adddi_operand" "")))
1.1 mrg 442: (clobber (reg:CC CC_REGNUM))])]
443: "TARGET_EITHER"
444: "
445: if (TARGET_THUMB1)
446: {
1.3 mrg 447: if (!REG_P (operands[1]))
1.1 mrg 448: operands[1] = force_reg (DImode, operands[1]);
1.3 mrg 449: if (!REG_P (operands[2]))
1.1 mrg 450: operands[2] = force_reg (DImode, operands[2]);
451: }
452: "
453: )
454:
455: (define_insn_and_split "*arm_adddi3"
1.3 mrg 456: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r,&r,&r")
457: (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0, r, 0, r")
458: (match_operand:DI 2 "arm_adddi_operand" "r, 0, r, Dd, Dd")))
1.1 mrg 459: (clobber (reg:CC CC_REGNUM))]
1.3 mrg 460: "TARGET_32BIT && !TARGET_NEON"
1.1 mrg 461: "#"
1.3 mrg 462: "TARGET_32BIT && reload_completed
463: && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
1.1 mrg 464: [(parallel [(set (reg:CC_C CC_REGNUM)
465: (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
466: (match_dup 1)))
467: (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
1.3 mrg 468: (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
469: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1.1 mrg 470: "
471: {
472: operands[3] = gen_highpart (SImode, operands[0]);
473: operands[0] = gen_lowpart (SImode, operands[0]);
474: operands[4] = gen_highpart (SImode, operands[1]);
475: operands[1] = gen_lowpart (SImode, operands[1]);
1.3 mrg 476: operands[5] = gen_highpart_mode (SImode, DImode, operands[2]);
1.1 mrg 477: operands[2] = gen_lowpart (SImode, operands[2]);
478: }"
479: [(set_attr "conds" "clob")
1.5 mrg 480: (set_attr "length" "8")
481: (set_attr "type" "multiple")]
1.1 mrg 482: )
483:
484: (define_insn_and_split "*adddi_sesidi_di"
485: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
486: (plus:DI (sign_extend:DI
487: (match_operand:SI 2 "s_register_operand" "r,r"))
488: (match_operand:DI 1 "s_register_operand" "0,r")))
489: (clobber (reg:CC CC_REGNUM))]
1.3 mrg 490: "TARGET_32BIT"
1.1 mrg 491: "#"
492: "TARGET_32BIT && reload_completed"
493: [(parallel [(set (reg:CC_C CC_REGNUM)
494: (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
495: (match_dup 1)))
496: (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
1.3 mrg 497: (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
1.1 mrg 498: (const_int 31))
1.3 mrg 499: (match_dup 4))
500: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1.1 mrg 501: "
502: {
503: operands[3] = gen_highpart (SImode, operands[0]);
504: operands[0] = gen_lowpart (SImode, operands[0]);
505: operands[4] = gen_highpart (SImode, operands[1]);
506: operands[1] = gen_lowpart (SImode, operands[1]);
507: operands[2] = gen_lowpart (SImode, operands[2]);
508: }"
509: [(set_attr "conds" "clob")
1.5 mrg 510: (set_attr "length" "8")
511: (set_attr "type" "multiple")]
1.1 mrg 512: )
513:
514: (define_insn_and_split "*adddi_zesidi_di"
515: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
516: (plus:DI (zero_extend:DI
517: (match_operand:SI 2 "s_register_operand" "r,r"))
518: (match_operand:DI 1 "s_register_operand" "0,r")))
519: (clobber (reg:CC CC_REGNUM))]
1.3 mrg 520: "TARGET_32BIT"
1.1 mrg 521: "#"
522: "TARGET_32BIT && reload_completed"
523: [(parallel [(set (reg:CC_C CC_REGNUM)
524: (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
525: (match_dup 1)))
526: (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
1.3 mrg 527: (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
528: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1.1 mrg 529: "
530: {
531: operands[3] = gen_highpart (SImode, operands[0]);
532: operands[0] = gen_lowpart (SImode, operands[0]);
533: operands[4] = gen_highpart (SImode, operands[1]);
534: operands[1] = gen_lowpart (SImode, operands[1]);
535: operands[2] = gen_lowpart (SImode, operands[2]);
536: }"
537: [(set_attr "conds" "clob")
1.5 mrg 538: (set_attr "length" "8")
539: (set_attr "type" "multiple")]
1.1 mrg 540: )
541:
542: (define_expand "addsi3"
543: [(set (match_operand:SI 0 "s_register_operand" "")
544: (plus:SI (match_operand:SI 1 "s_register_operand" "")
545: (match_operand:SI 2 "reg_or_int_operand" "")))]
546: "TARGET_EITHER"
547: "
1.3 mrg 548: if (TARGET_32BIT && CONST_INT_P (operands[2]))
1.1 mrg 549: {
550: arm_split_constant (PLUS, SImode, NULL_RTX,
551: INTVAL (operands[2]), operands[0], operands[1],
552: optimize && can_create_pseudo_p ());
553: DONE;
554: }
555: "
556: )
557:
558: ; If there is a scratch available, this will be faster than synthesizing the
559: ; addition.
560: (define_peephole2
561: [(match_scratch:SI 3 "r")
562: (set (match_operand:SI 0 "arm_general_register_operand" "")
563: (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
564: (match_operand:SI 2 "const_int_operand" "")))]
565: "TARGET_32BIT &&
566: !(const_ok_for_arm (INTVAL (operands[2]))
567: || const_ok_for_arm (-INTVAL (operands[2])))
568: && const_ok_for_arm (~INTVAL (operands[2]))"
569: [(set (match_dup 3) (match_dup 2))
570: (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
571: ""
572: )
573:
574: ;; The r/r/k alternative is required when reloading the address
575: ;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will
576: ;; put the duplicated register first, and not try the commutative version.
577: (define_insn_and_split "*arm_addsi3"
1.6 mrg 578: [(set (match_operand:SI 0 "s_register_operand" "=rk,l,l ,l ,r ,k ,r,k ,r ,k ,r ,k,k,r ,k ,r")
579: (plus:SI (match_operand:SI 1 "s_register_operand" "%0 ,l,0 ,l ,rk,k ,r,r ,rk,k ,rk,k,r,rk,k ,rk")
580: (match_operand:SI 2 "reg_or_int_operand" "rk ,l,Py,Pd,rI,rI,k,rI,Pj,Pj,L ,L,L,PJ,PJ,?n")))]
1.1 mrg 581: "TARGET_32BIT"
582: "@
1.3 mrg 583: add%?\\t%0, %0, %2
1.1 mrg 584: add%?\\t%0, %1, %2
585: add%?\\t%0, %1, %2
1.5 mrg 586: add%?\\t%0, %1, %2
587: add%?\\t%0, %1, %2
588: add%?\\t%0, %1, %2
1.1 mrg 589: add%?\\t%0, %2, %1
1.6 mrg 590: add%?\\t%0, %1, %2
1.3 mrg 591: addw%?\\t%0, %1, %2
592: addw%?\\t%0, %1, %2
1.1 mrg 593: sub%?\\t%0, %1, #%n2
594: sub%?\\t%0, %1, #%n2
1.3 mrg 595: sub%?\\t%0, %1, #%n2
596: subw%?\\t%0, %1, #%n2
597: subw%?\\t%0, %1, #%n2
1.1 mrg 598: #"
599: "TARGET_32BIT
1.3 mrg 600: && CONST_INT_P (operands[2])
601: && !const_ok_for_op (INTVAL (operands[2]), PLUS)
1.1 mrg 602: && (reload_completed || !arm_eliminable_register (operands[1]))"
603: [(clobber (const_int 0))]
604: "
605: arm_split_constant (PLUS, SImode, curr_insn,
606: INTVAL (operands[2]), operands[0],
607: operands[1], 0);
608: DONE;
609: "
1.6 mrg 610: [(set_attr "length" "2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,16")
1.3 mrg 611: (set_attr "predicable" "yes")
1.6 mrg 612: (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no")
613: (set_attr "arch" "t2,t2,t2,t2,*,*,*,a,t2,t2,*,*,a,t2,t2,*")
1.3 mrg 614: (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
1.5 mrg 615: (const_string "alu_imm")
616: (const_string "alu_sreg")))
1.3 mrg 617: ]
1.1 mrg 618: )
619:
1.3 mrg 620: (define_insn "addsi3_compare0"
1.1 mrg 621: [(set (reg:CC_NOOV CC_REGNUM)
622: (compare:CC_NOOV
1.3 mrg 623: (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
624: (match_operand:SI 2 "arm_add_operand" "I,L,r"))
1.1 mrg 625: (const_int 0)))
1.3 mrg 626: (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1.1 mrg 627: (plus:SI (match_dup 1) (match_dup 2)))]
1.3 mrg 628: "TARGET_ARM"
1.1 mrg 629: "@
1.7 ! mrg 630: adds%?\\t%0, %1, %2
! 631: subs%?\\t%0, %1, #%n2
! 632: adds%?\\t%0, %1, %2"
1.3 mrg 633: [(set_attr "conds" "set")
1.5 mrg 634: (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
1.1 mrg 635: )
636:
637: (define_insn "*addsi3_compare0_scratch"
638: [(set (reg:CC_NOOV CC_REGNUM)
639: (compare:CC_NOOV
1.3 mrg 640: (plus:SI (match_operand:SI 0 "s_register_operand" "r, r, r")
641: (match_operand:SI 1 "arm_add_operand" "I,L, r"))
1.1 mrg 642: (const_int 0)))]
1.3 mrg 643: "TARGET_ARM"
1.1 mrg 644: "@
645: cmn%?\\t%0, %1
1.3 mrg 646: cmp%?\\t%0, #%n1
647: cmn%?\\t%0, %1"
648: [(set_attr "conds" "set")
649: (set_attr "predicable" "yes")
1.5 mrg 650: (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
1.1 mrg 651: )
652:
653: (define_insn "*compare_negsi_si"
654: [(set (reg:CC_Z CC_REGNUM)
655: (compare:CC_Z
1.5 mrg 656: (neg:SI (match_operand:SI 0 "s_register_operand" "l,r"))
657: (match_operand:SI 1 "s_register_operand" "l,r")))]
1.1 mrg 658: "TARGET_32BIT"
659: "cmn%?\\t%1, %0"
1.3 mrg 660: [(set_attr "conds" "set")
1.5 mrg 661: (set_attr "predicable" "yes")
662: (set_attr "arch" "t2,*")
663: (set_attr "length" "2,4")
664: (set_attr "predicable_short_it" "yes,no")
665: (set_attr "type" "alus_sreg")]
1.1 mrg 666: )
667:
668: ;; This is the canonicalization of addsi3_compare0_for_combiner when the
669: ;; addend is a constant.
1.5 mrg 670: (define_insn "cmpsi2_addneg"
1.1 mrg 671: [(set (reg:CC CC_REGNUM)
672: (compare:CC
673: (match_operand:SI 1 "s_register_operand" "r,r")
1.3 mrg 674: (match_operand:SI 2 "arm_addimm_operand" "L,I")))
1.1 mrg 675: (set (match_operand:SI 0 "s_register_operand" "=r,r")
676: (plus:SI (match_dup 1)
1.3 mrg 677: (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
1.1 mrg 678: "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
679: "@
1.7 ! mrg 680: adds%?\\t%0, %1, %3
! 681: subs%?\\t%0, %1, #%n3"
1.5 mrg 682: [(set_attr "conds" "set")
683: (set_attr "type" "alus_sreg")]
1.1 mrg 684: )
685:
686: ;; Convert the sequence
687: ;; sub rd, rn, #1
688: ;; cmn rd, #1 (equivalent to cmp rd, #-1)
689: ;; bne dest
690: ;; into
691: ;; subs rd, rn, #1
692: ;; bcs dest ((unsigned)rn >= 1)
693: ;; similarly for the beq variant using bcc.
694: ;; This is a common looping idiom (while (n--))
695: (define_peephole2
696: [(set (match_operand:SI 0 "arm_general_register_operand" "")
697: (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
698: (const_int -1)))
699: (set (match_operand 2 "cc_register" "")
700: (compare (match_dup 0) (const_int -1)))
701: (set (pc)
702: (if_then_else (match_operator 3 "equality_operator"
703: [(match_dup 2) (const_int 0)])
704: (match_operand 4 "" "")
705: (match_operand 5 "" "")))]
706: "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
707: [(parallel[
708: (set (match_dup 2)
709: (compare:CC
710: (match_dup 1) (const_int 1)))
711: (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
712: (set (pc)
713: (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
714: (match_dup 4)
715: (match_dup 5)))]
716: "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
717: operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
718: ? GEU : LTU),
719: VOIDmode,
720: operands[2], const0_rtx);"
721: )
722:
723: ;; The next four insns work because they compare the result with one of
724: ;; the operands, and we know that the use of the condition code is
725: ;; either GEU or LTU, so we can use the carry flag from the addition
726: ;; instead of doing the compare a second time.
727: (define_insn "*addsi3_compare_op1"
728: [(set (reg:CC_C CC_REGNUM)
729: (compare:CC_C
1.3 mrg 730: (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
731: (match_operand:SI 2 "arm_add_operand" "I,L,r"))
1.1 mrg 732: (match_dup 1)))
1.3 mrg 733: (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1.1 mrg 734: (plus:SI (match_dup 1) (match_dup 2)))]
735: "TARGET_32BIT"
736: "@
1.7 ! mrg 737: adds%?\\t%0, %1, %2
! 738: subs%?\\t%0, %1, #%n2
! 739: adds%?\\t%0, %1, %2"
1.3 mrg 740: [(set_attr "conds" "set")
1.5 mrg 741: (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
1.1 mrg 742: )
743:
744: (define_insn "*addsi3_compare_op2"
745: [(set (reg:CC_C CC_REGNUM)
746: (compare:CC_C
1.3 mrg 747: (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
748: (match_operand:SI 2 "arm_add_operand" "I,L,r"))
1.1 mrg 749: (match_dup 2)))
1.3 mrg 750: (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1.1 mrg 751: (plus:SI (match_dup 1) (match_dup 2)))]
752: "TARGET_32BIT"
753: "@
1.7 ! mrg 754: adds%?\\t%0, %1, %2
! 755: subs%?\\t%0, %1, #%n2
! 756: adds%?\\t%0, %1, %2"
1.3 mrg 757: [(set_attr "conds" "set")
1.5 mrg 758: (set_attr "type" "alus_imm,alus_imm,alus_sreg")]
1.1 mrg 759: )
760:
761: (define_insn "*compare_addsi2_op0"
762: [(set (reg:CC_C CC_REGNUM)
1.5 mrg 763: (compare:CC_C
764: (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
765: (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
766: (match_dup 0)))]
1.1 mrg 767: "TARGET_32BIT"
768: "@
1.5 mrg 769: cmp%?\\t%0, #%n1
770: cmn%?\\t%0, %1
1.1 mrg 771: cmn%?\\t%0, %1
1.3 mrg 772: cmp%?\\t%0, #%n1
773: cmn%?\\t%0, %1"
774: [(set_attr "conds" "set")
775: (set_attr "predicable" "yes")
1.5 mrg 776: (set_attr "arch" "t2,t2,*,*,*")
777: (set_attr "predicable_short_it" "yes,yes,no,no,no")
778: (set_attr "length" "2,2,4,4,4")
779: (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
1.1 mrg 780: )
781:
782: (define_insn "*compare_addsi2_op1"
783: [(set (reg:CC_C CC_REGNUM)
1.5 mrg 784: (compare:CC_C
785: (plus:SI (match_operand:SI 0 "s_register_operand" "l,l,r,r,r")
786: (match_operand:SI 1 "arm_add_operand" "Pv,l,I,L,r"))
787: (match_dup 1)))]
1.1 mrg 788: "TARGET_32BIT"
789: "@
1.5 mrg 790: cmp%?\\t%0, #%n1
791: cmn%?\\t%0, %1
1.1 mrg 792: cmn%?\\t%0, %1
1.3 mrg 793: cmp%?\\t%0, #%n1
794: cmn%?\\t%0, %1"
795: [(set_attr "conds" "set")
796: (set_attr "predicable" "yes")
1.5 mrg 797: (set_attr "arch" "t2,t2,*,*,*")
798: (set_attr "predicable_short_it" "yes,yes,no,no,no")
799: (set_attr "length" "2,2,4,4,4")
800: (set_attr "type" "alus_imm,alus_sreg,alus_imm,alus_imm,alus_sreg")]
801: )
1.3 mrg 802:
803: (define_insn "*addsi3_carryin_<optab>"
1.5 mrg 804: [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
805: (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%l,r,r")
806: (match_operand:SI 2 "arm_not_operand" "0,rI,K"))
807: (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
1.3 mrg 808: "TARGET_32BIT"
809: "@
810: adc%?\\t%0, %1, %2
1.5 mrg 811: adc%?\\t%0, %1, %2
1.3 mrg 812: sbc%?\\t%0, %1, #%B2"
1.5 mrg 813: [(set_attr "conds" "use")
814: (set_attr "predicable" "yes")
815: (set_attr "arch" "t2,*,*")
816: (set_attr "length" "4")
817: (set_attr "predicable_short_it" "yes,no,no")
818: (set_attr "type" "adc_reg,adc_reg,adc_imm")]
1.1 mrg 819: )
820:
1.3 mrg 821: (define_insn "*addsi3_carryin_alt2_<optab>"
1.5 mrg 822: [(set (match_operand:SI 0 "s_register_operand" "=l,r,r")
823: (plus:SI (plus:SI (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))
824: (match_operand:SI 1 "s_register_operand" "%l,r,r"))
825: (match_operand:SI 2 "arm_rhs_operand" "l,rI,K")))]
1.1 mrg 826: "TARGET_32BIT"
1.3 mrg 827: "@
828: adc%?\\t%0, %1, %2
1.5 mrg 829: adc%?\\t%0, %1, %2
1.3 mrg 830: sbc%?\\t%0, %1, #%B2"
1.5 mrg 831: [(set_attr "conds" "use")
832: (set_attr "predicable" "yes")
833: (set_attr "arch" "t2,*,*")
834: (set_attr "length" "4")
835: (set_attr "predicable_short_it" "yes,no,no")
836: (set_attr "type" "adc_reg,adc_reg,adc_imm")]
1.1 mrg 837: )
838:
1.3 mrg 839: (define_insn "*addsi3_carryin_shift_<optab>"
1.1 mrg 840: [(set (match_operand:SI 0 "s_register_operand" "=r")
1.3 mrg 841: (plus:SI (plus:SI
842: (match_operator:SI 2 "shift_operator"
843: [(match_operand:SI 3 "s_register_operand" "r")
844: (match_operand:SI 4 "reg_or_int_operand" "rM")])
845: (match_operand:SI 1 "s_register_operand" "r"))
846: (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))]
1.1 mrg 847: "TARGET_32BIT"
848: "adc%?\\t%0, %1, %3%S2"
849: [(set_attr "conds" "use")
1.5 mrg 850: (set_attr "predicable" "yes")
851: (set_attr "predicable_short_it" "no")
1.1 mrg 852: (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1.5 mrg 853: (const_string "alu_shift_imm")
1.1 mrg 854: (const_string "alu_shift_reg")))]
855: )
856:
1.3 mrg 857: (define_insn "*addsi3_carryin_clobercc_<optab>"
1.1 mrg 858: [(set (match_operand:SI 0 "s_register_operand" "=r")
1.3 mrg 859: (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1.1 mrg 860: (match_operand:SI 2 "arm_rhs_operand" "rI"))
1.3 mrg 861: (LTUGEU:SI (reg:<cnb> CC_REGNUM) (const_int 0))))
862: (clobber (reg:CC CC_REGNUM))]
863: "TARGET_32BIT"
1.7 ! mrg 864: "adcs%?\\t%0, %1, %2"
1.5 mrg 865: [(set_attr "conds" "set")
866: (set_attr "type" "adcs_reg")]
1.1 mrg 867: )
868:
1.5 mrg 869: (define_insn "*subsi3_carryin"
1.1 mrg 870: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1.5 mrg 871: (minus:SI (minus:SI (match_operand:SI 1 "reg_or_int_operand" "r,I")
872: (match_operand:SI 2 "s_register_operand" "r,r"))
873: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
874: "TARGET_32BIT"
875: "@
876: sbc%?\\t%0, %1, %2
877: rsc%?\\t%0, %2, %1"
878: [(set_attr "conds" "use")
879: (set_attr "arch" "*,a")
880: (set_attr "predicable" "yes")
881: (set_attr "predicable_short_it" "no")
882: (set_attr "type" "adc_reg,adc_imm")]
883: )
884:
885: (define_insn "*subsi3_carryin_const"
886: [(set (match_operand:SI 0 "s_register_operand" "=r")
1.7 ! mrg 887: (minus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
! 888: (match_operand:SI 2 "arm_not_immediate_operand" "K"))
1.5 mrg 889: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
890: "TARGET_32BIT"
891: "sbc\\t%0, %1, #%B2"
892: [(set_attr "conds" "use")
893: (set_attr "type" "adc_imm")]
894: )
895:
896: (define_insn "*subsi3_carryin_compare"
897: [(set (reg:CC CC_REGNUM)
898: (compare:CC (match_operand:SI 1 "s_register_operand" "r")
899: (match_operand:SI 2 "s_register_operand" "r")))
900: (set (match_operand:SI 0 "s_register_operand" "=r")
901: (minus:SI (minus:SI (match_dup 1)
902: (match_dup 2))
903: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
904: "TARGET_32BIT"
905: "sbcs\\t%0, %1, %2"
906: [(set_attr "conds" "set")
907: (set_attr "type" "adcs_reg")]
908: )
909:
910: (define_insn "*subsi3_carryin_compare_const"
911: [(set (reg:CC CC_REGNUM)
912: (compare:CC (match_operand:SI 1 "reg_or_int_operand" "r")
913: (match_operand:SI 2 "arm_not_operand" "K")))
914: (set (match_operand:SI 0 "s_register_operand" "=r")
915: (minus:SI (plus:SI (match_dup 1)
916: (match_dup 2))
917: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
918: "TARGET_32BIT"
919: "sbcs\\t%0, %1, #%B2"
920: [(set_attr "conds" "set")
921: (set_attr "type" "adcs_imm")]
922: )
923:
924: (define_insn "*subsi3_carryin_shift"
925: [(set (match_operand:SI 0 "s_register_operand" "=r")
926: (minus:SI (minus:SI
927: (match_operand:SI 1 "s_register_operand" "r")
928: (match_operator:SI 2 "shift_operator"
929: [(match_operand:SI 3 "s_register_operand" "r")
930: (match_operand:SI 4 "reg_or_int_operand" "rM")]))
931: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1.1 mrg 932: "TARGET_32BIT"
1.5 mrg 933: "sbc%?\\t%0, %1, %3%S2"
934: [(set_attr "conds" "use")
935: (set_attr "predicable" "yes")
936: (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
937: (const_string "alu_shift_imm")
938: (const_string "alu_shift_reg")))]
1.1 mrg 939: )
940:
1.5 mrg 941: (define_insn "*rsbsi3_carryin_shift"
942: [(set (match_operand:SI 0 "s_register_operand" "=r")
943: (minus:SI (minus:SI
944: (match_operator:SI 2 "shift_operator"
945: [(match_operand:SI 3 "s_register_operand" "r")
946: (match_operand:SI 4 "reg_or_int_operand" "rM")])
947: (match_operand:SI 1 "s_register_operand" "r"))
948: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1.1 mrg 949: "TARGET_ARM"
1.5 mrg 950: "rsc%?\\t%0, %1, %3%S2"
1.1 mrg 951: [(set_attr "conds" "use")
1.5 mrg 952: (set_attr "predicable" "yes")
953: (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
954: (const_string "alu_shift_imm")
955: (const_string "alu_shift_reg")))]
1.1 mrg 956: )
957:
958: ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
959: (define_split
960: [(set (match_operand:SI 0 "s_register_operand" "")
961: (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
962: (match_operand:SI 2 "s_register_operand" ""))
963: (const_int -1)))
964: (clobber (match_operand:SI 3 "s_register_operand" ""))]
965: "TARGET_32BIT"
966: [(set (match_dup 3) (match_dup 1))
967: (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
968: "
969: operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
970: ")
971:
972: (define_expand "addsf3"
973: [(set (match_operand:SF 0 "s_register_operand" "")
974: (plus:SF (match_operand:SF 1 "s_register_operand" "")
1.3 mrg 975: (match_operand:SF 2 "s_register_operand" "")))]
1.1 mrg 976: "TARGET_32BIT && TARGET_HARD_FLOAT"
977: "
978: ")
979:
980: (define_expand "adddf3"
981: [(set (match_operand:DF 0 "s_register_operand" "")
982: (plus:DF (match_operand:DF 1 "s_register_operand" "")
1.3 mrg 983: (match_operand:DF 2 "s_register_operand" "")))]
1.1 mrg 984: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
985: "
986: ")
987:
988: (define_expand "subdi3"
989: [(parallel
990: [(set (match_operand:DI 0 "s_register_operand" "")
991: (minus:DI (match_operand:DI 1 "s_register_operand" "")
992: (match_operand:DI 2 "s_register_operand" "")))
993: (clobber (reg:CC CC_REGNUM))])]
994: "TARGET_EITHER"
995: "
996: if (TARGET_THUMB1)
997: {
1.3 mrg 998: if (!REG_P (operands[1]))
1.1 mrg 999: operands[1] = force_reg (DImode, operands[1]);
1.3 mrg 1000: if (!REG_P (operands[2]))
1.1 mrg 1001: operands[2] = force_reg (DImode, operands[2]);
1002: }
1003: "
1004: )
1005:
1.5 mrg 1006: (define_insn_and_split "*arm_subdi3"
1.1 mrg 1007: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
1008: (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1009: (match_operand:DI 2 "s_register_operand" "r,0,0")))
1010: (clobber (reg:CC CC_REGNUM))]
1.3 mrg 1011: "TARGET_32BIT && !TARGET_NEON"
1.5 mrg 1012: "#" ; "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1013: "&& reload_completed"
1014: [(parallel [(set (reg:CC CC_REGNUM)
1015: (compare:CC (match_dup 1) (match_dup 2)))
1016: (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1017: (set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
1018: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1019: {
1020: operands[3] = gen_highpart (SImode, operands[0]);
1021: operands[0] = gen_lowpart (SImode, operands[0]);
1022: operands[4] = gen_highpart (SImode, operands[1]);
1023: operands[1] = gen_lowpart (SImode, operands[1]);
1024: operands[5] = gen_highpart (SImode, operands[2]);
1025: operands[2] = gen_lowpart (SImode, operands[2]);
1026: }
1.1 mrg 1027: [(set_attr "conds" "clob")
1.5 mrg 1028: (set_attr "length" "8")
1029: (set_attr "type" "multiple")]
1.1 mrg 1030: )
1031:
1.5 mrg 1032: (define_insn_and_split "*subdi_di_zesidi"
1.1 mrg 1033: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1034: (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1035: (zero_extend:DI
1036: (match_operand:SI 2 "s_register_operand" "r,r"))))
1037: (clobber (reg:CC CC_REGNUM))]
1038: "TARGET_32BIT"
1.5 mrg 1039: "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1040: "&& reload_completed"
1041: [(parallel [(set (reg:CC CC_REGNUM)
1042: (compare:CC (match_dup 1) (match_dup 2)))
1043: (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1044: (set (match_dup 3) (minus:SI (plus:SI (match_dup 4) (match_dup 5))
1045: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1046: {
1047: operands[3] = gen_highpart (SImode, operands[0]);
1048: operands[0] = gen_lowpart (SImode, operands[0]);
1049: operands[4] = gen_highpart (SImode, operands[1]);
1050: operands[1] = gen_lowpart (SImode, operands[1]);
1051: operands[5] = GEN_INT (~0);
1052: }
1.1 mrg 1053: [(set_attr "conds" "clob")
1.5 mrg 1054: (set_attr "length" "8")
1055: (set_attr "type" "multiple")]
1.1 mrg 1056: )
1057:
1.5 mrg 1058: (define_insn_and_split "*subdi_di_sesidi"
1.1 mrg 1059: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1060: (minus:DI (match_operand:DI 1 "s_register_operand" "0,r")
1061: (sign_extend:DI
1062: (match_operand:SI 2 "s_register_operand" "r,r"))))
1063: (clobber (reg:CC CC_REGNUM))]
1064: "TARGET_32BIT"
1.5 mrg 1065: "#" ; "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1066: "&& reload_completed"
1067: [(parallel [(set (reg:CC CC_REGNUM)
1068: (compare:CC (match_dup 1) (match_dup 2)))
1069: (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1070: (set (match_dup 3) (minus:SI (minus:SI (match_dup 4)
1071: (ashiftrt:SI (match_dup 2)
1072: (const_int 31)))
1073: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1074: {
1075: operands[3] = gen_highpart (SImode, operands[0]);
1076: operands[0] = gen_lowpart (SImode, operands[0]);
1077: operands[4] = gen_highpart (SImode, operands[1]);
1078: operands[1] = gen_lowpart (SImode, operands[1]);
1079: }
1.1 mrg 1080: [(set_attr "conds" "clob")
1.5 mrg 1081: (set_attr "length" "8")
1082: (set_attr "type" "multiple")]
1.1 mrg 1083: )
1084:
1.5 mrg 1085: (define_insn_and_split "*subdi_zesidi_di"
1.1 mrg 1086: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1087: (minus:DI (zero_extend:DI
1088: (match_operand:SI 2 "s_register_operand" "r,r"))
1089: (match_operand:DI 1 "s_register_operand" "0,r")))
1090: (clobber (reg:CC CC_REGNUM))]
1091: "TARGET_ARM"
1.5 mrg 1092: "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1093: ; is equivalent to:
1094: ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, #0"
1095: "&& reload_completed"
1096: [(parallel [(set (reg:CC CC_REGNUM)
1097: (compare:CC (match_dup 2) (match_dup 1)))
1098: (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1099: (set (match_dup 3) (minus:SI (minus:SI (const_int 0) (match_dup 4))
1100: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1101: {
1102: operands[3] = gen_highpart (SImode, operands[0]);
1103: operands[0] = gen_lowpart (SImode, operands[0]);
1104: operands[4] = gen_highpart (SImode, operands[1]);
1105: operands[1] = gen_lowpart (SImode, operands[1]);
1106: }
1.1 mrg 1107: [(set_attr "conds" "clob")
1.5 mrg 1108: (set_attr "length" "8")
1109: (set_attr "type" "multiple")]
1.1 mrg 1110: )
1111:
1.5 mrg 1112: (define_insn_and_split "*subdi_sesidi_di"
1.1 mrg 1113: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1114: (minus:DI (sign_extend:DI
1115: (match_operand:SI 2 "s_register_operand" "r,r"))
1116: (match_operand:DI 1 "s_register_operand" "0,r")))
1117: (clobber (reg:CC CC_REGNUM))]
1118: "TARGET_ARM"
1.5 mrg 1119: "#" ; "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1120: ; is equivalent to:
1121: ; "subs\\t%Q0, %2, %Q1\;rsc\\t%R0, %R1, %2, asr #31"
1122: "&& reload_completed"
1123: [(parallel [(set (reg:CC CC_REGNUM)
1124: (compare:CC (match_dup 2) (match_dup 1)))
1125: (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))])
1126: (set (match_dup 3) (minus:SI (minus:SI
1127: (ashiftrt:SI (match_dup 2)
1128: (const_int 31))
1129: (match_dup 4))
1130: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1131: {
1132: operands[3] = gen_highpart (SImode, operands[0]);
1133: operands[0] = gen_lowpart (SImode, operands[0]);
1134: operands[4] = gen_highpart (SImode, operands[1]);
1135: operands[1] = gen_lowpart (SImode, operands[1]);
1136: }
1.1 mrg 1137: [(set_attr "conds" "clob")
1.5 mrg 1138: (set_attr "length" "8")
1139: (set_attr "type" "multiple")]
1.1 mrg 1140: )
1141:
1.5 mrg 1142: (define_insn_and_split "*subdi_zesidi_zesidi"
1.1 mrg 1143: [(set (match_operand:DI 0 "s_register_operand" "=r")
1144: (minus:DI (zero_extend:DI
1145: (match_operand:SI 1 "s_register_operand" "r"))
1146: (zero_extend:DI
1147: (match_operand:SI 2 "s_register_operand" "r"))))
1148: (clobber (reg:CC CC_REGNUM))]
1149: "TARGET_32BIT"
1.5 mrg 1150: "#" ; "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1151: "&& reload_completed"
1152: [(parallel [(set (reg:CC CC_REGNUM)
1153: (compare:CC (match_dup 1) (match_dup 2)))
1154: (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
1155: (set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 1))
1156: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
1157: {
1158: operands[3] = gen_highpart (SImode, operands[0]);
1159: operands[0] = gen_lowpart (SImode, operands[0]);
1160: }
1.1 mrg 1161: [(set_attr "conds" "clob")
1.5 mrg 1162: (set_attr "length" "8")
1163: (set_attr "type" "multiple")]
1.1 mrg 1164: )
1165:
1166: (define_expand "subsi3"
1167: [(set (match_operand:SI 0 "s_register_operand" "")
1168: (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1169: (match_operand:SI 2 "s_register_operand" "")))]
1170: "TARGET_EITHER"
1171: "
1.3 mrg 1172: if (CONST_INT_P (operands[1]))
1.1 mrg 1173: {
1174: if (TARGET_32BIT)
1175: {
1.7 ! mrg 1176: if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), MINUS))
! 1177: operands[1] = force_reg (SImode, operands[1]);
! 1178: else
! 1179: {
! 1180: arm_split_constant (MINUS, SImode, NULL_RTX,
! 1181: INTVAL (operands[1]), operands[0],
! 1182: operands[2],
! 1183: optimize && can_create_pseudo_p ());
! 1184: DONE;
! 1185: }
1.1 mrg 1186: }
1187: else /* TARGET_THUMB1 */
1188: operands[1] = force_reg (SImode, operands[1]);
1189: }
1190: "
1191: )
1192:
1193: ; ??? Check Thumb-2 split length
1194: (define_insn_and_split "*arm_subsi3_insn"
1.7 ! mrg 1195: [(set (match_operand:SI 0 "s_register_operand" "=l,l ,l ,l ,r,r,r,rk,r")
! 1196: (minus:SI (match_operand:SI 1 "reg_or_int_operand" "l ,0 ,l ,Pz,I,r,r,k ,?n")
! 1197: (match_operand:SI 2 "reg_or_int_operand" "l ,Py,Pd,l ,r,I,r,r ,r")))]
1.1 mrg 1198: "TARGET_32BIT"
1199: "@
1.5 mrg 1200: sub%?\\t%0, %1, %2
1201: sub%?\\t%0, %2
1202: sub%?\\t%0, %1, %2
1203: rsb%?\\t%0, %2, %1
1.1 mrg 1204: rsb%?\\t%0, %2, %1
1205: sub%?\\t%0, %1, %2
1.3 mrg 1206: sub%?\\t%0, %1, %2
1207: sub%?\\t%0, %1, %2
1.1 mrg 1208: #"
1.3 mrg 1209: "&& (CONST_INT_P (operands[1])
1210: && !const_ok_for_arm (INTVAL (operands[1])))"
1.1 mrg 1211: [(clobber (const_int 0))]
1212: "
1213: arm_split_constant (MINUS, SImode, curr_insn,
1214: INTVAL (operands[1]), operands[0], operands[2], 0);
1215: DONE;
1216: "
1.5 mrg 1217: [(set_attr "length" "4,4,4,4,4,4,4,4,16")
1218: (set_attr "arch" "t2,t2,t2,t2,*,*,*,*,*")
1.3 mrg 1219: (set_attr "predicable" "yes")
1.5 mrg 1220: (set_attr "predicable_short_it" "yes,yes,yes,yes,no,no,no,no,no")
1221: (set_attr "type" "alu_sreg,alu_sreg,alu_sreg,alu_sreg,alu_imm,alu_imm,alu_sreg,alu_sreg,multiple")]
1.1 mrg 1222: )
1223:
1224: (define_peephole2
1225: [(match_scratch:SI 3 "r")
1226: (set (match_operand:SI 0 "arm_general_register_operand" "")
1227: (minus:SI (match_operand:SI 1 "const_int_operand" "")
1228: (match_operand:SI 2 "arm_general_register_operand" "")))]
1229: "TARGET_32BIT
1230: && !const_ok_for_arm (INTVAL (operands[1]))
1231: && const_ok_for_arm (~INTVAL (operands[1]))"
1232: [(set (match_dup 3) (match_dup 1))
1233: (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1234: ""
1235: )
1236:
1.7 ! mrg 1237: (define_insn "subsi3_compare0"
1.1 mrg 1238: [(set (reg:CC_NOOV CC_REGNUM)
1239: (compare:CC_NOOV
1.3 mrg 1240: (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1241: (match_operand:SI 2 "arm_rhs_operand" "I,r,r"))
1.1 mrg 1242: (const_int 0)))
1.3 mrg 1243: (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1244: (minus:SI (match_dup 1) (match_dup 2)))]
1245: "TARGET_32BIT"
1246: "@
1.7 ! mrg 1247: subs%?\\t%0, %1, %2
! 1248: subs%?\\t%0, %1, %2
! 1249: rsbs%?\\t%0, %2, %1"
1.3 mrg 1250: [(set_attr "conds" "set")
1.5 mrg 1251: (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
1.3 mrg 1252: )
1253:
1.5 mrg 1254: (define_insn "subsi3_compare"
1.3 mrg 1255: [(set (reg:CC CC_REGNUM)
1256: (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
1257: (match_operand:SI 2 "arm_rhs_operand" "I,r,r")))
1258: (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1.1 mrg 1259: (minus:SI (match_dup 1) (match_dup 2)))]
1260: "TARGET_32BIT"
1261: "@
1.7 ! mrg 1262: subs%?\\t%0, %1, %2
! 1263: subs%?\\t%0, %1, %2
! 1264: rsbs%?\\t%0, %2, %1"
1.3 mrg 1265: [(set_attr "conds" "set")
1.5 mrg 1266: (set_attr "type" "alus_imm,alus_sreg,alus_sreg")]
1.1 mrg 1267: )
1268:
1269: (define_expand "subsf3"
1270: [(set (match_operand:SF 0 "s_register_operand" "")
1.3 mrg 1271: (minus:SF (match_operand:SF 1 "s_register_operand" "")
1272: (match_operand:SF 2 "s_register_operand" "")))]
1.1 mrg 1273: "TARGET_32BIT && TARGET_HARD_FLOAT"
1274: "
1275: ")
1276:
1277: (define_expand "subdf3"
1278: [(set (match_operand:DF 0 "s_register_operand" "")
1.3 mrg 1279: (minus:DF (match_operand:DF 1 "s_register_operand" "")
1280: (match_operand:DF 2 "s_register_operand" "")))]
1.1 mrg 1281: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1282: "
1283: ")
1284:
1285:
1286: ;; Multiplication insns
1287:
1.5 mrg 1288: (define_expand "mulhi3"
1289: [(set (match_operand:HI 0 "s_register_operand" "")
1290: (mult:HI (match_operand:HI 1 "s_register_operand" "")
1291: (match_operand:HI 2 "s_register_operand" "")))]
1292: "TARGET_DSP_MULTIPLY"
1293: "
1294: {
1295: rtx result = gen_reg_rtx (SImode);
1296: emit_insn (gen_mulhisi3 (result, operands[1], operands[2]));
1297: emit_move_insn (operands[0], gen_lowpart (HImode, result));
1298: DONE;
1299: }"
1300: )
1301:
1.1 mrg 1302: (define_expand "mulsi3"
1303: [(set (match_operand:SI 0 "s_register_operand" "")
1304: (mult:SI (match_operand:SI 2 "s_register_operand" "")
1305: (match_operand:SI 1 "s_register_operand" "")))]
1306: "TARGET_EITHER"
1307: ""
1308: )
1309:
1310: ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1311: (define_insn "*arm_mulsi3"
1312: [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1313: (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1314: (match_operand:SI 1 "s_register_operand" "%0,r")))]
1315: "TARGET_32BIT && !arm_arch6"
1316: "mul%?\\t%0, %2, %1"
1.5 mrg 1317: [(set_attr "type" "mul")
1.1 mrg 1318: (set_attr "predicable" "yes")]
1319: )
1320:
1321: (define_insn "*arm_mulsi3_v6"
1.5 mrg 1322: [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
1323: (mult:SI (match_operand:SI 1 "s_register_operand" "0,l,r")
1324: (match_operand:SI 2 "s_register_operand" "l,0,r")))]
1.1 mrg 1325: "TARGET_32BIT && arm_arch6"
1326: "mul%?\\t%0, %1, %2"
1.5 mrg 1327: [(set_attr "type" "mul")
1328: (set_attr "predicable" "yes")
1329: (set_attr "arch" "t2,t2,*")
1330: (set_attr "length" "4")
1331: (set_attr "predicable_short_it" "yes,yes,no")]
1.1 mrg 1332: )
1333:
1334: (define_insn "*mulsi3_compare0"
1335: [(set (reg:CC_NOOV CC_REGNUM)
1336: (compare:CC_NOOV (mult:SI
1337: (match_operand:SI 2 "s_register_operand" "r,r")
1338: (match_operand:SI 1 "s_register_operand" "%0,r"))
1339: (const_int 0)))
1340: (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1341: (mult:SI (match_dup 2) (match_dup 1)))]
1342: "TARGET_ARM && !arm_arch6"
1.7 ! mrg 1343: "muls%?\\t%0, %2, %1"
1.1 mrg 1344: [(set_attr "conds" "set")
1.5 mrg 1345: (set_attr "type" "muls")]
1.1 mrg 1346: )
1347:
1348: (define_insn "*mulsi3_compare0_v6"
1349: [(set (reg:CC_NOOV CC_REGNUM)
1350: (compare:CC_NOOV (mult:SI
1351: (match_operand:SI 2 "s_register_operand" "r")
1352: (match_operand:SI 1 "s_register_operand" "r"))
1353: (const_int 0)))
1354: (set (match_operand:SI 0 "s_register_operand" "=r")
1355: (mult:SI (match_dup 2) (match_dup 1)))]
1356: "TARGET_ARM && arm_arch6 && optimize_size"
1.7 ! mrg 1357: "muls%?\\t%0, %2, %1"
1.1 mrg 1358: [(set_attr "conds" "set")
1.5 mrg 1359: (set_attr "type" "muls")]
1.1 mrg 1360: )
1361:
1362: (define_insn "*mulsi_compare0_scratch"
1363: [(set (reg:CC_NOOV CC_REGNUM)
1364: (compare:CC_NOOV (mult:SI
1365: (match_operand:SI 2 "s_register_operand" "r,r")
1366: (match_operand:SI 1 "s_register_operand" "%0,r"))
1367: (const_int 0)))
1368: (clobber (match_scratch:SI 0 "=&r,&r"))]
1369: "TARGET_ARM && !arm_arch6"
1.7 ! mrg 1370: "muls%?\\t%0, %2, %1"
1.1 mrg 1371: [(set_attr "conds" "set")
1.5 mrg 1372: (set_attr "type" "muls")]
1.1 mrg 1373: )
1374:
1375: (define_insn "*mulsi_compare0_scratch_v6"
1376: [(set (reg:CC_NOOV CC_REGNUM)
1377: (compare:CC_NOOV (mult:SI
1378: (match_operand:SI 2 "s_register_operand" "r")
1379: (match_operand:SI 1 "s_register_operand" "r"))
1380: (const_int 0)))
1381: (clobber (match_scratch:SI 0 "=r"))]
1382: "TARGET_ARM && arm_arch6 && optimize_size"
1.7 ! mrg 1383: "muls%?\\t%0, %2, %1"
1.1 mrg 1384: [(set_attr "conds" "set")
1.5 mrg 1385: (set_attr "type" "muls")]
1.1 mrg 1386: )
1387:
1388: ;; Unnamed templates to match MLA instruction.
1389:
1390: (define_insn "*mulsi3addsi"
1391: [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1392: (plus:SI
1393: (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1394: (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1395: (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1396: "TARGET_32BIT && !arm_arch6"
1397: "mla%?\\t%0, %2, %1, %3"
1.5 mrg 1398: [(set_attr "type" "mla")
1.1 mrg 1399: (set_attr "predicable" "yes")]
1400: )
1401:
1402: (define_insn "*mulsi3addsi_v6"
1403: [(set (match_operand:SI 0 "s_register_operand" "=r")
1404: (plus:SI
1405: (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1406: (match_operand:SI 1 "s_register_operand" "r"))
1407: (match_operand:SI 3 "s_register_operand" "r")))]
1408: "TARGET_32BIT && arm_arch6"
1409: "mla%?\\t%0, %2, %1, %3"
1.5 mrg 1410: [(set_attr "type" "mla")
1411: (set_attr "predicable" "yes")
1412: (set_attr "predicable_short_it" "no")]
1.1 mrg 1413: )
1414:
1415: (define_insn "*mulsi3addsi_compare0"
1416: [(set (reg:CC_NOOV CC_REGNUM)
1417: (compare:CC_NOOV
1418: (plus:SI (mult:SI
1419: (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1420: (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1421: (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1422: (const_int 0)))
1423: (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1424: (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1425: (match_dup 3)))]
1426: "TARGET_ARM && arm_arch6"
1.7 ! mrg 1427: "mlas%?\\t%0, %2, %1, %3"
1.1 mrg 1428: [(set_attr "conds" "set")
1.5 mrg 1429: (set_attr "type" "mlas")]
1.1 mrg 1430: )
1431:
1432: (define_insn "*mulsi3addsi_compare0_v6"
1433: [(set (reg:CC_NOOV CC_REGNUM)
1434: (compare:CC_NOOV
1435: (plus:SI (mult:SI
1436: (match_operand:SI 2 "s_register_operand" "r")
1437: (match_operand:SI 1 "s_register_operand" "r"))
1438: (match_operand:SI 3 "s_register_operand" "r"))
1439: (const_int 0)))
1440: (set (match_operand:SI 0 "s_register_operand" "=r")
1441: (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1442: (match_dup 3)))]
1443: "TARGET_ARM && arm_arch6 && optimize_size"
1.7 ! mrg 1444: "mlas%?\\t%0, %2, %1, %3"
1.1 mrg 1445: [(set_attr "conds" "set")
1.5 mrg 1446: (set_attr "type" "mlas")]
1.1 mrg 1447: )
1448:
1449: (define_insn "*mulsi3addsi_compare0_scratch"
1450: [(set (reg:CC_NOOV CC_REGNUM)
1451: (compare:CC_NOOV
1452: (plus:SI (mult:SI
1453: (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1454: (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1455: (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1456: (const_int 0)))
1457: (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1458: "TARGET_ARM && !arm_arch6"
1.7 ! mrg 1459: "mlas%?\\t%0, %2, %1, %3"
1.1 mrg 1460: [(set_attr "conds" "set")
1.5 mrg 1461: (set_attr "type" "mlas")]
1.1 mrg 1462: )
1463:
1464: (define_insn "*mulsi3addsi_compare0_scratch_v6"
1465: [(set (reg:CC_NOOV CC_REGNUM)
1466: (compare:CC_NOOV
1467: (plus:SI (mult:SI
1468: (match_operand:SI 2 "s_register_operand" "r")
1469: (match_operand:SI 1 "s_register_operand" "r"))
1470: (match_operand:SI 3 "s_register_operand" "r"))
1471: (const_int 0)))
1472: (clobber (match_scratch:SI 0 "=r"))]
1473: "TARGET_ARM && arm_arch6 && optimize_size"
1.7 ! mrg 1474: "mlas%?\\t%0, %2, %1, %3"
1.1 mrg 1475: [(set_attr "conds" "set")
1.5 mrg 1476: (set_attr "type" "mlas")]
1.1 mrg 1477: )
1478:
1479: (define_insn "*mulsi3subsi"
1480: [(set (match_operand:SI 0 "s_register_operand" "=r")
1481: (minus:SI
1482: (match_operand:SI 3 "s_register_operand" "r")
1483: (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1484: (match_operand:SI 1 "s_register_operand" "r"))))]
1485: "TARGET_32BIT && arm_arch_thumb2"
1486: "mls%?\\t%0, %2, %1, %3"
1.5 mrg 1487: [(set_attr "type" "mla")
1488: (set_attr "predicable" "yes")
1489: (set_attr "predicable_short_it" "no")]
1.1 mrg 1490: )
1491:
1.3 mrg 1492: (define_expand "maddsidi4"
1493: [(set (match_operand:DI 0 "s_register_operand" "")
1494: (plus:DI
1495: (mult:DI
1496: (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1497: (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1498: (match_operand:DI 3 "s_register_operand" "")))]
1499: "TARGET_32BIT && arm_arch3m"
1500: "")
1.1 mrg 1501:
1502: (define_insn "*mulsidi3adddi"
1503: [(set (match_operand:DI 0 "s_register_operand" "=&r")
1504: (plus:DI
1505: (mult:DI
1506: (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1507: (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1508: (match_operand:DI 1 "s_register_operand" "0")))]
1509: "TARGET_32BIT && arm_arch3m && !arm_arch6"
1510: "smlal%?\\t%Q0, %R0, %3, %2"
1.5 mrg 1511: [(set_attr "type" "smlal")
1.1 mrg 1512: (set_attr "predicable" "yes")]
1513: )
1514:
1515: (define_insn "*mulsidi3adddi_v6"
1516: [(set (match_operand:DI 0 "s_register_operand" "=r")
1517: (plus:DI
1518: (mult:DI
1519: (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1520: (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1521: (match_operand:DI 1 "s_register_operand" "0")))]
1522: "TARGET_32BIT && arm_arch6"
1523: "smlal%?\\t%Q0, %R0, %3, %2"
1.5 mrg 1524: [(set_attr "type" "smlal")
1525: (set_attr "predicable" "yes")
1526: (set_attr "predicable_short_it" "no")]
1.1 mrg 1527: )
1528:
1529: ;; 32x32->64 widening multiply.
1530: ;; As with mulsi3, the only difference between the v3-5 and v6+
1531: ;; versions of these patterns is the requirement that the output not
1532: ;; overlap the inputs, but that still means we have to have a named
1533: ;; expander and two different starred insns.
1534:
1535: (define_expand "mulsidi3"
1536: [(set (match_operand:DI 0 "s_register_operand" "")
1537: (mult:DI
1538: (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1539: (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1540: "TARGET_32BIT && arm_arch3m"
1541: ""
1542: )
1543:
1544: (define_insn "*mulsidi3_nov6"
1545: [(set (match_operand:DI 0 "s_register_operand" "=&r")
1546: (mult:DI
1547: (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1548: (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1549: "TARGET_32BIT && arm_arch3m && !arm_arch6"
1550: "smull%?\\t%Q0, %R0, %1, %2"
1.5 mrg 1551: [(set_attr "type" "smull")
1.1 mrg 1552: (set_attr "predicable" "yes")]
1553: )
1554:
1555: (define_insn "*mulsidi3_v6"
1556: [(set (match_operand:DI 0 "s_register_operand" "=r")
1557: (mult:DI
1558: (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1559: (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1560: "TARGET_32BIT && arm_arch6"
1561: "smull%?\\t%Q0, %R0, %1, %2"
1.5 mrg 1562: [(set_attr "type" "smull")
1563: (set_attr "predicable" "yes")
1564: (set_attr "predicable_short_it" "no")]
1.1 mrg 1565: )
1566:
1567: (define_expand "umulsidi3"
1568: [(set (match_operand:DI 0 "s_register_operand" "")
1569: (mult:DI
1570: (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1571: (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1572: "TARGET_32BIT && arm_arch3m"
1573: ""
1574: )
1575:
1576: (define_insn "*umulsidi3_nov6"
1577: [(set (match_operand:DI 0 "s_register_operand" "=&r")
1578: (mult:DI
1579: (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1580: (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1581: "TARGET_32BIT && arm_arch3m && !arm_arch6"
1582: "umull%?\\t%Q0, %R0, %1, %2"
1.5 mrg 1583: [(set_attr "type" "umull")
1.1 mrg 1584: (set_attr "predicable" "yes")]
1585: )
1586:
1587: (define_insn "*umulsidi3_v6"
1588: [(set (match_operand:DI 0 "s_register_operand" "=r")
1589: (mult:DI
1590: (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1591: (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1592: "TARGET_32BIT && arm_arch6"
1593: "umull%?\\t%Q0, %R0, %1, %2"
1.5 mrg 1594: [(set_attr "type" "umull")
1595: (set_attr "predicable" "yes")
1596: (set_attr "predicable_short_it" "no")]
1.1 mrg 1597: )
1598:
1.3 mrg 1599: (define_expand "umaddsidi4"
1600: [(set (match_operand:DI 0 "s_register_operand" "")
1601: (plus:DI
1602: (mult:DI
1603: (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1604: (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1605: (match_operand:DI 3 "s_register_operand" "")))]
1606: "TARGET_32BIT && arm_arch3m"
1607: "")
1.1 mrg 1608:
1609: (define_insn "*umulsidi3adddi"
1610: [(set (match_operand:DI 0 "s_register_operand" "=&r")
1611: (plus:DI
1612: (mult:DI
1613: (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1614: (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1615: (match_operand:DI 1 "s_register_operand" "0")))]
1616: "TARGET_32BIT && arm_arch3m && !arm_arch6"
1617: "umlal%?\\t%Q0, %R0, %3, %2"
1.5 mrg 1618: [(set_attr "type" "umlal")
1.1 mrg 1619: (set_attr "predicable" "yes")]
1620: )
1621:
1622: (define_insn "*umulsidi3adddi_v6"
1623: [(set (match_operand:DI 0 "s_register_operand" "=r")
1624: (plus:DI
1625: (mult:DI
1626: (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1627: (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1628: (match_operand:DI 1 "s_register_operand" "0")))]
1629: "TARGET_32BIT && arm_arch6"
1630: "umlal%?\\t%Q0, %R0, %3, %2"
1.5 mrg 1631: [(set_attr "type" "umlal")
1632: (set_attr "predicable" "yes")
1633: (set_attr "predicable_short_it" "no")]
1.1 mrg 1634: )
1635:
1636: (define_expand "smulsi3_highpart"
1637: [(parallel
1638: [(set (match_operand:SI 0 "s_register_operand" "")
1639: (truncate:SI
1640: (lshiftrt:DI
1641: (mult:DI
1642: (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1643: (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1644: (const_int 32))))
1645: (clobber (match_scratch:SI 3 ""))])]
1646: "TARGET_32BIT && arm_arch3m"
1647: ""
1648: )
1649:
1650: (define_insn "*smulsi3_highpart_nov6"
1651: [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1652: (truncate:SI
1653: (lshiftrt:DI
1654: (mult:DI
1655: (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1656: (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1657: (const_int 32))))
1658: (clobber (match_scratch:SI 3 "=&r,&r"))]
1659: "TARGET_32BIT && arm_arch3m && !arm_arch6"
1660: "smull%?\\t%3, %0, %2, %1"
1.5 mrg 1661: [(set_attr "type" "smull")
1.1 mrg 1662: (set_attr "predicable" "yes")]
1663: )
1664:
1665: (define_insn "*smulsi3_highpart_v6"
1666: [(set (match_operand:SI 0 "s_register_operand" "=r")
1667: (truncate:SI
1668: (lshiftrt:DI
1669: (mult:DI
1670: (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1671: (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1672: (const_int 32))))
1673: (clobber (match_scratch:SI 3 "=r"))]
1674: "TARGET_32BIT && arm_arch6"
1675: "smull%?\\t%3, %0, %2, %1"
1.5 mrg 1676: [(set_attr "type" "smull")
1677: (set_attr "predicable" "yes")
1678: (set_attr "predicable_short_it" "no")]
1.1 mrg 1679: )
1680:
1681: (define_expand "umulsi3_highpart"
1682: [(parallel
1683: [(set (match_operand:SI 0 "s_register_operand" "")
1684: (truncate:SI
1685: (lshiftrt:DI
1686: (mult:DI
1687: (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1688: (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1689: (const_int 32))))
1690: (clobber (match_scratch:SI 3 ""))])]
1691: "TARGET_32BIT && arm_arch3m"
1692: ""
1693: )
1694:
1695: (define_insn "*umulsi3_highpart_nov6"
1696: [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1697: (truncate:SI
1698: (lshiftrt:DI
1699: (mult:DI
1700: (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1701: (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1702: (const_int 32))))
1703: (clobber (match_scratch:SI 3 "=&r,&r"))]
1704: "TARGET_32BIT && arm_arch3m && !arm_arch6"
1705: "umull%?\\t%3, %0, %2, %1"
1.5 mrg 1706: [(set_attr "type" "umull")
1.1 mrg 1707: (set_attr "predicable" "yes")]
1708: )
1709:
1710: (define_insn "*umulsi3_highpart_v6"
1711: [(set (match_operand:SI 0 "s_register_operand" "=r")
1712: (truncate:SI
1713: (lshiftrt:DI
1714: (mult:DI
1715: (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1716: (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1717: (const_int 32))))
1718: (clobber (match_scratch:SI 3 "=r"))]
1719: "TARGET_32BIT && arm_arch6"
1720: "umull%?\\t%3, %0, %2, %1"
1.5 mrg 1721: [(set_attr "type" "umull")
1722: (set_attr "predicable" "yes")
1723: (set_attr "predicable_short_it" "no")]
1.1 mrg 1724: )
1725:
1726: (define_insn "mulhisi3"
1727: [(set (match_operand:SI 0 "s_register_operand" "=r")
1728: (mult:SI (sign_extend:SI
1729: (match_operand:HI 1 "s_register_operand" "%r"))
1730: (sign_extend:SI
1731: (match_operand:HI 2 "s_register_operand" "r"))))]
1732: "TARGET_DSP_MULTIPLY"
1733: "smulbb%?\\t%0, %1, %2"
1.5 mrg 1734: [(set_attr "type" "smulxy")
1.1 mrg 1735: (set_attr "predicable" "yes")]
1736: )
1737:
1738: (define_insn "*mulhisi3tb"
1739: [(set (match_operand:SI 0 "s_register_operand" "=r")
1740: (mult:SI (ashiftrt:SI
1741: (match_operand:SI 1 "s_register_operand" "r")
1742: (const_int 16))
1743: (sign_extend:SI
1744: (match_operand:HI 2 "s_register_operand" "r"))))]
1745: "TARGET_DSP_MULTIPLY"
1746: "smultb%?\\t%0, %1, %2"
1.5 mrg 1747: [(set_attr "type" "smulxy")
1748: (set_attr "predicable" "yes")
1749: (set_attr "predicable_short_it" "no")]
1.1 mrg 1750: )
1751:
1752: (define_insn "*mulhisi3bt"
1753: [(set (match_operand:SI 0 "s_register_operand" "=r")
1754: (mult:SI (sign_extend:SI
1755: (match_operand:HI 1 "s_register_operand" "r"))
1756: (ashiftrt:SI
1757: (match_operand:SI 2 "s_register_operand" "r")
1758: (const_int 16))))]
1759: "TARGET_DSP_MULTIPLY"
1760: "smulbt%?\\t%0, %1, %2"
1.5 mrg 1761: [(set_attr "type" "smulxy")
1762: (set_attr "predicable" "yes")
1763: (set_attr "predicable_short_it" "no")]
1.1 mrg 1764: )
1765:
1766: (define_insn "*mulhisi3tt"
1767: [(set (match_operand:SI 0 "s_register_operand" "=r")
1768: (mult:SI (ashiftrt:SI
1769: (match_operand:SI 1 "s_register_operand" "r")
1770: (const_int 16))
1771: (ashiftrt:SI
1772: (match_operand:SI 2 "s_register_operand" "r")
1773: (const_int 16))))]
1774: "TARGET_DSP_MULTIPLY"
1775: "smultt%?\\t%0, %1, %2"
1.5 mrg 1776: [(set_attr "type" "smulxy")
1777: (set_attr "predicable" "yes")
1778: (set_attr "predicable_short_it" "no")]
1.1 mrg 1779: )
1780:
1.3 mrg 1781: (define_insn "maddhisi4"
1782: [(set (match_operand:SI 0 "s_register_operand" "=r")
1783: (plus:SI (mult:SI (sign_extend:SI
1784: (match_operand:HI 1 "s_register_operand" "r"))
1785: (sign_extend:SI
1786: (match_operand:HI 2 "s_register_operand" "r")))
1787: (match_operand:SI 3 "s_register_operand" "r")))]
1788: "TARGET_DSP_MULTIPLY"
1789: "smlabb%?\\t%0, %1, %2, %3"
1.5 mrg 1790: [(set_attr "type" "smlaxy")
1791: (set_attr "predicable" "yes")
1792: (set_attr "predicable_short_it" "no")]
1.3 mrg 1793: )
1794:
1795: ;; Note: there is no maddhisi4ibt because this one is canonical form
1796: (define_insn "*maddhisi4tb"
1.1 mrg 1797: [(set (match_operand:SI 0 "s_register_operand" "=r")
1.3 mrg 1798: (plus:SI (mult:SI (ashiftrt:SI
1799: (match_operand:SI 1 "s_register_operand" "r")
1800: (const_int 16))
1.1 mrg 1801: (sign_extend:SI
1.3 mrg 1802: (match_operand:HI 2 "s_register_operand" "r")))
1803: (match_operand:SI 3 "s_register_operand" "r")))]
1804: "TARGET_DSP_MULTIPLY"
1805: "smlatb%?\\t%0, %1, %2, %3"
1.5 mrg 1806: [(set_attr "type" "smlaxy")
1807: (set_attr "predicable" "yes")
1808: (set_attr "predicable_short_it" "no")]
1.3 mrg 1809: )
1810:
1811: (define_insn "*maddhisi4tt"
1812: [(set (match_operand:SI 0 "s_register_operand" "=r")
1813: (plus:SI (mult:SI (ashiftrt:SI
1814: (match_operand:SI 1 "s_register_operand" "r")
1815: (const_int 16))
1816: (ashiftrt:SI
1817: (match_operand:SI 2 "s_register_operand" "r")
1818: (const_int 16)))
1819: (match_operand:SI 3 "s_register_operand" "r")))]
1.1 mrg 1820: "TARGET_DSP_MULTIPLY"
1.3 mrg 1821: "smlatt%?\\t%0, %1, %2, %3"
1.5 mrg 1822: [(set_attr "type" "smlaxy")
1823: (set_attr "predicable" "yes")
1824: (set_attr "predicable_short_it" "no")]
1.1 mrg 1825: )
1826:
1.3 mrg 1827: (define_insn "maddhidi4"
1828: [(set (match_operand:DI 0 "s_register_operand" "=r")
1829: (plus:DI
1830: (mult:DI (sign_extend:DI
1.5 mrg 1831: (match_operand:HI 1 "s_register_operand" "r"))
1.3 mrg 1832: (sign_extend:DI
1833: (match_operand:HI 2 "s_register_operand" "r")))
1834: (match_operand:DI 3 "s_register_operand" "0")))]
1835: "TARGET_DSP_MULTIPLY"
1836: "smlalbb%?\\t%Q0, %R0, %1, %2"
1.5 mrg 1837: [(set_attr "type" "smlalxy")
1838: (set_attr "predicable" "yes")
1839: (set_attr "predicable_short_it" "no")])
1.3 mrg 1840:
1841: ;; Note: there is no maddhidi4ibt because this one is canonical form
1842: (define_insn "*maddhidi4tb"
1843: [(set (match_operand:DI 0 "s_register_operand" "=r")
1844: (plus:DI
1845: (mult:DI (sign_extend:DI
1846: (ashiftrt:SI
1847: (match_operand:SI 1 "s_register_operand" "r")
1848: (const_int 16)))
1849: (sign_extend:DI
1850: (match_operand:HI 2 "s_register_operand" "r")))
1851: (match_operand:DI 3 "s_register_operand" "0")))]
1852: "TARGET_DSP_MULTIPLY"
1853: "smlaltb%?\\t%Q0, %R0, %1, %2"
1.5 mrg 1854: [(set_attr "type" "smlalxy")
1855: (set_attr "predicable" "yes")
1856: (set_attr "predicable_short_it" "no")])
1.3 mrg 1857:
1858: (define_insn "*maddhidi4tt"
1.1 mrg 1859: [(set (match_operand:DI 0 "s_register_operand" "=r")
1860: (plus:DI
1861: (mult:DI (sign_extend:DI
1.3 mrg 1862: (ashiftrt:SI
1863: (match_operand:SI 1 "s_register_operand" "r")
1864: (const_int 16)))
1.1 mrg 1865: (sign_extend:DI
1.3 mrg 1866: (ashiftrt:SI
1867: (match_operand:SI 2 "s_register_operand" "r")
1868: (const_int 16))))
1869: (match_operand:DI 3 "s_register_operand" "0")))]
1.1 mrg 1870: "TARGET_DSP_MULTIPLY"
1.3 mrg 1871: "smlaltt%?\\t%Q0, %R0, %1, %2"
1.5 mrg 1872: [(set_attr "type" "smlalxy")
1873: (set_attr "predicable" "yes")
1874: (set_attr "predicable_short_it" "no")])
1.1 mrg 1875:
1876: (define_expand "mulsf3"
1877: [(set (match_operand:SF 0 "s_register_operand" "")
1878: (mult:SF (match_operand:SF 1 "s_register_operand" "")
1.3 mrg 1879: (match_operand:SF 2 "s_register_operand" "")))]
1.1 mrg 1880: "TARGET_32BIT && TARGET_HARD_FLOAT"
1881: "
1882: ")
1883:
1884: (define_expand "muldf3"
1885: [(set (match_operand:DF 0 "s_register_operand" "")
1886: (mult:DF (match_operand:DF 1 "s_register_operand" "")
1.3 mrg 1887: (match_operand:DF 2 "s_register_operand" "")))]
1.1 mrg 1888: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1889: "
1890: ")
1891:
1892: ;; Division insns
1893:
1894: (define_expand "divsf3"
1895: [(set (match_operand:SF 0 "s_register_operand" "")
1.3 mrg 1896: (div:SF (match_operand:SF 1 "s_register_operand" "")
1897: (match_operand:SF 2 "s_register_operand" "")))]
1898: "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1.1 mrg 1899: "")
1900:
1901: (define_expand "divdf3"
1902: [(set (match_operand:DF 0 "s_register_operand" "")
1.3 mrg 1903: (div:DF (match_operand:DF 1 "s_register_operand" "")
1904: (match_operand:DF 2 "s_register_operand" "")))]
1905: "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1.1 mrg 1906: "")
1907:
1908: ;; Boolean and,ior,xor insns
1909:
1910: ;; Split up double word logical operations
1911:
1912: ;; Split up simple DImode logical operations. Simply perform the logical
1913: ;; operation on the upper and lower halves of the registers.
1914: (define_split
1915: [(set (match_operand:DI 0 "s_register_operand" "")
1916: (match_operator:DI 6 "logical_binary_operator"
1917: [(match_operand:DI 1 "s_register_operand" "")
1918: (match_operand:DI 2 "s_register_operand" "")]))]
1919: "TARGET_32BIT && reload_completed
1.3 mrg 1920: && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
1.1 mrg 1921: && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1922: [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1923: (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1924: "
1925: {
1926: operands[3] = gen_highpart (SImode, operands[0]);
1927: operands[0] = gen_lowpart (SImode, operands[0]);
1928: operands[4] = gen_highpart (SImode, operands[1]);
1929: operands[1] = gen_lowpart (SImode, operands[1]);
1930: operands[5] = gen_highpart (SImode, operands[2]);
1931: operands[2] = gen_lowpart (SImode, operands[2]);
1932: }"
1933: )
1934:
1935: (define_split
1936: [(set (match_operand:DI 0 "s_register_operand" "")
1937: (match_operator:DI 6 "logical_binary_operator"
1938: [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1939: (match_operand:DI 1 "s_register_operand" "")]))]
1940: "TARGET_32BIT && reload_completed"
1941: [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1942: (set (match_dup 3) (match_op_dup:SI 6
1943: [(ashiftrt:SI (match_dup 2) (const_int 31))
1944: (match_dup 4)]))]
1945: "
1946: {
1947: operands[3] = gen_highpart (SImode, operands[0]);
1948: operands[0] = gen_lowpart (SImode, operands[0]);
1949: operands[4] = gen_highpart (SImode, operands[1]);
1950: operands[1] = gen_lowpart (SImode, operands[1]);
1951: operands[5] = gen_highpart (SImode, operands[2]);
1952: operands[2] = gen_lowpart (SImode, operands[2]);
1953: }"
1954: )
1955:
1956: ;; The zero extend of operand 2 means we can just copy the high part of
1957: ;; operand1 into operand0.
1958: (define_split
1959: [(set (match_operand:DI 0 "s_register_operand" "")
1960: (ior:DI
1961: (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1962: (match_operand:DI 1 "s_register_operand" "")))]
1963: "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1964: [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1965: (set (match_dup 3) (match_dup 4))]
1966: "
1967: {
1968: operands[4] = gen_highpart (SImode, operands[1]);
1969: operands[3] = gen_highpart (SImode, operands[0]);
1970: operands[0] = gen_lowpart (SImode, operands[0]);
1971: operands[1] = gen_lowpart (SImode, operands[1]);
1972: }"
1973: )
1974:
1975: ;; The zero extend of operand 2 means we can just copy the high part of
1976: ;; operand1 into operand0.
1977: (define_split
1978: [(set (match_operand:DI 0 "s_register_operand" "")
1979: (xor:DI
1980: (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1981: (match_operand:DI 1 "s_register_operand" "")))]
1982: "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
1983: [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1984: (set (match_dup 3) (match_dup 4))]
1985: "
1986: {
1987: operands[4] = gen_highpart (SImode, operands[1]);
1988: operands[3] = gen_highpart (SImode, operands[0]);
1989: operands[0] = gen_lowpart (SImode, operands[0]);
1990: operands[1] = gen_lowpart (SImode, operands[1]);
1991: }"
1992: )
1993:
1.3 mrg 1994: (define_expand "anddi3"
1995: [(set (match_operand:DI 0 "s_register_operand" "")
1996: (and:DI (match_operand:DI 1 "s_register_operand" "")
1997: (match_operand:DI 2 "neon_inv_logic_op2" "")))]
1998: "TARGET_32BIT"
1999: ""
2000: )
2001:
1.5 mrg 2002: (define_insn_and_split "*anddi3_insn"
2003: [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2004: (and:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2005: (match_operand:DI 2 "arm_anddi_operand_neon" "w ,DL,r ,r ,De,De,w ,DL")))]
2006: "TARGET_32BIT && !TARGET_IWMMXT"
2007: {
2008: switch (which_alternative)
2009: {
2010: case 0: /* fall through */
2011: case 6: return "vand\t%P0, %P1, %P2";
2012: case 1: /* fall through */
2013: case 7: return neon_output_logic_immediate ("vand", &operands[2],
2014: DImode, 1, VALID_NEON_QREG_MODE (DImode));
2015: case 2:
2016: case 3:
2017: case 4:
2018: case 5: /* fall through */
2019: return "#";
2020: default: gcc_unreachable ();
2021: }
2022: }
2023: "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2024: && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2025: [(set (match_dup 3) (match_dup 4))
2026: (set (match_dup 5) (match_dup 6))]
2027: "
2028: {
2029: operands[3] = gen_lowpart (SImode, operands[0]);
2030: operands[5] = gen_highpart (SImode, operands[0]);
2031:
2032: operands[4] = simplify_gen_binary (AND, SImode,
2033: gen_lowpart (SImode, operands[1]),
2034: gen_lowpart (SImode, operands[2]));
2035: operands[6] = simplify_gen_binary (AND, SImode,
2036: gen_highpart (SImode, operands[1]),
2037: gen_highpart_mode (SImode, DImode, operands[2]));
2038:
2039: }"
2040: [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,\
2041: multiple,multiple,neon_logic,neon_logic")
2042: (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,
2043: avoid_neon_for_64bits,avoid_neon_for_64bits")
2044: (set_attr "length" "*,*,8,8,8,8,*,*")
2045: ]
1.1 mrg 2046: )
2047:
2048: (define_insn_and_split "*anddi_zesidi_di"
2049: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2050: (and:DI (zero_extend:DI
2051: (match_operand:SI 2 "s_register_operand" "r,r"))
2052: (match_operand:DI 1 "s_register_operand" "0,r")))]
2053: "TARGET_32BIT"
2054: "#"
2055: "TARGET_32BIT && reload_completed"
2056: ; The zero extend of operand 2 clears the high word of the output
2057: ; operand.
2058: [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2059: (set (match_dup 3) (const_int 0))]
2060: "
2061: {
2062: operands[3] = gen_highpart (SImode, operands[0]);
2063: operands[0] = gen_lowpart (SImode, operands[0]);
2064: operands[1] = gen_lowpart (SImode, operands[1]);
2065: }"
1.5 mrg 2066: [(set_attr "length" "8")
2067: (set_attr "type" "multiple")]
1.1 mrg 2068: )
2069:
2070: (define_insn "*anddi_sesdi_di"
2071: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2072: (and:DI (sign_extend:DI
2073: (match_operand:SI 2 "s_register_operand" "r,r"))
2074: (match_operand:DI 1 "s_register_operand" "0,r")))]
2075: "TARGET_32BIT"
2076: "#"
1.5 mrg 2077: [(set_attr "length" "8")
2078: (set_attr "type" "multiple")]
1.1 mrg 2079: )
2080:
2081: (define_expand "andsi3"
2082: [(set (match_operand:SI 0 "s_register_operand" "")
2083: (and:SI (match_operand:SI 1 "s_register_operand" "")
2084: (match_operand:SI 2 "reg_or_int_operand" "")))]
2085: "TARGET_EITHER"
2086: "
2087: if (TARGET_32BIT)
2088: {
1.3 mrg 2089: if (CONST_INT_P (operands[2]))
1.1 mrg 2090: {
1.3 mrg 2091: if (INTVAL (operands[2]) == 255 && arm_arch6)
2092: {
2093: operands[1] = convert_to_mode (QImode, operands[1], 1);
2094: emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2095: operands[1]));
1.7 ! mrg 2096: DONE;
1.3 mrg 2097: }
1.7 ! mrg 2098: else if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), AND))
! 2099: operands[2] = force_reg (SImode, operands[2]);
1.3 mrg 2100: else
1.7 ! mrg 2101: {
! 2102: arm_split_constant (AND, SImode, NULL_RTX,
! 2103: INTVAL (operands[2]), operands[0],
! 2104: operands[1],
! 2105: optimize && can_create_pseudo_p ());
1.1 mrg 2106:
1.7 ! mrg 2107: DONE;
! 2108: }
1.1 mrg 2109: }
2110: }
2111: else /* TARGET_THUMB1 */
2112: {
1.3 mrg 2113: if (!CONST_INT_P (operands[2]))
1.1 mrg 2114: {
2115: rtx tmp = force_reg (SImode, operands[2]);
2116: if (rtx_equal_p (operands[0], operands[1]))
2117: operands[2] = tmp;
2118: else
2119: {
2120: operands[2] = operands[1];
2121: operands[1] = tmp;
2122: }
2123: }
2124: else
2125: {
2126: int i;
2127:
2128: if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2129: {
2130: operands[2] = force_reg (SImode,
2131: GEN_INT (~INTVAL (operands[2])));
2132:
1.3 mrg 2133: emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
1.1 mrg 2134:
2135: DONE;
2136: }
2137:
2138: for (i = 9; i <= 31; i++)
2139: {
2140: if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2141: {
2142: emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2143: const0_rtx));
2144: DONE;
2145: }
2146: else if ((((HOST_WIDE_INT) 1) << i) - 1
2147: == ~INTVAL (operands[2]))
2148: {
2149: rtx shift = GEN_INT (i);
2150: rtx reg = gen_reg_rtx (SImode);
2151:
2152: emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2153: emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2154:
2155: DONE;
2156: }
2157: }
2158:
2159: operands[2] = force_reg (SImode, operands[2]);
2160: }
2161: }
2162: "
2163: )
2164:
2165: ; ??? Check split length for Thumb-2
2166: (define_insn_and_split "*arm_andsi3_insn"
1.5 mrg 2167: [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2168: (and:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2169: (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
1.1 mrg 2170: "TARGET_32BIT"
2171: "@
2172: and%?\\t%0, %1, %2
1.5 mrg 2173: and%?\\t%0, %1, %2
1.1 mrg 2174: bic%?\\t%0, %1, #%B2
1.3 mrg 2175: and%?\\t%0, %1, %2
1.1 mrg 2176: #"
2177: "TARGET_32BIT
1.3 mrg 2178: && CONST_INT_P (operands[2])
1.1 mrg 2179: && !(const_ok_for_arm (INTVAL (operands[2]))
2180: || const_ok_for_arm (~INTVAL (operands[2])))"
2181: [(clobber (const_int 0))]
2182: "
2183: arm_split_constant (AND, SImode, curr_insn,
2184: INTVAL (operands[2]), operands[0], operands[1], 0);
2185: DONE;
2186: "
1.5 mrg 2187: [(set_attr "length" "4,4,4,4,16")
1.3 mrg 2188: (set_attr "predicable" "yes")
1.5 mrg 2189: (set_attr "predicable_short_it" "no,yes,no,no,no")
2190: (set_attr "type" "logic_imm,logic_imm,logic_reg,logic_reg,logic_imm")]
1.1 mrg 2191: )
2192:
2193: (define_insn "*andsi3_compare0"
2194: [(set (reg:CC_NOOV CC_REGNUM)
2195: (compare:CC_NOOV
1.3 mrg 2196: (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2197: (match_operand:SI 2 "arm_not_operand" "I,K,r"))
1.1 mrg 2198: (const_int 0)))
1.3 mrg 2199: (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1.1 mrg 2200: (and:SI (match_dup 1) (match_dup 2)))]
2201: "TARGET_32BIT"
2202: "@
1.7 ! mrg 2203: ands%?\\t%0, %1, %2
! 2204: bics%?\\t%0, %1, #%B2
! 2205: ands%?\\t%0, %1, %2"
1.3 mrg 2206: [(set_attr "conds" "set")
1.5 mrg 2207: (set_attr "type" "logics_imm,logics_imm,logics_reg")]
1.1 mrg 2208: )
2209:
2210: (define_insn "*andsi3_compare0_scratch"
2211: [(set (reg:CC_NOOV CC_REGNUM)
2212: (compare:CC_NOOV
1.3 mrg 2213: (and:SI (match_operand:SI 0 "s_register_operand" "r,r,r")
2214: (match_operand:SI 1 "arm_not_operand" "I,K,r"))
1.1 mrg 2215: (const_int 0)))
1.3 mrg 2216: (clobber (match_scratch:SI 2 "=X,r,X"))]
1.1 mrg 2217: "TARGET_32BIT"
2218: "@
2219: tst%?\\t%0, %1
1.7 ! mrg 2220: bics%?\\t%2, %0, #%B1
1.3 mrg 2221: tst%?\\t%0, %1"
2222: [(set_attr "conds" "set")
1.5 mrg 2223: (set_attr "type" "logics_imm,logics_imm,logics_reg")]
1.1 mrg 2224: )
2225:
2226: (define_insn "*zeroextractsi_compare0_scratch"
2227: [(set (reg:CC_NOOV CC_REGNUM)
2228: (compare:CC_NOOV (zero_extract:SI
2229: (match_operand:SI 0 "s_register_operand" "r")
1.5 mrg 2230: (match_operand 1 "const_int_operand" "n")
1.1 mrg 2231: (match_operand 2 "const_int_operand" "n"))
2232: (const_int 0)))]
2233: "TARGET_32BIT
2234: && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2235: && INTVAL (operands[1]) > 0
2236: && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2237: && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2238: "*
2239: operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2240: << INTVAL (operands[2]));
2241: output_asm_insn (\"tst%?\\t%0, %1\", operands);
2242: return \"\";
2243: "
1.3 mrg 2244: [(set_attr "conds" "set")
2245: (set_attr "predicable" "yes")
1.5 mrg 2246: (set_attr "predicable_short_it" "no")
2247: (set_attr "type" "logics_imm")]
1.1 mrg 2248: )
2249:
2250: (define_insn_and_split "*ne_zeroextractsi"
2251: [(set (match_operand:SI 0 "s_register_operand" "=r")
2252: (ne:SI (zero_extract:SI
2253: (match_operand:SI 1 "s_register_operand" "r")
2254: (match_operand:SI 2 "const_int_operand" "n")
2255: (match_operand:SI 3 "const_int_operand" "n"))
2256: (const_int 0)))
2257: (clobber (reg:CC CC_REGNUM))]
2258: "TARGET_32BIT
2259: && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2260: && INTVAL (operands[2]) > 0
2261: && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2262: && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2263: "#"
2264: "TARGET_32BIT
2265: && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2266: && INTVAL (operands[2]) > 0
2267: && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2268: && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2269: [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2270: (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2271: (const_int 0)))
2272: (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2273: (set (match_dup 0)
2274: (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2275: (match_dup 0) (const_int 1)))]
2276: "
2277: operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2278: << INTVAL (operands[3]));
2279: "
2280: [(set_attr "conds" "clob")
2281: (set (attr "length")
2282: (if_then_else (eq_attr "is_thumb" "yes")
2283: (const_int 12)
1.5 mrg 2284: (const_int 8)))
2285: (set_attr "type" "multiple")]
1.1 mrg 2286: )
2287:
2288: (define_insn_and_split "*ne_zeroextractsi_shifted"
2289: [(set (match_operand:SI 0 "s_register_operand" "=r")
2290: (ne:SI (zero_extract:SI
2291: (match_operand:SI 1 "s_register_operand" "r")
2292: (match_operand:SI 2 "const_int_operand" "n")
2293: (const_int 0))
2294: (const_int 0)))
2295: (clobber (reg:CC CC_REGNUM))]
2296: "TARGET_ARM"
2297: "#"
2298: "TARGET_ARM"
2299: [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2300: (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2301: (const_int 0)))
2302: (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2303: (set (match_dup 0)
2304: (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2305: (match_dup 0) (const_int 1)))]
2306: "
2307: operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2308: "
2309: [(set_attr "conds" "clob")
1.5 mrg 2310: (set_attr "length" "8")
2311: (set_attr "type" "multiple")]
1.1 mrg 2312: )
2313:
2314: (define_insn_and_split "*ite_ne_zeroextractsi"
2315: [(set (match_operand:SI 0 "s_register_operand" "=r")
2316: (if_then_else:SI (ne (zero_extract:SI
2317: (match_operand:SI 1 "s_register_operand" "r")
2318: (match_operand:SI 2 "const_int_operand" "n")
2319: (match_operand:SI 3 "const_int_operand" "n"))
2320: (const_int 0))
2321: (match_operand:SI 4 "arm_not_operand" "rIK")
2322: (const_int 0)))
2323: (clobber (reg:CC CC_REGNUM))]
2324: "TARGET_ARM
2325: && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2326: && INTVAL (operands[2]) > 0
2327: && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2328: && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2329: && !reg_overlap_mentioned_p (operands[0], operands[4])"
2330: "#"
2331: "TARGET_ARM
2332: && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2333: && INTVAL (operands[2]) > 0
2334: && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2335: && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2336: && !reg_overlap_mentioned_p (operands[0], operands[4])"
2337: [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2338: (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2339: (const_int 0)))
2340: (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2341: (set (match_dup 0)
2342: (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2343: (match_dup 0) (match_dup 4)))]
2344: "
2345: operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2346: << INTVAL (operands[3]));
2347: "
2348: [(set_attr "conds" "clob")
1.5 mrg 2349: (set_attr "length" "8")
2350: (set_attr "type" "multiple")]
1.1 mrg 2351: )
2352:
2353: (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2354: [(set (match_operand:SI 0 "s_register_operand" "=r")
2355: (if_then_else:SI (ne (zero_extract:SI
2356: (match_operand:SI 1 "s_register_operand" "r")
2357: (match_operand:SI 2 "const_int_operand" "n")
2358: (const_int 0))
2359: (const_int 0))
2360: (match_operand:SI 3 "arm_not_operand" "rIK")
2361: (const_int 0)))
2362: (clobber (reg:CC CC_REGNUM))]
2363: "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2364: "#"
2365: "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2366: [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2367: (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2368: (const_int 0)))
2369: (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2370: (set (match_dup 0)
2371: (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2372: (match_dup 0) (match_dup 3)))]
2373: "
2374: operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2375: "
2376: [(set_attr "conds" "clob")
1.5 mrg 2377: (set_attr "length" "8")
2378: (set_attr "type" "multiple")]
1.1 mrg 2379: )
2380:
2381: ;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2382: (define_split
2383: [(set (match_operand:SI 0 "s_register_operand" "")
2384: (match_operator:SI 1 "shiftable_operator"
2385: [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2386: (match_operand:SI 3 "const_int_operand" "")
2387: (match_operand:SI 4 "const_int_operand" ""))
2388: (match_operand:SI 5 "s_register_operand" "")]))
2389: (clobber (match_operand:SI 6 "s_register_operand" ""))]
2390: "TARGET_ARM"
2391: [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2392: (set (match_dup 0)
2393: (match_op_dup 1
2394: [(lshiftrt:SI (match_dup 6) (match_dup 4))
2395: (match_dup 5)]))]
2396: "{
2397: HOST_WIDE_INT temp = INTVAL (operands[3]);
2398:
2399: operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2400: operands[4] = GEN_INT (32 - temp);
2401: }"
2402: )
2403:
2404: (define_split
2405: [(set (match_operand:SI 0 "s_register_operand" "")
2406: (match_operator:SI 1 "shiftable_operator"
2407: [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2408: (match_operand:SI 3 "const_int_operand" "")
2409: (match_operand:SI 4 "const_int_operand" ""))
2410: (match_operand:SI 5 "s_register_operand" "")]))
2411: (clobber (match_operand:SI 6 "s_register_operand" ""))]
2412: "TARGET_ARM"
2413: [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2414: (set (match_dup 0)
2415: (match_op_dup 1
2416: [(ashiftrt:SI (match_dup 6) (match_dup 4))
2417: (match_dup 5)]))]
2418: "{
2419: HOST_WIDE_INT temp = INTVAL (operands[3]);
2420:
2421: operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2422: operands[4] = GEN_INT (32 - temp);
2423: }"
2424: )
2425:
2426: ;;; ??? This pattern is bogus. If operand3 has bits outside the range
2427: ;;; represented by the bitfield, then this will produce incorrect results.
2428: ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
2429: ;;; which have a real bit-field insert instruction, the truncation happens
2430: ;;; in the bit-field insert instruction itself. Since arm does not have a
2431: ;;; bit-field insert instruction, we would have to emit code here to truncate
2432: ;;; the value before we insert. This loses some of the advantage of having
2433: ;;; this insv pattern, so this pattern needs to be reevalutated.
2434:
2435: (define_expand "insv"
1.3 mrg 2436: [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2437: (match_operand 1 "general_operand" "")
2438: (match_operand 2 "general_operand" ""))
2439: (match_operand 3 "reg_or_int_operand" ""))]
1.1 mrg 2440: "TARGET_ARM || arm_arch_thumb2"
2441: "
2442: {
2443: int start_bit = INTVAL (operands[2]);
2444: int width = INTVAL (operands[1]);
2445: HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2446: rtx target, subtarget;
2447:
2448: if (arm_arch_thumb2)
2449: {
1.3 mrg 2450: if (unaligned_access && MEM_P (operands[0])
2451: && s_register_operand (operands[3], GET_MODE (operands[3]))
2452: && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
2453: {
2454: rtx base_addr;
1.1 mrg 2455:
1.3 mrg 2456: if (BYTES_BIG_ENDIAN)
2457: start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2458: - start_bit;
1.1 mrg 2459:
1.3 mrg 2460: if (width == 32)
1.1 mrg 2461: {
1.3 mrg 2462: base_addr = adjust_address (operands[0], SImode,
2463: start_bit / BITS_PER_UNIT);
2464: emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
1.1 mrg 2465: }
1.3 mrg 2466: else
2467: {
2468: rtx tmp = gen_reg_rtx (HImode);
1.1 mrg 2469:
1.3 mrg 2470: base_addr = adjust_address (operands[0], HImode,
2471: start_bit / BITS_PER_UNIT);
2472: emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2473: emit_insn (gen_unaligned_storehi (base_addr, tmp));
2474: }
2475: DONE;
1.1 mrg 2476: }
1.3 mrg 2477: else if (s_register_operand (operands[0], GET_MODE (operands[0])))
1.1 mrg 2478: {
1.3 mrg 2479: bool use_bfi = TRUE;
2480:
2481: if (CONST_INT_P (operands[3]))
2482: {
2483: HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2484:
2485: if (val == 0)
2486: {
2487: emit_insn (gen_insv_zero (operands[0], operands[1],
2488: operands[2]));
2489: DONE;
2490: }
2491:
2492: /* See if the set can be done with a single orr instruction. */
2493: if (val == mask && const_ok_for_arm (val << start_bit))
2494: use_bfi = FALSE;
2495: }
2496:
2497: if (use_bfi)
2498: {
2499: if (!REG_P (operands[3]))
2500: operands[3] = force_reg (SImode, operands[3]);
1.1 mrg 2501:
1.3 mrg 2502: emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2503: operands[3]));
2504: DONE;
2505: }
1.1 mrg 2506: }
1.3 mrg 2507: else
2508: FAIL;
1.1 mrg 2509: }
2510:
1.3 mrg 2511: if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2512: FAIL;
2513:
1.1 mrg 2514: target = copy_rtx (operands[0]);
2515: /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2516: subreg as the final target. */
2517: if (GET_CODE (target) == SUBREG)
2518: {
2519: subtarget = gen_reg_rtx (SImode);
2520: if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2521: < GET_MODE_SIZE (SImode))
2522: target = SUBREG_REG (target);
2523: }
2524: else
2525: subtarget = target;
2526:
1.3 mrg 2527: if (CONST_INT_P (operands[3]))
1.1 mrg 2528: {
2529: /* Since we are inserting a known constant, we may be able to
2530: reduce the number of bits that we have to clear so that
2531: the mask becomes simple. */
2532: /* ??? This code does not check to see if the new mask is actually
2533: simpler. It may not be. */
2534: rtx op1 = gen_reg_rtx (SImode);
2535: /* ??? Truncate operand3 to fit in the bitfield. See comment before
2536: start of this pattern. */
2537: HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2538: HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2539:
2540: emit_insn (gen_andsi3 (op1, operands[0],
2541: gen_int_mode (~mask2, SImode)));
2542: emit_insn (gen_iorsi3 (subtarget, op1,
2543: gen_int_mode (op3_value << start_bit, SImode)));
2544: }
2545: else if (start_bit == 0
2546: && !(const_ok_for_arm (mask)
2547: || const_ok_for_arm (~mask)))
2548: {
2549: /* A Trick, since we are setting the bottom bits in the word,
2550: we can shift operand[3] up, operand[0] down, OR them together
2551: and rotate the result back again. This takes 3 insns, and
2552: the third might be mergeable into another op. */
2553: /* The shift up copes with the possibility that operand[3] is
2554: wider than the bitfield. */
2555: rtx op0 = gen_reg_rtx (SImode);
2556: rtx op1 = gen_reg_rtx (SImode);
2557:
2558: emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2559: emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2560: emit_insn (gen_iorsi3 (op1, op1, op0));
2561: emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2562: }
2563: else if ((width + start_bit == 32)
2564: && !(const_ok_for_arm (mask)
2565: || const_ok_for_arm (~mask)))
2566: {
2567: /* Similar trick, but slightly less efficient. */
2568:
2569: rtx op0 = gen_reg_rtx (SImode);
2570: rtx op1 = gen_reg_rtx (SImode);
2571:
2572: emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2573: emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2574: emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2575: emit_insn (gen_iorsi3 (subtarget, op1, op0));
2576: }
2577: else
2578: {
2579: rtx op0 = gen_int_mode (mask, SImode);
2580: rtx op1 = gen_reg_rtx (SImode);
2581: rtx op2 = gen_reg_rtx (SImode);
2582:
2583: if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2584: {
2585: rtx tmp = gen_reg_rtx (SImode);
2586:
2587: emit_insn (gen_movsi (tmp, op0));
2588: op0 = tmp;
2589: }
2590:
2591: /* Mask out any bits in operand[3] that are not needed. */
2592: emit_insn (gen_andsi3 (op1, operands[3], op0));
2593:
1.3 mrg 2594: if (CONST_INT_P (op0)
1.1 mrg 2595: && (const_ok_for_arm (mask << start_bit)
2596: || const_ok_for_arm (~(mask << start_bit))))
2597: {
2598: op0 = gen_int_mode (~(mask << start_bit), SImode);
2599: emit_insn (gen_andsi3 (op2, operands[0], op0));
2600: }
2601: else
2602: {
1.3 mrg 2603: if (CONST_INT_P (op0))
1.1 mrg 2604: {
2605: rtx tmp = gen_reg_rtx (SImode);
2606:
2607: emit_insn (gen_movsi (tmp, op0));
2608: op0 = tmp;
2609: }
2610:
2611: if (start_bit != 0)
2612: emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2613:
2614: emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2615: }
2616:
2617: if (start_bit != 0)
2618: emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2619:
2620: emit_insn (gen_iorsi3 (subtarget, op1, op2));
2621: }
2622:
2623: if (subtarget != target)
2624: {
2625: /* If TARGET is still a SUBREG, then it must be wider than a word,
2626: so we must be careful only to set the subword we were asked to. */
2627: if (GET_CODE (target) == SUBREG)
2628: emit_move_insn (target, subtarget);
2629: else
2630: emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2631: }
2632:
2633: DONE;
2634: }"
2635: )
2636:
2637: (define_insn "insv_zero"
2638: [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
1.5 mrg 2639: (match_operand:SI 1 "const_int_M_operand" "M")
2640: (match_operand:SI 2 "const_int_M_operand" "M"))
1.1 mrg 2641: (const_int 0))]
2642: "arm_arch_thumb2"
2643: "bfc%?\t%0, %2, %1"
2644: [(set_attr "length" "4")
1.5 mrg 2645: (set_attr "predicable" "yes")
2646: (set_attr "predicable_short_it" "no")
2647: (set_attr "type" "bfm")]
1.1 mrg 2648: )
2649:
2650: (define_insn "insv_t2"
2651: [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
1.5 mrg 2652: (match_operand:SI 1 "const_int_M_operand" "M")
2653: (match_operand:SI 2 "const_int_M_operand" "M"))
1.1 mrg 2654: (match_operand:SI 3 "s_register_operand" "r"))]
2655: "arm_arch_thumb2"
2656: "bfi%?\t%0, %3, %2, %1"
2657: [(set_attr "length" "4")
1.5 mrg 2658: (set_attr "predicable" "yes")
2659: (set_attr "predicable_short_it" "no")
2660: (set_attr "type" "bfm")]
1.1 mrg 2661: )
2662:
2663: ; constants for op 2 will never be given to these patterns.
2664: (define_insn_and_split "*anddi_notdi_di"
2665: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2666: (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2667: (match_operand:DI 2 "s_register_operand" "r,0")))]
2668: "TARGET_32BIT"
2669: "#"
1.3 mrg 2670: "TARGET_32BIT && reload_completed
2671: && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2672: && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1.1 mrg 2673: [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2674: (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2675: "
2676: {
2677: operands[3] = gen_highpart (SImode, operands[0]);
2678: operands[0] = gen_lowpart (SImode, operands[0]);
2679: operands[4] = gen_highpart (SImode, operands[1]);
2680: operands[1] = gen_lowpart (SImode, operands[1]);
2681: operands[5] = gen_highpart (SImode, operands[2]);
2682: operands[2] = gen_lowpart (SImode, operands[2]);
2683: }"
2684: [(set_attr "length" "8")
1.5 mrg 2685: (set_attr "predicable" "yes")
2686: (set_attr "type" "multiple")]
1.1 mrg 2687: )
1.5 mrg 2688:
1.1 mrg 2689: (define_insn_and_split "*anddi_notzesidi_di"
2690: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2691: (and:DI (not:DI (zero_extend:DI
2692: (match_operand:SI 2 "s_register_operand" "r,r")))
2693: (match_operand:DI 1 "s_register_operand" "0,?r")))]
2694: "TARGET_32BIT"
2695: "@
2696: bic%?\\t%Q0, %Q1, %2
2697: #"
2698: ; (not (zero_extend ...)) allows us to just copy the high word from
2699: ; operand1 to operand0.
2700: "TARGET_32BIT
2701: && reload_completed
2702: && operands[0] != operands[1]"
2703: [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2704: (set (match_dup 3) (match_dup 4))]
2705: "
2706: {
2707: operands[3] = gen_highpart (SImode, operands[0]);
2708: operands[0] = gen_lowpart (SImode, operands[0]);
2709: operands[4] = gen_highpart (SImode, operands[1]);
2710: operands[1] = gen_lowpart (SImode, operands[1]);
2711: }"
2712: [(set_attr "length" "4,8")
1.5 mrg 2713: (set_attr "predicable" "yes")
2714: (set_attr "predicable_short_it" "no")
2715: (set_attr "type" "multiple")]
2716: )
2717:
2718: (define_insn_and_split "*anddi_notdi_zesidi"
2719: [(set (match_operand:DI 0 "s_register_operand" "=r")
2720: (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r"))
2721: (zero_extend:DI
2722: (match_operand:SI 1 "s_register_operand" "r"))))]
2723: "TARGET_32BIT"
2724: "#"
2725: "TARGET_32BIT && reload_completed"
2726: [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2727: (set (match_dup 3) (const_int 0))]
2728: "
2729: {
2730: operands[3] = gen_highpart (SImode, operands[0]);
2731: operands[0] = gen_lowpart (SImode, operands[0]);
2732: operands[2] = gen_lowpart (SImode, operands[2]);
2733: }"
2734: [(set_attr "length" "8")
2735: (set_attr "predicable" "yes")
2736: (set_attr "predicable_short_it" "no")
2737: (set_attr "type" "multiple")]
1.1 mrg 2738: )
1.5 mrg 2739:
1.1 mrg 2740: (define_insn_and_split "*anddi_notsesidi_di"
2741: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2742: (and:DI (not:DI (sign_extend:DI
2743: (match_operand:SI 2 "s_register_operand" "r,r")))
2744: (match_operand:DI 1 "s_register_operand" "0,r")))]
2745: "TARGET_32BIT"
2746: "#"
2747: "TARGET_32BIT && reload_completed"
2748: [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2749: (set (match_dup 3) (and:SI (not:SI
2750: (ashiftrt:SI (match_dup 2) (const_int 31)))
2751: (match_dup 4)))]
2752: "
2753: {
2754: operands[3] = gen_highpart (SImode, operands[0]);
2755: operands[0] = gen_lowpart (SImode, operands[0]);
2756: operands[4] = gen_highpart (SImode, operands[1]);
2757: operands[1] = gen_lowpart (SImode, operands[1]);
2758: }"
2759: [(set_attr "length" "8")
1.5 mrg 2760: (set_attr "predicable" "yes")
2761: (set_attr "predicable_short_it" "no")
2762: (set_attr "type" "multiple")]
1.1 mrg 2763: )
1.5 mrg 2764:
1.1 mrg 2765: (define_insn "andsi_notsi_si"
2766: [(set (match_operand:SI 0 "s_register_operand" "=r")
2767: (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2768: (match_operand:SI 1 "s_register_operand" "r")))]
2769: "TARGET_32BIT"
2770: "bic%?\\t%0, %1, %2"
1.5 mrg 2771: [(set_attr "predicable" "yes")
2772: (set_attr "predicable_short_it" "no")
2773: (set_attr "type" "logic_reg")]
1.1 mrg 2774: )
2775:
2776: (define_insn "andsi_not_shiftsi_si"
2777: [(set (match_operand:SI 0 "s_register_operand" "=r")
2778: (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2779: [(match_operand:SI 2 "s_register_operand" "r")
2780: (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2781: (match_operand:SI 1 "s_register_operand" "r")))]
2782: "TARGET_ARM"
2783: "bic%?\\t%0, %1, %2%S4"
2784: [(set_attr "predicable" "yes")
2785: (set_attr "shift" "2")
2786: (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
1.5 mrg 2787: (const_string "logic_shift_imm")
2788: (const_string "logic_shift_reg")))]
1.1 mrg 2789: )
2790:
1.7 ! mrg 2791: ;; Shifted bics pattern used to set up CC status register and not reusing
! 2792: ;; bics output. Pattern restricts Thumb2 shift operand as bics for Thumb2
! 2793: ;; does not support shift by register.
! 2794: (define_insn "andsi_not_shiftsi_si_scc_no_reuse"
! 2795: [(set (reg:CC_NOOV CC_REGNUM)
! 2796: (compare:CC_NOOV
! 2797: (and:SI (not:SI (match_operator:SI 0 "shift_operator"
! 2798: [(match_operand:SI 1 "s_register_operand" "r")
! 2799: (match_operand:SI 2 "arm_rhs_operand" "rM")]))
! 2800: (match_operand:SI 3 "s_register_operand" "r"))
! 2801: (const_int 0)))
! 2802: (clobber (match_scratch:SI 4 "=r"))]
! 2803: "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
! 2804: "bics%?\\t%4, %3, %1%S0"
! 2805: [(set_attr "predicable" "yes")
! 2806: (set_attr "predicable_short_it" "no")
! 2807: (set_attr "conds" "set")
! 2808: (set_attr "shift" "1")
! 2809: (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
! 2810: (const_string "logic_shift_imm")
! 2811: (const_string "logic_shift_reg")))]
! 2812: )
! 2813:
! 2814: ;; Same as andsi_not_shiftsi_si_scc_no_reuse, but the bics result is also
! 2815: ;; getting reused later.
! 2816: (define_insn "andsi_not_shiftsi_si_scc"
! 2817: [(parallel [(set (reg:CC_NOOV CC_REGNUM)
! 2818: (compare:CC_NOOV
! 2819: (and:SI (not:SI (match_operator:SI 0 "shift_operator"
! 2820: [(match_operand:SI 1 "s_register_operand" "r")
! 2821: (match_operand:SI 2 "arm_rhs_operand" "rM")]))
! 2822: (match_operand:SI 3 "s_register_operand" "r"))
! 2823: (const_int 0)))
! 2824: (set (match_operand:SI 4 "s_register_operand" "=r")
! 2825: (and:SI (not:SI (match_op_dup 0
! 2826: [(match_dup 1)
! 2827: (match_dup 2)]))
! 2828: (match_dup 3)))])]
! 2829: "TARGET_ARM || (TARGET_THUMB2 && CONST_INT_P (operands[2]))"
! 2830: "bics%?\\t%4, %3, %1%S0"
! 2831: [(set_attr "predicable" "yes")
! 2832: (set_attr "predicable_short_it" "no")
! 2833: (set_attr "conds" "set")
! 2834: (set_attr "shift" "1")
! 2835: (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
! 2836: (const_string "logic_shift_imm")
! 2837: (const_string "logic_shift_reg")))]
! 2838: )
! 2839:
1.1 mrg 2840: (define_insn "*andsi_notsi_si_compare0"
2841: [(set (reg:CC_NOOV CC_REGNUM)
2842: (compare:CC_NOOV
2843: (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2844: (match_operand:SI 1 "s_register_operand" "r"))
2845: (const_int 0)))
2846: (set (match_operand:SI 0 "s_register_operand" "=r")
2847: (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2848: "TARGET_32BIT"
1.7 ! mrg 2849: "bics\\t%0, %1, %2"
1.5 mrg 2850: [(set_attr "conds" "set")
2851: (set_attr "type" "logics_shift_reg")]
1.1 mrg 2852: )
2853:
2854: (define_insn "*andsi_notsi_si_compare0_scratch"
2855: [(set (reg:CC_NOOV CC_REGNUM)
2856: (compare:CC_NOOV
2857: (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2858: (match_operand:SI 1 "s_register_operand" "r"))
2859: (const_int 0)))
2860: (clobber (match_scratch:SI 0 "=r"))]
2861: "TARGET_32BIT"
1.7 ! mrg 2862: "bics\\t%0, %1, %2"
1.5 mrg 2863: [(set_attr "conds" "set")
2864: (set_attr "type" "logics_shift_reg")]
1.1 mrg 2865: )
2866:
1.3 mrg 2867: (define_expand "iordi3"
2868: [(set (match_operand:DI 0 "s_register_operand" "")
2869: (ior:DI (match_operand:DI 1 "s_register_operand" "")
2870: (match_operand:DI 2 "neon_logic_op2" "")))]
2871: "TARGET_32BIT"
2872: ""
2873: )
2874:
1.5 mrg 2875: (define_insn_and_split "*iordi3_insn"
2876: [(set (match_operand:DI 0 "s_register_operand" "=w,w ,&r,&r,&r,&r,?w,?w")
2877: (ior:DI (match_operand:DI 1 "s_register_operand" "%w,0 ,0 ,r ,0 ,r ,w ,0")
2878: (match_operand:DI 2 "arm_iordi_operand_neon" "w ,Dl,r ,r ,Df,Df,w ,Dl")))]
2879: "TARGET_32BIT && !TARGET_IWMMXT"
2880: {
2881: switch (which_alternative)
2882: {
2883: case 0: /* fall through */
2884: case 6: return "vorr\t%P0, %P1, %P2";
2885: case 1: /* fall through */
2886: case 7: return neon_output_logic_immediate ("vorr", &operands[2],
2887: DImode, 0, VALID_NEON_QREG_MODE (DImode));
2888: case 2:
2889: case 3:
2890: case 4:
2891: case 5:
2892: return "#";
2893: default: gcc_unreachable ();
2894: }
2895: }
2896: "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
2897: && !(IS_VFP_REGNUM (REGNO (operands[0])))"
2898: [(set (match_dup 3) (match_dup 4))
2899: (set (match_dup 5) (match_dup 6))]
2900: "
2901: {
2902: operands[3] = gen_lowpart (SImode, operands[0]);
2903: operands[5] = gen_highpart (SImode, operands[0]);
2904:
2905: operands[4] = simplify_gen_binary (IOR, SImode,
2906: gen_lowpart (SImode, operands[1]),
2907: gen_lowpart (SImode, operands[2]));
2908: operands[6] = simplify_gen_binary (IOR, SImode,
2909: gen_highpart (SImode, operands[1]),
2910: gen_highpart_mode (SImode, DImode, operands[2]));
2911:
2912: }"
2913: [(set_attr "type" "neon_logic,neon_logic,multiple,multiple,multiple,\
2914: multiple,neon_logic,neon_logic")
2915: (set_attr "length" "*,*,8,8,8,8,*,*")
2916: (set_attr "arch" "neon_for_64bits,neon_for_64bits,*,*,*,*,avoid_neon_for_64bits,avoid_neon_for_64bits")]
1.1 mrg 2917: )
2918:
2919: (define_insn "*iordi_zesidi_di"
2920: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2921: (ior:DI (zero_extend:DI
2922: (match_operand:SI 2 "s_register_operand" "r,r"))
2923: (match_operand:DI 1 "s_register_operand" "0,?r")))]
2924: "TARGET_32BIT"
2925: "@
2926: orr%?\\t%Q0, %Q1, %2
2927: #"
2928: [(set_attr "length" "4,8")
1.5 mrg 2929: (set_attr "predicable" "yes")
2930: (set_attr "predicable_short_it" "no")
2931: (set_attr "type" "logic_reg,multiple")]
1.1 mrg 2932: )
2933:
2934: (define_insn "*iordi_sesidi_di"
2935: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2936: (ior:DI (sign_extend:DI
2937: (match_operand:SI 2 "s_register_operand" "r,r"))
2938: (match_operand:DI 1 "s_register_operand" "0,r")))]
2939: "TARGET_32BIT"
2940: "#"
2941: [(set_attr "length" "8")
1.5 mrg 2942: (set_attr "predicable" "yes")
2943: (set_attr "type" "multiple")]
1.1 mrg 2944: )
2945:
2946: (define_expand "iorsi3"
2947: [(set (match_operand:SI 0 "s_register_operand" "")
2948: (ior:SI (match_operand:SI 1 "s_register_operand" "")
2949: (match_operand:SI 2 "reg_or_int_operand" "")))]
2950: "TARGET_EITHER"
2951: "
1.3 mrg 2952: if (CONST_INT_P (operands[2]))
1.1 mrg 2953: {
2954: if (TARGET_32BIT)
2955: {
1.7 ! mrg 2956: if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), IOR))
! 2957: operands[2] = force_reg (SImode, operands[2]);
! 2958: else
! 2959: {
! 2960: arm_split_constant (IOR, SImode, NULL_RTX,
! 2961: INTVAL (operands[2]), operands[0],
! 2962: operands[1],
! 2963: optimize && can_create_pseudo_p ());
! 2964: DONE;
! 2965: }
1.1 mrg 2966: }
2967: else /* TARGET_THUMB1 */
2968: {
2969: rtx tmp = force_reg (SImode, operands[2]);
2970: if (rtx_equal_p (operands[0], operands[1]))
2971: operands[2] = tmp;
2972: else
2973: {
2974: operands[2] = operands[1];
2975: operands[1] = tmp;
2976: }
2977: }
2978: }
2979: "
2980: )
2981:
1.3 mrg 2982: (define_insn_and_split "*iorsi3_insn"
1.5 mrg 2983: [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r,r")
2984: (ior:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r,r")
2985: (match_operand:SI 2 "reg_or_int_operand" "I,l,K,r,?n")))]
1.3 mrg 2986: "TARGET_32BIT"
1.1 mrg 2987: "@
2988: orr%?\\t%0, %1, %2
1.5 mrg 2989: orr%?\\t%0, %1, %2
1.3 mrg 2990: orn%?\\t%0, %1, #%B2
2991: orr%?\\t%0, %1, %2
1.1 mrg 2992: #"
1.3 mrg 2993: "TARGET_32BIT
2994: && CONST_INT_P (operands[2])
2995: && !(const_ok_for_arm (INTVAL (operands[2]))
2996: || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
1.1 mrg 2997: [(clobber (const_int 0))]
1.3 mrg 2998: {
1.5 mrg 2999: arm_split_constant (IOR, SImode, curr_insn,
1.1 mrg 3000: INTVAL (operands[2]), operands[0], operands[1], 0);
3001: DONE;
1.3 mrg 3002: }
1.5 mrg 3003: [(set_attr "length" "4,4,4,4,16")
3004: (set_attr "arch" "32,t2,t2,32,32")
1.3 mrg 3005: (set_attr "predicable" "yes")
1.5 mrg 3006: (set_attr "predicable_short_it" "no,yes,no,no,no")
3007: (set_attr "type" "logic_imm,logic_reg,logic_imm,logic_reg,logic_reg")]
1.1 mrg 3008: )
3009:
3010: (define_peephole2
3011: [(match_scratch:SI 3 "r")
3012: (set (match_operand:SI 0 "arm_general_register_operand" "")
3013: (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
3014: (match_operand:SI 2 "const_int_operand" "")))]
3015: "TARGET_ARM
3016: && !const_ok_for_arm (INTVAL (operands[2]))
3017: && const_ok_for_arm (~INTVAL (operands[2]))"
3018: [(set (match_dup 3) (match_dup 2))
3019: (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
3020: ""
3021: )
3022:
3023: (define_insn "*iorsi3_compare0"
3024: [(set (reg:CC_NOOV CC_REGNUM)
1.3 mrg 3025: (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3026: (match_operand:SI 2 "arm_rhs_operand" "I,r"))
1.1 mrg 3027: (const_int 0)))
1.3 mrg 3028: (set (match_operand:SI 0 "s_register_operand" "=r,r")
1.1 mrg 3029: (ior:SI (match_dup 1) (match_dup 2)))]
3030: "TARGET_32BIT"
1.7 ! mrg 3031: "orrs%?\\t%0, %1, %2"
1.3 mrg 3032: [(set_attr "conds" "set")
1.5 mrg 3033: (set_attr "type" "logics_imm,logics_reg")]
1.1 mrg 3034: )
3035:
3036: (define_insn "*iorsi3_compare0_scratch"
3037: [(set (reg:CC_NOOV CC_REGNUM)
1.3 mrg 3038: (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3039: (match_operand:SI 2 "arm_rhs_operand" "I,r"))
1.1 mrg 3040: (const_int 0)))
1.3 mrg 3041: (clobber (match_scratch:SI 0 "=r,r"))]
1.1 mrg 3042: "TARGET_32BIT"
1.7 ! mrg 3043: "orrs%?\\t%0, %1, %2"
1.3 mrg 3044: [(set_attr "conds" "set")
1.5 mrg 3045: (set_attr "type" "logics_imm,logics_reg")]
1.1 mrg 3046: )
3047:
1.3 mrg 3048: (define_expand "xordi3"
3049: [(set (match_operand:DI 0 "s_register_operand" "")
3050: (xor:DI (match_operand:DI 1 "s_register_operand" "")
1.5 mrg 3051: (match_operand:DI 2 "arm_xordi_operand" "")))]
1.3 mrg 3052: "TARGET_32BIT"
3053: ""
3054: )
3055:
1.5 mrg 3056: (define_insn_and_split "*xordi3_insn"
3057: [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,&r,&r,?w")
3058: (xor:DI (match_operand:DI 1 "s_register_operand" "%w ,0,r ,0 ,r ,w")
3059: (match_operand:DI 2 "arm_xordi_operand" "w ,r ,r ,Dg,Dg,w")))]
3060: "TARGET_32BIT && !TARGET_IWMMXT"
3061: {
3062: switch (which_alternative)
3063: {
3064: case 1:
3065: case 2:
3066: case 3:
3067: case 4: /* fall through */
3068: return "#";
3069: case 0: /* fall through */
3070: case 5: return "veor\t%P0, %P1, %P2";
3071: default: gcc_unreachable ();
3072: }
3073: }
3074: "TARGET_32BIT && !TARGET_IWMMXT && reload_completed
3075: && !(IS_VFP_REGNUM (REGNO (operands[0])))"
3076: [(set (match_dup 3) (match_dup 4))
3077: (set (match_dup 5) (match_dup 6))]
3078: "
3079: {
3080: operands[3] = gen_lowpart (SImode, operands[0]);
3081: operands[5] = gen_highpart (SImode, operands[0]);
3082:
3083: operands[4] = simplify_gen_binary (XOR, SImode,
3084: gen_lowpart (SImode, operands[1]),
3085: gen_lowpart (SImode, operands[2]));
3086: operands[6] = simplify_gen_binary (XOR, SImode,
3087: gen_highpart (SImode, operands[1]),
3088: gen_highpart_mode (SImode, DImode, operands[2]));
3089:
3090: }"
3091: [(set_attr "length" "*,8,8,8,8,*")
3092: (set_attr "type" "neon_logic,multiple,multiple,multiple,multiple,neon_logic")
3093: (set_attr "arch" "neon_for_64bits,*,*,*,*,avoid_neon_for_64bits")]
1.1 mrg 3094: )
3095:
3096: (define_insn "*xordi_zesidi_di"
3097: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3098: (xor:DI (zero_extend:DI
3099: (match_operand:SI 2 "s_register_operand" "r,r"))
3100: (match_operand:DI 1 "s_register_operand" "0,?r")))]
3101: "TARGET_32BIT"
3102: "@
3103: eor%?\\t%Q0, %Q1, %2
3104: #"
3105: [(set_attr "length" "4,8")
1.5 mrg 3106: (set_attr "predicable" "yes")
3107: (set_attr "predicable_short_it" "no")
3108: (set_attr "type" "logic_reg")]
1.1 mrg 3109: )
3110:
3111: (define_insn "*xordi_sesidi_di"
3112: [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3113: (xor:DI (sign_extend:DI
3114: (match_operand:SI 2 "s_register_operand" "r,r"))
3115: (match_operand:DI 1 "s_register_operand" "0,r")))]
3116: "TARGET_32BIT"
3117: "#"
3118: [(set_attr "length" "8")
1.5 mrg 3119: (set_attr "predicable" "yes")
3120: (set_attr "type" "multiple")]
1.1 mrg 3121: )
3122:
3123: (define_expand "xorsi3"
3124: [(set (match_operand:SI 0 "s_register_operand" "")
3125: (xor:SI (match_operand:SI 1 "s_register_operand" "")
3126: (match_operand:SI 2 "reg_or_int_operand" "")))]
3127: "TARGET_EITHER"
1.3 mrg 3128: "if (CONST_INT_P (operands[2]))
1.1 mrg 3129: {
3130: if (TARGET_32BIT)
3131: {
1.7 ! mrg 3132: if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[2]), XOR))
! 3133: operands[2] = force_reg (SImode, operands[2]);
! 3134: else
! 3135: {
! 3136: arm_split_constant (XOR, SImode, NULL_RTX,
! 3137: INTVAL (operands[2]), operands[0],
! 3138: operands[1],
! 3139: optimize && can_create_pseudo_p ());
! 3140: DONE;
! 3141: }
1.1 mrg 3142: }
3143: else /* TARGET_THUMB1 */
3144: {
3145: rtx tmp = force_reg (SImode, operands[2]);
3146: if (rtx_equal_p (operands[0], operands[1]))
3147: operands[2] = tmp;
3148: else
3149: {
3150: operands[2] = operands[1];
3151: operands[1] = tmp;
3152: }
3153: }
3154: }"
3155: )
3156:
1.3 mrg 3157: (define_insn_and_split "*arm_xorsi3"
1.5 mrg 3158: [(set (match_operand:SI 0 "s_register_operand" "=r,l,r,r")
3159: (xor:SI (match_operand:SI 1 "s_register_operand" "%r,0,r,r")
3160: (match_operand:SI 2 "reg_or_int_operand" "I,l,r,?n")))]
1.1 mrg 3161: "TARGET_32BIT"
1.3 mrg 3162: "@
3163: eor%?\\t%0, %1, %2
3164: eor%?\\t%0, %1, %2
1.5 mrg 3165: eor%?\\t%0, %1, %2
1.3 mrg 3166: #"
3167: "TARGET_32BIT
3168: && CONST_INT_P (operands[2])
3169: && !const_ok_for_arm (INTVAL (operands[2]))"
3170: [(clobber (const_int 0))]
3171: {
3172: arm_split_constant (XOR, SImode, curr_insn,
3173: INTVAL (operands[2]), operands[0], operands[1], 0);
3174: DONE;
3175: }
1.5 mrg 3176: [(set_attr "length" "4,4,4,16")
1.3 mrg 3177: (set_attr "predicable" "yes")
1.5 mrg 3178: (set_attr "predicable_short_it" "no,yes,no,no")
3179: (set_attr "type" "logic_imm,logic_reg,logic_reg,multiple")]
1.1 mrg 3180: )
3181:
3182: (define_insn "*xorsi3_compare0"
3183: [(set (reg:CC_NOOV CC_REGNUM)
1.3 mrg 3184: (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r,r")
3185: (match_operand:SI 2 "arm_rhs_operand" "I,r"))
1.1 mrg 3186: (const_int 0)))
1.3 mrg 3187: (set (match_operand:SI 0 "s_register_operand" "=r,r")
1.1 mrg 3188: (xor:SI (match_dup 1) (match_dup 2)))]
3189: "TARGET_32BIT"
1.7 ! mrg 3190: "eors%?\\t%0, %1, %2"
1.3 mrg 3191: [(set_attr "conds" "set")
1.5 mrg 3192: (set_attr "type" "logics_imm,logics_reg")]
1.1 mrg 3193: )
3194:
3195: (define_insn "*xorsi3_compare0_scratch"
3196: [(set (reg:CC_NOOV CC_REGNUM)
1.3 mrg 3197: (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r,r")
3198: (match_operand:SI 1 "arm_rhs_operand" "I,r"))
1.1 mrg 3199: (const_int 0)))]
3200: "TARGET_32BIT"
3201: "teq%?\\t%0, %1"
1.3 mrg 3202: [(set_attr "conds" "set")
1.5 mrg 3203: (set_attr "type" "logics_imm,logics_reg")]
1.1 mrg 3204: )
3205:
3206: ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3207: ; (NOT D) we can sometimes merge the final NOT into one of the following
3208: ; insns.
3209:
3210: (define_split
3211: [(set (match_operand:SI 0 "s_register_operand" "")
3212: (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3213: (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3214: (match_operand:SI 3 "arm_rhs_operand" "")))
3215: (clobber (match_operand:SI 4 "s_register_operand" ""))]
3216: "TARGET_32BIT"
3217: [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3218: (not:SI (match_dup 3))))
3219: (set (match_dup 0) (not:SI (match_dup 4)))]
3220: ""
3221: )
3222:
1.5 mrg 3223: (define_insn_and_split "*andsi_iorsi3_notsi"
1.1 mrg 3224: [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3225: (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3226: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3227: (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3228: "TARGET_32BIT"
1.5 mrg 3229: "#" ; "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3230: "&& reload_completed"
3231: [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
3232: (set (match_dup 0) (and:SI (match_dup 4) (match_dup 5)))]
3233: {
3234: /* If operands[3] is a constant make sure to fold the NOT into it
3235: to avoid creating a NOT of a CONST_INT. */
3236: rtx not_rtx = simplify_gen_unary (NOT, SImode, operands[3], SImode);
3237: if (CONST_INT_P (not_rtx))
3238: {
3239: operands[4] = operands[0];
3240: operands[5] = not_rtx;
3241: }
3242: else
3243: {
3244: operands[5] = operands[0];
3245: operands[4] = not_rtx;
3246: }
3247: }
1.1 mrg 3248: [(set_attr "length" "8")
3249: (set_attr "ce_count" "2")
1.5 mrg 3250: (set_attr "predicable" "yes")
3251: (set_attr "predicable_short_it" "no")
3252: (set_attr "type" "multiple")]
1.1 mrg 3253: )
3254:
3255: ; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3256: ; insns are available?
3257: (define_split
3258: [(set (match_operand:SI 0 "s_register_operand" "")
3259: (match_operator:SI 1 "logical_binary_operator"
3260: [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3261: (match_operand:SI 3 "const_int_operand" "")
3262: (match_operand:SI 4 "const_int_operand" ""))
3263: (match_operator:SI 9 "logical_binary_operator"
3264: [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3265: (match_operand:SI 6 "const_int_operand" ""))
3266: (match_operand:SI 7 "s_register_operand" "")])]))
3267: (clobber (match_operand:SI 8 "s_register_operand" ""))]
3268: "TARGET_32BIT
3269: && GET_CODE (operands[1]) == GET_CODE (operands[9])
3270: && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3271: [(set (match_dup 8)
3272: (match_op_dup 1
3273: [(ashift:SI (match_dup 2) (match_dup 4))
3274: (match_dup 5)]))
3275: (set (match_dup 0)
3276: (match_op_dup 1
3277: [(lshiftrt:SI (match_dup 8) (match_dup 6))
3278: (match_dup 7)]))]
3279: "
3280: operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3281: ")
3282:
3283: (define_split
3284: [(set (match_operand:SI 0 "s_register_operand" "")
3285: (match_operator:SI 1 "logical_binary_operator"
3286: [(match_operator:SI 9 "logical_binary_operator"
3287: [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3288: (match_operand:SI 6 "const_int_operand" ""))
3289: (match_operand:SI 7 "s_register_operand" "")])
3290: (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3291: (match_operand:SI 3 "const_int_operand" "")
3292: (match_operand:SI 4 "const_int_operand" ""))]))
3293: (clobber (match_operand:SI 8 "s_register_operand" ""))]
3294: "TARGET_32BIT
3295: && GET_CODE (operands[1]) == GET_CODE (operands[9])
3296: && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3297: [(set (match_dup 8)
3298: (match_op_dup 1
3299: [(ashift:SI (match_dup 2) (match_dup 4))
3300: (match_dup 5)]))
3301: (set (match_dup 0)
3302: (match_op_dup 1
3303: [(lshiftrt:SI (match_dup 8) (match_dup 6))
3304: (match_dup 7)]))]
3305: "
3306: operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3307: ")
3308:
3309: (define_split
3310: [(set (match_operand:SI 0 "s_register_operand" "")
3311: (match_operator:SI 1 "logical_binary_operator"
3312: [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3313: (match_operand:SI 3 "const_int_operand" "")
3314: (match_operand:SI 4 "const_int_operand" ""))
3315: (match_operator:SI 9 "logical_binary_operator"
3316: [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3317: (match_operand:SI 6 "const_int_operand" ""))
3318: (match_operand:SI 7 "s_register_operand" "")])]))
3319: (clobber (match_operand:SI 8 "s_register_operand" ""))]
3320: "TARGET_32BIT
3321: && GET_CODE (operands[1]) == GET_CODE (operands[9])
3322: && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3323: [(set (match_dup 8)
3324: (match_op_dup 1
3325: [(ashift:SI (match_dup 2) (match_dup 4))
3326: (match_dup 5)]))
3327: (set (match_dup 0)
3328: (match_op_dup 1
3329: [(ashiftrt:SI (match_dup 8) (match_dup 6))
3330: (match_dup 7)]))]
3331: "
3332: operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3333: ")
3334:
3335: (define_split
3336: [(set (match_operand:SI 0 "s_register_operand" "")
3337: (match_operator:SI 1 "logical_binary_operator"
3338: [(match_operator:SI 9 "logical_binary_operator"
3339: [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3340: (match_operand:SI 6 "const_int_operand" ""))
3341: (match_operand:SI 7 "s_register_operand" "")])
3342: (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3343: (match_operand:SI 3 "const_int_operand" "")
3344: (match_operand:SI 4 "const_int_operand" ""))]))
3345: (clobber (match_operand:SI 8 "s_register_operand" ""))]
3346: "TARGET_32BIT
3347: && GET_CODE (operands[1]) == GET_CODE (operands[9])
3348: && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3349: [(set (match_dup 8)
3350: (match_op_dup 1
3351: [(ashift:SI (match_dup 2) (match_dup 4))
3352: (match_dup 5)]))
3353: (set (match_dup 0)
3354: (match_op_dup 1
3355: [(ashiftrt:SI (match_dup 8) (match_dup 6))
3356: (match_dup 7)]))]
3357: "
3358: operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3359: ")
3360:
3361:
3362: ;; Minimum and maximum insns
3363:
3364: (define_expand "smaxsi3"
3365: [(parallel [
3366: (set (match_operand:SI 0 "s_register_operand" "")
3367: (smax:SI (match_operand:SI 1 "s_register_operand" "")
3368: (match_operand:SI 2 "arm_rhs_operand" "")))
3369: (clobber (reg:CC CC_REGNUM))])]
3370: "TARGET_32BIT"
3371: "
3372: if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3373: {
3374: /* No need for a clobber of the condition code register here. */
1.7 ! mrg 3375: emit_insn (gen_rtx_SET (operands[0],
1.1 mrg 3376: gen_rtx_SMAX (SImode, operands[1],
3377: operands[2])));
3378: DONE;
3379: }
3380: ")
3381:
3382: (define_insn "*smax_0"
3383: [(set (match_operand:SI 0 "s_register_operand" "=r")
3384: (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3385: (const_int 0)))]
3386: "TARGET_32BIT"
3387: "bic%?\\t%0, %1, %1, asr #31"
1.5 mrg 3388: [(set_attr "predicable" "yes")
3389: (set_attr "predicable_short_it" "no")
3390: (set_attr "type" "logic_shift_reg")]
1.1 mrg 3391: )
3392:
3393: (define_insn "*smax_m1"
3394: [(set (match_operand:SI 0 "s_register_operand" "=r")
3395: (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3396: (const_int -1)))]
3397: "TARGET_32BIT"
3398: "orr%?\\t%0, %1, %1, asr #31"
1.5 mrg 3399: [(set_attr "predicable" "yes")
3400: (set_attr "predicable_short_it" "no")
3401: (set_attr "type" "logic_shift_reg")]
1.1 mrg 3402: )
3403:
1.5 mrg 3404: (define_insn_and_split "*arm_smax_insn"
1.1 mrg 3405: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3406: (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3407: (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3408: (clobber (reg:CC CC_REGNUM))]
3409: "TARGET_ARM"
1.5 mrg 3410: "#"
3411: ; cmp\\t%1, %2\;movlt\\t%0, %2
3412: ; cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3413: "TARGET_ARM"
3414: [(set (reg:CC CC_REGNUM)
3415: (compare:CC (match_dup 1) (match_dup 2)))
3416: (set (match_dup 0)
3417: (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
3418: (match_dup 1)
3419: (match_dup 2)))]
3420: ""
1.1 mrg 3421: [(set_attr "conds" "clob")
1.5 mrg 3422: (set_attr "length" "8,12")
3423: (set_attr "type" "multiple")]
1.1 mrg 3424: )
3425:
3426: (define_expand "sminsi3"
3427: [(parallel [
3428: (set (match_operand:SI 0 "s_register_operand" "")
3429: (smin:SI (match_operand:SI 1 "s_register_operand" "")
3430: (match_operand:SI 2 "arm_rhs_operand" "")))
3431: (clobber (reg:CC CC_REGNUM))])]
3432: "TARGET_32BIT"
3433: "
3434: if (operands[2] == const0_rtx)
3435: {
3436: /* No need for a clobber of the condition code register here. */
1.7 ! mrg 3437: emit_insn (gen_rtx_SET (operands[0],
1.1 mrg 3438: gen_rtx_SMIN (SImode, operands[1],
3439: operands[2])));
3440: DONE;
3441: }
3442: ")
3443:
3444: (define_insn "*smin_0"
3445: [(set (match_operand:SI 0 "s_register_operand" "=r")
3446: (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3447: (const_int 0)))]
3448: "TARGET_32BIT"
3449: "and%?\\t%0, %1, %1, asr #31"
1.5 mrg 3450: [(set_attr "predicable" "yes")
3451: (set_attr "predicable_short_it" "no")
3452: (set_attr "type" "logic_shift_reg")]
1.1 mrg 3453: )
3454:
1.5 mrg 3455: (define_insn_and_split "*arm_smin_insn"
1.1 mrg 3456: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3457: (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3458: (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3459: (clobber (reg:CC CC_REGNUM))]
3460: "TARGET_ARM"
1.5 mrg 3461: "#"
3462: ; cmp\\t%1, %2\;movge\\t%0, %2
3463: ; cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3464: "TARGET_ARM"
3465: [(set (reg:CC CC_REGNUM)
3466: (compare:CC (match_dup 1) (match_dup 2)))
3467: (set (match_dup 0)
3468: (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
3469: (match_dup 1)
3470: (match_dup 2)))]
3471: ""
1.1 mrg 3472: [(set_attr "conds" "clob")
1.5 mrg 3473: (set_attr "length" "8,12")
3474: (set_attr "type" "multiple,multiple")]
1.1 mrg 3475: )
3476:
3477: (define_expand "umaxsi3"
3478: [(parallel [
3479: (set (match_operand:SI 0 "s_register_operand" "")
3480: (umax:SI (match_operand:SI 1 "s_register_operand" "")
3481: (match_operand:SI 2 "arm_rhs_operand" "")))
3482: (clobber (reg:CC CC_REGNUM))])]
3483: "TARGET_32BIT"
3484: ""
3485: )
3486:
1.5 mrg 3487: (define_insn_and_split "*arm_umaxsi3"
1.1 mrg 3488: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3489: (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3490: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3491: (clobber (reg:CC CC_REGNUM))]
3492: "TARGET_ARM"
1.5 mrg 3493: "#"
3494: ; cmp\\t%1, %2\;movcc\\t%0, %2
3495: ; cmp\\t%1, %2\;movcs\\t%0, %1
3496: ; cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3497: "TARGET_ARM"
3498: [(set (reg:CC CC_REGNUM)
3499: (compare:CC (match_dup 1) (match_dup 2)))
3500: (set (match_dup 0)
3501: (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
3502: (match_dup 1)
3503: (match_dup 2)))]
3504: ""
1.1 mrg 3505: [(set_attr "conds" "clob")
1.5 mrg 3506: (set_attr "length" "8,8,12")
3507: (set_attr "type" "store1")]
1.1 mrg 3508: )
3509:
3510: (define_expand "uminsi3"
3511: [(parallel [
3512: (set (match_operand:SI 0 "s_register_operand" "")
3513: (umin:SI (match_operand:SI 1 "s_register_operand" "")
3514: (match_operand:SI 2 "arm_rhs_operand" "")))
3515: (clobber (reg:CC CC_REGNUM))])]
3516: "TARGET_32BIT"
3517: ""
3518: )
3519:
1.5 mrg 3520: (define_insn_and_split "*arm_uminsi3"
1.1 mrg 3521: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3522: (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3523: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3524: (clobber (reg:CC CC_REGNUM))]
3525: "TARGET_ARM"
1.5 mrg 3526: "#"
3527: ; cmp\\t%1, %2\;movcs\\t%0, %2
3528: ; cmp\\t%1, %2\;movcc\\t%0, %1
3529: ; cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3530: "TARGET_ARM"
3531: [(set (reg:CC CC_REGNUM)
3532: (compare:CC (match_dup 1) (match_dup 2)))
3533: (set (match_dup 0)
3534: (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
3535: (match_dup 1)
3536: (match_dup 2)))]
3537: ""
1.1 mrg 3538: [(set_attr "conds" "clob")
1.5 mrg 3539: (set_attr "length" "8,8,12")
3540: (set_attr "type" "store1")]
1.1 mrg 3541: )
3542:
3543: (define_insn "*store_minmaxsi"
3544: [(set (match_operand:SI 0 "memory_operand" "=m")
3545: (match_operator:SI 3 "minmax_operator"
3546: [(match_operand:SI 1 "s_register_operand" "r")
3547: (match_operand:SI 2 "s_register_operand" "r")]))
3548: (clobber (reg:CC CC_REGNUM))]
1.5 mrg 3549: "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it"
1.1 mrg 3550: "*
3551: operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3552: operands[1], operands[2]);
3553: output_asm_insn (\"cmp\\t%1, %2\", operands);
3554: if (TARGET_THUMB2)
3555: output_asm_insn (\"ite\t%d3\", operands);
3556: output_asm_insn (\"str%d3\\t%1, %0\", operands);
3557: output_asm_insn (\"str%D3\\t%2, %0\", operands);
3558: return \"\";
3559: "
3560: [(set_attr "conds" "clob")
3561: (set (attr "length")
3562: (if_then_else (eq_attr "is_thumb" "yes")
3563: (const_int 14)
3564: (const_int 12)))
3565: (set_attr "type" "store1")]
3566: )
3567:
3568: ; Reject the frame pointer in operand[1], since reloading this after
3569: ; it has been eliminated can cause carnage.
3570: (define_insn "*minmax_arithsi"
3571: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3572: (match_operator:SI 4 "shiftable_operator"
3573: [(match_operator:SI 5 "minmax_operator"
3574: [(match_operand:SI 2 "s_register_operand" "r,r")
3575: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3576: (match_operand:SI 1 "s_register_operand" "0,?r")]))
3577: (clobber (reg:CC CC_REGNUM))]
1.5 mrg 3578: "TARGET_32BIT && !arm_eliminable_register (operands[1]) && !arm_restrict_it"
1.1 mrg 3579: "*
3580: {
3581: enum rtx_code code = GET_CODE (operands[4]);
3582: bool need_else;
3583:
3584: if (which_alternative != 0 || operands[3] != const0_rtx
3585: || (code != PLUS && code != IOR && code != XOR))
3586: need_else = true;
3587: else
3588: need_else = false;
3589:
3590: operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3591: operands[2], operands[3]);
3592: output_asm_insn (\"cmp\\t%2, %3\", operands);
3593: if (TARGET_THUMB2)
3594: {
3595: if (need_else)
3596: output_asm_insn (\"ite\\t%d5\", operands);
3597: else
3598: output_asm_insn (\"it\\t%d5\", operands);
3599: }
3600: output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3601: if (need_else)
3602: output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3603: return \"\";
3604: }"
3605: [(set_attr "conds" "clob")
3606: (set (attr "length")
3607: (if_then_else (eq_attr "is_thumb" "yes")
3608: (const_int 14)
1.5 mrg 3609: (const_int 12)))
3610: (set_attr "type" "multiple")]
3611: )
3612:
3613: ; Reject the frame pointer in operand[1], since reloading this after
3614: ; it has been eliminated can cause carnage.
3615: (define_insn_and_split "*minmax_arithsi_non_canon"
3616: [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
3617: (minus:SI
3618: (match_operand:SI 1 "s_register_operand" "0,?Ts")
3619: (match_operator:SI 4 "minmax_operator"
3620: [(match_operand:SI 2 "s_register_operand" "Ts,Ts")
3621: (match_operand:SI 3 "arm_rhs_operand" "TsI,TsI")])))
3622: (clobber (reg:CC CC_REGNUM))]
3623: "TARGET_32BIT && !arm_eliminable_register (operands[1])
3624: && !(arm_restrict_it && CONST_INT_P (operands[3]))"
3625: "#"
3626: "TARGET_32BIT && !arm_eliminable_register (operands[1]) && reload_completed"
3627: [(set (reg:CC CC_REGNUM)
3628: (compare:CC (match_dup 2) (match_dup 3)))
3629:
3630: (cond_exec (match_op_dup 4 [(reg:CC CC_REGNUM) (const_int 0)])
3631: (set (match_dup 0)
3632: (minus:SI (match_dup 1)
3633: (match_dup 2))))
3634: (cond_exec (match_op_dup 5 [(reg:CC CC_REGNUM) (const_int 0)])
3635: (set (match_dup 0)
3636: (match_dup 6)))]
3637: {
3638: machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
3639: operands[2], operands[3]);
3640: enum rtx_code rc = minmax_code (operands[4]);
3641: operands[4] = gen_rtx_fmt_ee (rc, VOIDmode,
3642: operands[2], operands[3]);
3643:
3644: if (mode == CCFPmode || mode == CCFPEmode)
3645: rc = reverse_condition_maybe_unordered (rc);
3646: else
3647: rc = reverse_condition (rc);
3648: operands[5] = gen_rtx_fmt_ee (rc, SImode, operands[2], operands[3]);
3649: if (CONST_INT_P (operands[3]))
3650: operands[6] = plus_constant (SImode, operands[1], -INTVAL (operands[3]));
3651: else
3652: operands[6] = gen_rtx_MINUS (SImode, operands[1], operands[3]);
3653: }
3654: [(set_attr "conds" "clob")
3655: (set (attr "length")
3656: (if_then_else (eq_attr "is_thumb" "yes")
3657: (const_int 14)
3658: (const_int 12)))
3659: (set_attr "type" "multiple")]
1.1 mrg 3660: )
3661:
1.3 mrg 3662: (define_code_iterator SAT [smin smax])
3663: (define_code_iterator SATrev [smin smax])
3664: (define_code_attr SATlo [(smin "1") (smax "2")])
3665: (define_code_attr SAThi [(smin "2") (smax "1")])
3666:
3667: (define_insn "*satsi_<SAT:code>"
3668: [(set (match_operand:SI 0 "s_register_operand" "=r")
3669: (SAT:SI (SATrev:SI (match_operand:SI 3 "s_register_operand" "r")
3670: (match_operand:SI 1 "const_int_operand" "i"))
3671: (match_operand:SI 2 "const_int_operand" "i")))]
3672: "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3673: && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3674: {
3675: int mask;
3676: bool signed_sat;
3677: if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3678: &mask, &signed_sat))
3679: gcc_unreachable ();
3680:
3681: operands[1] = GEN_INT (mask);
3682: if (signed_sat)
3683: return "ssat%?\t%0, %1, %3";
3684: else
3685: return "usat%?\t%0, %1, %3";
3686: }
3687: [(set_attr "predicable" "yes")
1.5 mrg 3688: (set_attr "predicable_short_it" "no")
3689: (set_attr "type" "alus_imm")]
3690: )
1.3 mrg 3691:
3692: (define_insn "*satsi_<SAT:code>_shift"
3693: [(set (match_operand:SI 0 "s_register_operand" "=r")
3694: (SAT:SI (SATrev:SI (match_operator:SI 3 "sat_shift_operator"
3695: [(match_operand:SI 4 "s_register_operand" "r")
3696: (match_operand:SI 5 "const_int_operand" "i")])
3697: (match_operand:SI 1 "const_int_operand" "i"))
3698: (match_operand:SI 2 "const_int_operand" "i")))]
3699: "TARGET_32BIT && arm_arch6 && <SAT:CODE> != <SATrev:CODE>
3700: && arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>], NULL, NULL)"
3701: {
3702: int mask;
3703: bool signed_sat;
3704: if (!arm_sat_operator_match (operands[<SAT:SATlo>], operands[<SAT:SAThi>],
3705: &mask, &signed_sat))
3706: gcc_unreachable ();
3707:
3708: operands[1] = GEN_INT (mask);
3709: if (signed_sat)
3710: return "ssat%?\t%0, %1, %4%S3";
3711: else
3712: return "usat%?\t%0, %1, %4%S3";
3713: }
3714: [(set_attr "predicable" "yes")
1.5 mrg 3715: (set_attr "predicable_short_it" "no")
1.3 mrg 3716: (set_attr "shift" "3")
1.5 mrg 3717: (set_attr "type" "logic_shift_reg")])
1.1 mrg 3718:
3719: ;; Shift and rotation insns
3720:
3721: (define_expand "ashldi3"
3722: [(set (match_operand:DI 0 "s_register_operand" "")
3723: (ashift:DI (match_operand:DI 1 "s_register_operand" "")
1.3 mrg 3724: (match_operand:SI 2 "general_operand" "")))]
1.1 mrg 3725: "TARGET_32BIT"
3726: "
1.3 mrg 3727: if (TARGET_NEON)
3728: {
3729: /* Delay the decision whether to use NEON or core-regs until
3730: register allocation. */
3731: emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
3732: DONE;
3733: }
3734: else
3735: {
3736: /* Only the NEON case can handle in-memory shift counts. */
3737: if (!reg_or_int_operand (operands[2], SImode))
3738: operands[2] = force_reg (SImode, operands[2]);
3739: }
3740:
3741: if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
3742: ; /* No special preparation statements; expand pattern as above. */
3743: else
1.1 mrg 3744: {
1.3 mrg 3745: rtx scratch1, scratch2;
3746:
3747: if (CONST_INT_P (operands[2])
3748: && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
1.1 mrg 3749: {
3750: emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3751: DONE;
3752: }
1.3 mrg 3753:
3754: /* Ideally we should use iwmmxt here if we could know that operands[1]
3755: ends up already living in an iwmmxt register. Otherwise it's
3756: cheaper to have the alternate code being generated than moving
3757: values to iwmmxt regs and back. */
3758:
3759: /* If we're optimizing for size, we prefer the libgcc calls. */
3760: if (optimize_function_for_size_p (cfun))
3761: FAIL;
3762:
3763: /* Expand operation using core-registers.
3764: 'FAIL' would achieve the same thing, but this is a bit smarter. */
3765: scratch1 = gen_reg_rtx (SImode);
3766: scratch2 = gen_reg_rtx (SImode);
3767: arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
3768: operands[2], scratch1, scratch2);
3769: DONE;
1.1 mrg 3770: }
3771: "
3772: )
3773:
3774: (define_insn "arm_ashldi3_1bit"
3775: [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3776: (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3777: (const_int 1)))
3778: (clobber (reg:CC CC_REGNUM))]
3779: "TARGET_32BIT"
3780: "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3781: [(set_attr "conds" "clob")
1.5 mrg 3782: (set_attr "length" "8")
3783: (set_attr "type" "multiple")]
1.1 mrg 3784: )
3785:
3786: (define_expand "ashlsi3"
3787: [(set (match_operand:SI 0 "s_register_operand" "")
3788: (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3789: (match_operand:SI 2 "arm_rhs_operand" "")))]
3790: "TARGET_EITHER"
3791: "
1.3 mrg 3792: if (CONST_INT_P (operands[2])
1.1 mrg 3793: && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3794: {
3795: emit_insn (gen_movsi (operands[0], const0_rtx));
3796: DONE;
3797: }
3798: "
3799: )
3800:
3801: (define_expand "ashrdi3"
3802: [(set (match_operand:DI 0 "s_register_operand" "")
3803: (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3804: (match_operand:SI 2 "reg_or_int_operand" "")))]
3805: "TARGET_32BIT"
3806: "
1.3 mrg 3807: if (TARGET_NEON)
3808: {
3809: /* Delay the decision whether to use NEON or core-regs until
3810: register allocation. */
3811: emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
3812: DONE;
3813: }
3814:
3815: if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
3816: ; /* No special preparation statements; expand pattern as above. */
3817: else
1.1 mrg 3818: {
1.3 mrg 3819: rtx scratch1, scratch2;
3820:
3821: if (CONST_INT_P (operands[2])
3822: && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
1.1 mrg 3823: {
3824: emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3825: DONE;
3826: }
1.3 mrg 3827:
3828: /* Ideally we should use iwmmxt here if we could know that operands[1]
3829: ends up already living in an iwmmxt register. Otherwise it's
3830: cheaper to have the alternate code being generated than moving
3831: values to iwmmxt regs and back. */
3832:
3833: /* If we're optimizing for size, we prefer the libgcc calls. */
3834: if (optimize_function_for_size_p (cfun))
3835: FAIL;
3836:
3837: /* Expand operation using core-registers.
3838: 'FAIL' would achieve the same thing, but this is a bit smarter. */
3839: scratch1 = gen_reg_rtx (SImode);
3840: scratch2 = gen_reg_rtx (SImode);
3841: arm_emit_coreregs_64bit_shift (ASHIFTRT, operands[0], operands[1],
3842: operands[2], scratch1, scratch2);
3843: DONE;
1.1 mrg 3844: }
3845: "
3846: )
3847:
3848: (define_insn "arm_ashrdi3_1bit"
3849: [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3850: (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3851: (const_int 1)))
3852: (clobber (reg:CC CC_REGNUM))]
3853: "TARGET_32BIT"
3854: "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3855: [(set_attr "conds" "clob")
1.5 mrg 3856: (set_attr "length" "8")
3857: (set_attr "type" "multiple")]
1.1 mrg 3858: )
3859:
3860: (define_expand "ashrsi3"
3861: [(set (match_operand:SI 0 "s_register_operand" "")
3862: (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3863: (match_operand:SI 2 "arm_rhs_operand" "")))]
3864: "TARGET_EITHER"
3865: "
1.3 mrg 3866: if (CONST_INT_P (operands[2])
1.1 mrg 3867: && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3868: operands[2] = GEN_INT (31);
3869: "
3870: )
3871:
3872: (define_expand "lshrdi3"
3873: [(set (match_operand:DI 0 "s_register_operand" "")
3874: (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3875: (match_operand:SI 2 "reg_or_int_operand" "")))]
3876: "TARGET_32BIT"
3877: "
1.3 mrg 3878: if (TARGET_NEON)
1.1 mrg 3879: {
1.3 mrg 3880: /* Delay the decision whether to use NEON or core-regs until
3881: register allocation. */
3882: emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
3883: DONE;
3884: }
3885:
3886: if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
3887: ; /* No special preparation statements; expand pattern as above. */
3888: else
3889: {
3890: rtx scratch1, scratch2;
3891:
3892: if (CONST_INT_P (operands[2])
3893: && (HOST_WIDE_INT) INTVAL (operands[2]) == 1)
1.1 mrg 3894: {
3895: emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3896: DONE;
3897: }
1.3 mrg 3898:
3899: /* Ideally we should use iwmmxt here if we could know that operands[1]
3900: ends up already living in an iwmmxt register. Otherwise it's
3901: cheaper to have the alternate code being generated than moving
3902: values to iwmmxt regs and back. */
3903:
3904: /* If we're optimizing for size, we prefer the libgcc calls. */
3905: if (optimize_function_for_size_p (cfun))
3906: FAIL;
3907:
3908: /* Expand operation using core-registers.
3909: 'FAIL' would achieve the same thing, but this is a bit smarter. */
3910: scratch1 = gen_reg_rtx (SImode);
3911: scratch2 = gen_reg_rtx (SImode);
3912: arm_emit_coreregs_64bit_shift (LSHIFTRT, operands[0], operands[1],
3913: operands[2], scratch1, scratch2);
3914: DONE;
1.1 mrg 3915: }
3916: "
3917: )
3918:
3919: (define_insn "arm_lshrdi3_1bit"
3920: [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
3921: (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3922: (const_int 1)))
3923: (clobber (reg:CC CC_REGNUM))]
3924: "TARGET_32BIT"
3925: "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3926: [(set_attr "conds" "clob")
1.5 mrg 3927: (set_attr "length" "8")
3928: (set_attr "type" "multiple")]
1.1 mrg 3929: )
3930:
3931: (define_expand "lshrsi3"
3932: [(set (match_operand:SI 0 "s_register_operand" "")
3933: (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3934: (match_operand:SI 2 "arm_rhs_operand" "")))]
3935: "TARGET_EITHER"
3936: "
1.3 mrg 3937: if (CONST_INT_P (operands[2])
1.1 mrg 3938: && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3939: {
3940: emit_insn (gen_movsi (operands[0], const0_rtx));
3941: DONE;
3942: }
3943: "
3944: )
3945:
3946: (define_expand "rotlsi3"
3947: [(set (match_operand:SI 0 "s_register_operand" "")
3948: (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3949: (match_operand:SI 2 "reg_or_int_operand" "")))]
3950: "TARGET_32BIT"
3951: "
1.3 mrg 3952: if (CONST_INT_P (operands[2]))
1.1 mrg 3953: operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3954: else
3955: {
3956: rtx reg = gen_reg_rtx (SImode);
3957: emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3958: operands[2] = reg;
3959: }
3960: "
3961: )
3962:
3963: (define_expand "rotrsi3"
3964: [(set (match_operand:SI 0 "s_register_operand" "")
3965: (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3966: (match_operand:SI 2 "arm_rhs_operand" "")))]
3967: "TARGET_EITHER"
3968: "
3969: if (TARGET_32BIT)
3970: {
1.3 mrg 3971: if (CONST_INT_P (operands[2])
1.1 mrg 3972: && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3973: operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3974: }
3975: else /* TARGET_THUMB1 */
3976: {
1.3 mrg 3977: if (CONST_INT_P (operands [2]))
1.1 mrg 3978: operands [2] = force_reg (SImode, operands[2]);
3979: }
3980: "
3981: )
3982:
3983: (define_insn "*arm_shiftsi3"
1.5 mrg 3984: [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r")
1.1 mrg 3985: (match_operator:SI 3 "shift_operator"
1.5 mrg 3986: [(match_operand:SI 1 "s_register_operand" "0,l,r,r")
3987: (match_operand:SI 2 "reg_or_int_operand" "l,M,M,r")]))]
1.1 mrg 3988: "TARGET_32BIT"
3989: "* return arm_output_shift(operands, 0);"
3990: [(set_attr "predicable" "yes")
1.5 mrg 3991: (set_attr "arch" "t2,t2,*,*")
3992: (set_attr "predicable_short_it" "yes,yes,no,no")
3993: (set_attr "length" "4")
1.1 mrg 3994: (set_attr "shift" "1")
1.5 mrg 3995: (set_attr "type" "alu_shift_reg,alu_shift_imm,alu_shift_imm,alu_shift_reg")]
1.1 mrg 3996: )
3997:
3998: (define_insn "*shiftsi3_compare0"
3999: [(set (reg:CC_NOOV CC_REGNUM)
4000: (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1.5 mrg 4001: [(match_operand:SI 1 "s_register_operand" "r,r")
4002: (match_operand:SI 2 "arm_rhs_operand" "M,r")])
1.1 mrg 4003: (const_int 0)))
1.5 mrg 4004: (set (match_operand:SI 0 "s_register_operand" "=r,r")
1.1 mrg 4005: (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
4006: "TARGET_32BIT"
4007: "* return arm_output_shift(operands, 1);"
4008: [(set_attr "conds" "set")
4009: (set_attr "shift" "1")
1.5 mrg 4010: (set_attr "type" "alus_shift_imm,alus_shift_reg")]
1.1 mrg 4011: )
4012:
4013: (define_insn "*shiftsi3_compare0_scratch"
4014: [(set (reg:CC_NOOV CC_REGNUM)
4015: (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1.5 mrg 4016: [(match_operand:SI 1 "s_register_operand" "r,r")
4017: (match_operand:SI 2 "arm_rhs_operand" "M,r")])
1.1 mrg 4018: (const_int 0)))
1.5 mrg 4019: (clobber (match_scratch:SI 0 "=r,r"))]
1.1 mrg 4020: "TARGET_32BIT"
4021: "* return arm_output_shift(operands, 1);"
4022: [(set_attr "conds" "set")
1.5 mrg 4023: (set_attr "shift" "1")
4024: (set_attr "type" "shift_imm,shift_reg")]
1.1 mrg 4025: )
4026:
1.3 mrg 4027: (define_insn "*not_shiftsi"
4028: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1.1 mrg 4029: (not:SI (match_operator:SI 3 "shift_operator"
1.3 mrg 4030: [(match_operand:SI 1 "s_register_operand" "r,r")
4031: (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
4032: "TARGET_32BIT"
1.1 mrg 4033: "mvn%?\\t%0, %1%S3"
4034: [(set_attr "predicable" "yes")
1.5 mrg 4035: (set_attr "predicable_short_it" "no")
1.1 mrg 4036: (set_attr "shift" "1")
1.3 mrg 4037: (set_attr "arch" "32,a")
1.5 mrg 4038: (set_attr "type" "mvn_shift,mvn_shift_reg")])
1.1 mrg 4039:
1.3 mrg 4040: (define_insn "*not_shiftsi_compare0"
1.1 mrg 4041: [(set (reg:CC_NOOV CC_REGNUM)
1.3 mrg 4042: (compare:CC_NOOV
4043: (not:SI (match_operator:SI 3 "shift_operator"
4044: [(match_operand:SI 1 "s_register_operand" "r,r")
4045: (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4046: (const_int 0)))
4047: (set (match_operand:SI 0 "s_register_operand" "=r,r")
1.1 mrg 4048: (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1.3 mrg 4049: "TARGET_32BIT"
1.7 ! mrg 4050: "mvns%?\\t%0, %1%S3"
1.1 mrg 4051: [(set_attr "conds" "set")
4052: (set_attr "shift" "1")
1.3 mrg 4053: (set_attr "arch" "32,a")
1.5 mrg 4054: (set_attr "type" "mvn_shift,mvn_shift_reg")])
1.1 mrg 4055:
1.3 mrg 4056: (define_insn "*not_shiftsi_compare0_scratch"
1.1 mrg 4057: [(set (reg:CC_NOOV CC_REGNUM)
1.3 mrg 4058: (compare:CC_NOOV
4059: (not:SI (match_operator:SI 3 "shift_operator"
4060: [(match_operand:SI 1 "s_register_operand" "r,r")
4061: (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
4062: (const_int 0)))
4063: (clobber (match_scratch:SI 0 "=r,r"))]
4064: "TARGET_32BIT"
1.7 ! mrg 4065: "mvns%?\\t%0, %1%S3"
1.1 mrg 4066: [(set_attr "conds" "set")
4067: (set_attr "shift" "1")
1.3 mrg 4068: (set_attr "arch" "32,a")
1.5 mrg 4069: (set_attr "type" "mvn_shift,mvn_shift_reg")])
1.1 mrg 4070:
4071: ;; We don't really have extzv, but defining this using shifts helps
4072: ;; to reduce register pressure later on.
4073:
4074: (define_expand "extzv"
1.3 mrg 4075: [(set (match_operand 0 "s_register_operand" "")
4076: (zero_extract (match_operand 1 "nonimmediate_operand" "")
4077: (match_operand 2 "const_int_operand" "")
4078: (match_operand 3 "const_int_operand" "")))]
1.1 mrg 4079: "TARGET_THUMB1 || arm_arch_thumb2"
4080: "
4081: {
4082: HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
4083: HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
4084:
4085: if (arm_arch_thumb2)
4086: {
1.3 mrg 4087: HOST_WIDE_INT width = INTVAL (operands[2]);
4088: HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4089:
4090: if (unaligned_access && MEM_P (operands[1])
4091: && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
4092: {
4093: rtx base_addr;
4094:
4095: if (BYTES_BIG_ENDIAN)
4096: bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
4097: - bitpos;
4098:
4099: if (width == 32)
4100: {
4101: base_addr = adjust_address (operands[1], SImode,
4102: bitpos / BITS_PER_UNIT);
4103: emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4104: }
4105: else
4106: {
4107: rtx dest = operands[0];
4108: rtx tmp = gen_reg_rtx (SImode);
4109:
4110: /* We may get a paradoxical subreg here. Strip it off. */
4111: if (GET_CODE (dest) == SUBREG
4112: && GET_MODE (dest) == SImode
4113: && GET_MODE (SUBREG_REG (dest)) == HImode)
4114: dest = SUBREG_REG (dest);
4115:
4116: if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4117: FAIL;
4118:
4119: base_addr = adjust_address (operands[1], HImode,
4120: bitpos / BITS_PER_UNIT);
4121: emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
4122: emit_move_insn (gen_lowpart (SImode, dest), tmp);
4123: }
4124: DONE;
4125: }
4126: else if (s_register_operand (operands[1], GET_MODE (operands[1])))
4127: {
4128: emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
4129: operands[3]));
4130: DONE;
4131: }
4132: else
4133: FAIL;
1.1 mrg 4134: }
1.3 mrg 4135:
4136: if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4137: FAIL;
1.1 mrg 4138:
4139: operands[3] = GEN_INT (rshift);
4140:
4141: if (lshift == 0)
4142: {
4143: emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
4144: DONE;
4145: }
4146:
1.3 mrg 4147: emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
4148: operands[3], gen_reg_rtx (SImode)));
4149: DONE;
1.1 mrg 4150: }"
4151: )
4152:
1.3 mrg 4153: ;; Helper for extzv, for the Thumb-1 register-shifts case.
4154:
4155: (define_expand "extzv_t1"
4156: [(set (match_operand:SI 4 "s_register_operand" "")
4157: (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
4158: (match_operand:SI 2 "const_int_operand" "")))
4159: (set (match_operand:SI 0 "s_register_operand" "")
4160: (lshiftrt:SI (match_dup 4)
4161: (match_operand:SI 3 "const_int_operand" "")))]
4162: "TARGET_THUMB1"
4163: "")
4164:
4165: (define_expand "extv"
4166: [(set (match_operand 0 "s_register_operand" "")
4167: (sign_extract (match_operand 1 "nonimmediate_operand" "")
4168: (match_operand 2 "const_int_operand" "")
4169: (match_operand 3 "const_int_operand" "")))]
4170: "arm_arch_thumb2"
4171: {
4172: HOST_WIDE_INT width = INTVAL (operands[2]);
4173: HOST_WIDE_INT bitpos = INTVAL (operands[3]);
4174:
4175: if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
4176: && (bitpos % BITS_PER_UNIT) == 0)
4177: {
4178: rtx base_addr;
4179:
4180: if (BYTES_BIG_ENDIAN)
4181: bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
4182:
4183: if (width == 32)
4184: {
4185: base_addr = adjust_address (operands[1], SImode,
4186: bitpos / BITS_PER_UNIT);
4187: emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
4188: }
4189: else
4190: {
4191: rtx dest = operands[0];
4192: rtx tmp = gen_reg_rtx (SImode);
4193:
4194: /* We may get a paradoxical subreg here. Strip it off. */
4195: if (GET_CODE (dest) == SUBREG
4196: && GET_MODE (dest) == SImode
4197: && GET_MODE (SUBREG_REG (dest)) == HImode)
4198: dest = SUBREG_REG (dest);
4199:
4200: if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
4201: FAIL;
4202:
4203: base_addr = adjust_address (operands[1], HImode,
4204: bitpos / BITS_PER_UNIT);
4205: emit_insn (gen_unaligned_loadhis (tmp, base_addr));
4206: emit_move_insn (gen_lowpart (SImode, dest), tmp);
4207: }
4208:
4209: DONE;
4210: }
4211: else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
4212: FAIL;
4213: else if (GET_MODE (operands[0]) == SImode
4214: && GET_MODE (operands[1]) == SImode)
4215: {
4216: emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
4217: operands[3]));
4218: DONE;
4219: }
4220:
4221: FAIL;
4222: })
4223:
4224: ; Helper to expand register forms of extv with the proper modes.
4225:
4226: (define_expand "extv_regsi"
4227: [(set (match_operand:SI 0 "s_register_operand" "")
4228: (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
4229: (match_operand 2 "const_int_operand" "")
4230: (match_operand 3 "const_int_operand" "")))]
4231: ""
4232: {
4233: })
4234:
4235: ; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
4236:
4237: (define_insn "unaligned_loadsi"
4238: [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4239: (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
4240: UNSPEC_UNALIGNED_LOAD))]
1.7 ! mrg 4241: "unaligned_access"
1.3 mrg 4242: "ldr%?\t%0, %1\t@ unaligned"
4243: [(set_attr "arch" "t2,any")
4244: (set_attr "length" "2,4")
4245: (set_attr "predicable" "yes")
1.5 mrg 4246: (set_attr "predicable_short_it" "yes,no")
1.3 mrg 4247: (set_attr "type" "load1")])
4248:
4249: (define_insn "unaligned_loadhis"
4250: [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4251: (sign_extend:SI
4252: (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")]
4253: UNSPEC_UNALIGNED_LOAD)))]
1.7 ! mrg 4254: "unaligned_access"
! 4255: "ldrsh%?\t%0, %1\t@ unaligned"
1.3 mrg 4256: [(set_attr "arch" "t2,any")
4257: (set_attr "length" "2,4")
4258: (set_attr "predicable" "yes")
1.5 mrg 4259: (set_attr "predicable_short_it" "yes,no")
1.3 mrg 4260: (set_attr "type" "load_byte")])
4261:
4262: (define_insn "unaligned_loadhiu"
4263: [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4264: (zero_extend:SI
4265: (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
4266: UNSPEC_UNALIGNED_LOAD)))]
1.7 ! mrg 4267: "unaligned_access"
! 4268: "ldrh%?\t%0, %1\t@ unaligned"
1.3 mrg 4269: [(set_attr "arch" "t2,any")
4270: (set_attr "length" "2,4")
4271: (set_attr "predicable" "yes")
1.5 mrg 4272: (set_attr "predicable_short_it" "yes,no")
1.3 mrg 4273: (set_attr "type" "load_byte")])
4274:
4275: (define_insn "unaligned_storesi"
4276: [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
4277: (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
4278: UNSPEC_UNALIGNED_STORE))]
1.7 ! mrg 4279: "unaligned_access"
1.3 mrg 4280: "str%?\t%1, %0\t@ unaligned"
4281: [(set_attr "arch" "t2,any")
4282: (set_attr "length" "2,4")
4283: (set_attr "predicable" "yes")
1.5 mrg 4284: (set_attr "predicable_short_it" "yes,no")
1.3 mrg 4285: (set_attr "type" "store1")])
4286:
4287: (define_insn "unaligned_storehi"
4288: [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
4289: (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
4290: UNSPEC_UNALIGNED_STORE))]
1.7 ! mrg 4291: "unaligned_access"
! 4292: "strh%?\t%1, %0\t@ unaligned"
1.3 mrg 4293: [(set_attr "arch" "t2,any")
4294: (set_attr "length" "2,4")
4295: (set_attr "predicable" "yes")
1.5 mrg 4296: (set_attr "predicable_short_it" "yes,no")
1.3 mrg 4297: (set_attr "type" "store1")])
4298:
1.5 mrg 4299:
1.3 mrg 4300: (define_insn "*extv_reg"
1.1 mrg 4301: [(set (match_operand:SI 0 "s_register_operand" "=r")
4302: (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
1.5 mrg 4303: (match_operand:SI 2 "const_int_M_operand" "M")
4304: (match_operand:SI 3 "const_int_M_operand" "M")))]
1.1 mrg 4305: "arm_arch_thumb2"
4306: "sbfx%?\t%0, %1, %3, %2"
4307: [(set_attr "length" "4")
1.5 mrg 4308: (set_attr "predicable" "yes")
4309: (set_attr "predicable_short_it" "no")
4310: (set_attr "type" "bfm")]
1.1 mrg 4311: )
4312:
4313: (define_insn "extzv_t2"
4314: [(set (match_operand:SI 0 "s_register_operand" "=r")
4315: (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
1.5 mrg 4316: (match_operand:SI 2 "const_int_M_operand" "M")
4317: (match_operand:SI 3 "const_int_M_operand" "M")))]
1.1 mrg 4318: "arm_arch_thumb2"
4319: "ubfx%?\t%0, %1, %3, %2"
4320: [(set_attr "length" "4")
1.5 mrg 4321: (set_attr "predicable" "yes")
4322: (set_attr "predicable_short_it" "no")
4323: (set_attr "type" "bfm")]
1.1 mrg 4324: )
4325:
1.3 mrg 4326:
4327: ;; Division instructions
4328: (define_insn "divsi3"
4329: [(set (match_operand:SI 0 "s_register_operand" "=r")
4330: (div:SI (match_operand:SI 1 "s_register_operand" "r")
4331: (match_operand:SI 2 "s_register_operand" "r")))]
4332: "TARGET_IDIV"
4333: "sdiv%?\t%0, %1, %2"
4334: [(set_attr "predicable" "yes")
1.5 mrg 4335: (set_attr "predicable_short_it" "no")
4336: (set_attr "type" "sdiv")]
1.3 mrg 4337: )
4338:
4339: (define_insn "udivsi3"
4340: [(set (match_operand:SI 0 "s_register_operand" "=r")
4341: (udiv:SI (match_operand:SI 1 "s_register_operand" "r")
4342: (match_operand:SI 2 "s_register_operand" "r")))]
4343: "TARGET_IDIV"
4344: "udiv%?\t%0, %1, %2"
4345: [(set_attr "predicable" "yes")
1.5 mrg 4346: (set_attr "predicable_short_it" "no")
4347: (set_attr "type" "udiv")]
1.3 mrg 4348: )
4349:
1.1 mrg 4350:
4351: ;; Unary arithmetic insns
4352:
4353: (define_expand "negdi2"
4354: [(parallel
1.3 mrg 4355: [(set (match_operand:DI 0 "s_register_operand" "")
4356: (neg:DI (match_operand:DI 1 "s_register_operand" "")))
1.1 mrg 4357: (clobber (reg:CC CC_REGNUM))])]
4358: "TARGET_EITHER"
1.3 mrg 4359: {
4360: if (TARGET_NEON)
4361: {
4362: emit_insn (gen_negdi2_neon (operands[0], operands[1]));
4363: DONE;
4364: }
4365: }
1.1 mrg 4366: )
4367:
4368: ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
4369: ;; The first alternative allows the common case of a *full* overlap.
1.5 mrg 4370: (define_insn_and_split "*arm_negdi2"
1.1 mrg 4371: [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4372: (neg:DI (match_operand:DI 1 "s_register_operand" "0,r")))
4373: (clobber (reg:CC CC_REGNUM))]
4374: "TARGET_ARM"
1.5 mrg 4375: "#" ; "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4376: "&& reload_completed"
4377: [(parallel [(set (reg:CC CC_REGNUM)
4378: (compare:CC (const_int 0) (match_dup 1)))
4379: (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4380: (set (match_dup 2) (minus:SI (minus:SI (const_int 0) (match_dup 3))
4381: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4382: {
4383: operands[2] = gen_highpart (SImode, operands[0]);
4384: operands[0] = gen_lowpart (SImode, operands[0]);
4385: operands[3] = gen_highpart (SImode, operands[1]);
4386: operands[1] = gen_lowpart (SImode, operands[1]);
4387: }
1.1 mrg 4388: [(set_attr "conds" "clob")
1.5 mrg 4389: (set_attr "length" "8")
4390: (set_attr "type" "multiple")]
1.1 mrg 4391: )
4392:
4393: (define_expand "negsi2"
4394: [(set (match_operand:SI 0 "s_register_operand" "")
4395: (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4396: "TARGET_EITHER"
4397: ""
4398: )
4399:
4400: (define_insn "*arm_negsi2"
1.5 mrg 4401: [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4402: (neg:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
1.1 mrg 4403: "TARGET_32BIT"
4404: "rsb%?\\t%0, %1, #0"
1.5 mrg 4405: [(set_attr "predicable" "yes")
4406: (set_attr "predicable_short_it" "yes,no")
4407: (set_attr "arch" "t2,*")
4408: (set_attr "length" "4")
4409: (set_attr "type" "alu_sreg")]
1.1 mrg 4410: )
4411:
4412: (define_expand "negsf2"
4413: [(set (match_operand:SF 0 "s_register_operand" "")
4414: (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
1.3 mrg 4415: "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1.1 mrg 4416: ""
4417: )
4418:
4419: (define_expand "negdf2"
4420: [(set (match_operand:DF 0 "s_register_operand" "")
4421: (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
1.3 mrg 4422: "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1.1 mrg 4423: "")
4424:
1.5 mrg 4425: (define_insn_and_split "*zextendsidi_negsi"
4426: [(set (match_operand:DI 0 "s_register_operand" "=r")
4427: (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
4428: "TARGET_32BIT"
4429: "#"
4430: ""
4431: [(set (match_dup 2)
4432: (neg:SI (match_dup 1)))
4433: (set (match_dup 3)
4434: (const_int 0))]
4435: {
4436: operands[2] = gen_lowpart (SImode, operands[0]);
4437: operands[3] = gen_highpart (SImode, operands[0]);
4438: }
4439: [(set_attr "length" "8")
4440: (set_attr "type" "multiple")]
4441: )
4442:
4443: ;; Negate an extended 32-bit value.
4444: (define_insn_and_split "*negdi_extendsidi"
4445: [(set (match_operand:DI 0 "s_register_operand" "=l,r")
4446: (neg:DI (sign_extend:DI
4447: (match_operand:SI 1 "s_register_operand" "l,r"))))
4448: (clobber (reg:CC CC_REGNUM))]
4449: "TARGET_32BIT"
4450: "#"
4451: "&& reload_completed"
4452: [(const_int 0)]
4453: {
4454: rtx low = gen_lowpart (SImode, operands[0]);
4455: rtx high = gen_highpart (SImode, operands[0]);
4456:
4457: if (reg_overlap_mentioned_p (low, operands[1]))
4458: {
4459: /* Input overlaps the low word of the output. Use:
4460: asr Rhi, Rin, #31
4461: rsbs Rlo, Rin, #0
4462: rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */
4463: rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM);
4464:
1.7 ! mrg 4465: emit_insn (gen_rtx_SET (high,
1.5 mrg 4466: gen_rtx_ASHIFTRT (SImode, operands[1],
4467: GEN_INT (31))));
4468:
4469: emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1]));
4470: if (TARGET_ARM)
1.7 ! mrg 4471: emit_insn (gen_rtx_SET (high,
1.5 mrg 4472: gen_rtx_MINUS (SImode,
4473: gen_rtx_MINUS (SImode,
4474: const0_rtx,
4475: high),
4476: gen_rtx_LTU (SImode,
4477: cc_reg,
4478: const0_rtx))));
4479: else
4480: {
4481: rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1));
1.7 ! mrg 4482: emit_insn (gen_rtx_SET (high,
1.5 mrg 4483: gen_rtx_MINUS (SImode,
4484: gen_rtx_MINUS (SImode,
4485: high,
4486: two_x),
4487: gen_rtx_LTU (SImode,
4488: cc_reg,
4489: const0_rtx))));
4490: }
4491: }
4492: else
4493: {
4494: /* No overlap, or overlap on high word. Use:
4495: rsb Rlo, Rin, #0
4496: bic Rhi, Rlo, Rin
4497: asr Rhi, Rhi, #31
4498: Flags not needed for this sequence. */
1.7 ! mrg 4499: emit_insn (gen_rtx_SET (low, gen_rtx_NEG (SImode, operands[1])));
! 4500: emit_insn (gen_rtx_SET (high,
1.5 mrg 4501: gen_rtx_AND (SImode,
4502: gen_rtx_NOT (SImode, operands[1]),
4503: low)));
1.7 ! mrg 4504: emit_insn (gen_rtx_SET (high,
1.5 mrg 4505: gen_rtx_ASHIFTRT (SImode, high,
4506: GEN_INT (31))));
4507: }
4508: DONE;
4509: }
4510: [(set_attr "length" "12")
4511: (set_attr "arch" "t2,*")
4512: (set_attr "type" "multiple")]
4513: )
4514:
4515: (define_insn_and_split "*negdi_zero_extendsidi"
4516: [(set (match_operand:DI 0 "s_register_operand" "=r,&r")
4517: (neg:DI (zero_extend:DI (match_operand:SI 1 "s_register_operand" "0,r"))))
4518: (clobber (reg:CC CC_REGNUM))]
4519: "TARGET_32BIT"
4520: "#" ; "rsbs\\t%Q0, %1, #0\;sbc\\t%R0,%R0,%R0"
4521: ;; Don't care what register is input to sbc,
1.7 ! mrg 4522: ;; since we just need to propagate the carry.
1.5 mrg 4523: "&& reload_completed"
4524: [(parallel [(set (reg:CC CC_REGNUM)
4525: (compare:CC (const_int 0) (match_dup 1)))
4526: (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1)))])
4527: (set (match_dup 2) (minus:SI (minus:SI (match_dup 2) (match_dup 2))
4528: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
4529: {
4530: operands[2] = gen_highpart (SImode, operands[0]);
4531: operands[0] = gen_lowpart (SImode, operands[0]);
4532: }
4533: [(set_attr "conds" "clob")
4534: (set_attr "length" "8")
4535: (set_attr "type" "multiple")] ;; length in thumb is 4
4536: )
4537:
1.1 mrg 4538: ;; abssi2 doesn't really clobber the condition codes if a different register
4539: ;; is being set. To keep things simple, assume during rtl manipulations that
4540: ;; it does, but tell the final scan operator the truth. Similarly for
4541: ;; (neg (abs...))
4542:
4543: (define_expand "abssi2"
4544: [(parallel
4545: [(set (match_operand:SI 0 "s_register_operand" "")
4546: (abs:SI (match_operand:SI 1 "s_register_operand" "")))
4547: (clobber (match_dup 2))])]
4548: "TARGET_EITHER"
4549: "
4550: if (TARGET_THUMB1)
4551: operands[2] = gen_rtx_SCRATCH (SImode);
4552: else
4553: operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4554: ")
4555:
1.5 mrg 4556: (define_insn_and_split "*arm_abssi2"
1.1 mrg 4557: [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4558: (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
4559: (clobber (reg:CC CC_REGNUM))]
4560: "TARGET_ARM"
1.5 mrg 4561: "#"
4562: "&& reload_completed"
4563: [(const_int 0)]
4564: {
4565: /* if (which_alternative == 0) */
4566: if (REGNO(operands[0]) == REGNO(operands[1]))
4567: {
4568: /* Emit the pattern:
4569: cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4570: [(set (reg:CC CC_REGNUM)
4571: (compare:CC (match_dup 0) (const_int 0)))
4572: (cond_exec (lt:CC (reg:CC CC_REGNUM) (const_int 0))
4573: (set (match_dup 0) (minus:SI (const_int 0) (match_dup 1))))]
4574: */
1.7 ! mrg 4575: emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
1.5 mrg 4576: gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4577: emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4578: (gen_rtx_LT (SImode,
4579: gen_rtx_REG (CCmode, CC_REGNUM),
4580: const0_rtx)),
1.7 ! mrg 4581: (gen_rtx_SET (operands[0],
1.5 mrg 4582: (gen_rtx_MINUS (SImode,
4583: const0_rtx,
4584: operands[1]))))));
4585: DONE;
4586: }
4587: else
4588: {
4589: /* Emit the pattern:
4590: alt1: eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
4591: [(set (match_dup 0)
4592: (xor:SI (match_dup 1)
4593: (ashiftrt:SI (match_dup 1) (const_int 31))))
4594: (set (match_dup 0)
4595: (minus:SI (match_dup 0)
4596: (ashiftrt:SI (match_dup 1) (const_int 31))))]
4597: */
1.7 ! mrg 4598: emit_insn (gen_rtx_SET (operands[0],
1.5 mrg 4599: gen_rtx_XOR (SImode,
4600: gen_rtx_ASHIFTRT (SImode,
4601: operands[1],
4602: GEN_INT (31)),
4603: operands[1])));
1.7 ! mrg 4604: emit_insn (gen_rtx_SET (operands[0],
1.5 mrg 4605: gen_rtx_MINUS (SImode,
4606: operands[0],
4607: gen_rtx_ASHIFTRT (SImode,
4608: operands[1],
4609: GEN_INT (31)))));
4610: DONE;
4611: }
4612: }
1.1 mrg 4613: [(set_attr "conds" "clob,*")
4614: (set_attr "shift" "1")
1.3 mrg 4615: (set_attr "predicable" "no, yes")
1.5 mrg 4616: (set_attr "length" "8")
4617: (set_attr "type" "multiple")]
1.1 mrg 4618: )
4619:
1.5 mrg 4620: (define_insn_and_split "*arm_neg_abssi2"
1.1 mrg 4621: [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4622: (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
4623: (clobber (reg:CC CC_REGNUM))]
4624: "TARGET_ARM"
1.5 mrg 4625: "#"
4626: "&& reload_completed"
4627: [(const_int 0)]
4628: {
4629: /* if (which_alternative == 0) */
4630: if (REGNO (operands[0]) == REGNO (operands[1]))
4631: {
4632: /* Emit the pattern:
4633: cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4634: */
1.7 ! mrg 4635: emit_insn (gen_rtx_SET (gen_rtx_REG (CCmode, CC_REGNUM),
1.5 mrg 4636: gen_rtx_COMPARE (CCmode, operands[0], const0_rtx)));
4637: emit_insn (gen_rtx_COND_EXEC (VOIDmode,
4638: gen_rtx_GT (SImode,
4639: gen_rtx_REG (CCmode, CC_REGNUM),
4640: const0_rtx),
1.7 ! mrg 4641: gen_rtx_SET (operands[0],
1.5 mrg 4642: (gen_rtx_MINUS (SImode,
4643: const0_rtx,
4644: operands[1])))));
4645: }
4646: else
4647: {
4648: /* Emit the pattern:
4649: eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
4650: */
1.7 ! mrg 4651: emit_insn (gen_rtx_SET (operands[0],
1.5 mrg 4652: gen_rtx_XOR (SImode,
4653: gen_rtx_ASHIFTRT (SImode,
4654: operands[1],
4655: GEN_INT (31)),
4656: operands[1])));
1.7 ! mrg 4657: emit_insn (gen_rtx_SET (operands[0],
1.5 mrg 4658: gen_rtx_MINUS (SImode,
4659: gen_rtx_ASHIFTRT (SImode,
4660: operands[1],
4661: GEN_INT (31)),
4662: operands[0])));
4663: }
4664: DONE;
4665: }
1.1 mrg 4666: [(set_attr "conds" "clob,*")
4667: (set_attr "shift" "1")
1.3 mrg 4668: (set_attr "predicable" "no, yes")
1.5 mrg 4669: (set_attr "length" "8")
4670: (set_attr "type" "multiple")]
1.1 mrg 4671: )
4672:
4673: (define_expand "abssf2"
4674: [(set (match_operand:SF 0 "s_register_operand" "")
4675: (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
4676: "TARGET_32BIT && TARGET_HARD_FLOAT"
4677: "")
4678:
4679: (define_expand "absdf2"
4680: [(set (match_operand:DF 0 "s_register_operand" "")
4681: (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
4682: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4683: "")
4684:
4685: (define_expand "sqrtsf2"
4686: [(set (match_operand:SF 0 "s_register_operand" "")
4687: (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
1.3 mrg 4688: "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1.1 mrg 4689: "")
4690:
4691: (define_expand "sqrtdf2"
4692: [(set (match_operand:DF 0 "s_register_operand" "")
4693: (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
1.3 mrg 4694: "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1.1 mrg 4695: "")
4696:
4697: (define_insn_and_split "one_cmpldi2"
1.3 mrg 4698: [(set (match_operand:DI 0 "s_register_operand" "=w,&r,&r,?w")
4699: (not:DI (match_operand:DI 1 "s_register_operand" " w, 0, r, w")))]
1.1 mrg 4700: "TARGET_32BIT"
1.3 mrg 4701: "@
4702: vmvn\t%P0, %P1
4703: #
4704: #
4705: vmvn\t%P0, %P1"
4706: "TARGET_32BIT && reload_completed
4707: && arm_general_register_operand (operands[0], DImode)"
1.1 mrg 4708: [(set (match_dup 0) (not:SI (match_dup 1)))
4709: (set (match_dup 2) (not:SI (match_dup 3)))]
4710: "
4711: {
4712: operands[2] = gen_highpart (SImode, operands[0]);
4713: operands[0] = gen_lowpart (SImode, operands[0]);
4714: operands[3] = gen_highpart (SImode, operands[1]);
4715: operands[1] = gen_lowpart (SImode, operands[1]);
4716: }"
1.3 mrg 4717: [(set_attr "length" "*,8,8,*")
4718: (set_attr "predicable" "no,yes,yes,no")
1.5 mrg 4719: (set_attr "type" "neon_move,multiple,multiple,neon_move")
4720: (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")]
1.1 mrg 4721: )
4722:
4723: (define_expand "one_cmplsi2"
4724: [(set (match_operand:SI 0 "s_register_operand" "")
4725: (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4726: "TARGET_EITHER"
4727: ""
4728: )
4729:
4730: (define_insn "*arm_one_cmplsi2"
1.5 mrg 4731: [(set (match_operand:SI 0 "s_register_operand" "=l,r")
4732: (not:SI (match_operand:SI 1 "s_register_operand" "l,r")))]
1.1 mrg 4733: "TARGET_32BIT"
4734: "mvn%?\\t%0, %1"
1.3 mrg 4735: [(set_attr "predicable" "yes")
1.5 mrg 4736: (set_attr "predicable_short_it" "yes,no")
4737: (set_attr "arch" "t2,*")
4738: (set_attr "length" "4")
4739: (set_attr "type" "mvn_reg")]
1.1 mrg 4740: )
4741:
4742: (define_insn "*notsi_compare0"
4743: [(set (reg:CC_NOOV CC_REGNUM)
4744: (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4745: (const_int 0)))
4746: (set (match_operand:SI 0 "s_register_operand" "=r")
4747: (not:SI (match_dup 1)))]
4748: "TARGET_32BIT"
1.7 ! mrg 4749: "mvns%?\\t%0, %1"
1.3 mrg 4750: [(set_attr "conds" "set")
1.5 mrg 4751: (set_attr "type" "mvn_reg")]
1.1 mrg 4752: )
4753:
4754: (define_insn "*notsi_compare0_scratch"
4755: [(set (reg:CC_NOOV CC_REGNUM)
4756: (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4757: (const_int 0)))
4758: (clobber (match_scratch:SI 0 "=r"))]
4759: "TARGET_32BIT"
1.7 ! mrg 4760: "mvns%?\\t%0, %1"
1.3 mrg 4761: [(set_attr "conds" "set")
1.5 mrg 4762: (set_attr "type" "mvn_reg")]
1.1 mrg 4763: )
4764:
4765: ;; Fixed <--> Floating conversion insns
4766:
4767: (define_expand "floatsihf2"
4768: [(set (match_operand:HF 0 "general_operand" "")
4769: (float:HF (match_operand:SI 1 "general_operand" "")))]
4770: "TARGET_EITHER"
4771: "
4772: {
4773: rtx op1 = gen_reg_rtx (SFmode);
4774: expand_float (op1, operands[1], 0);
4775: op1 = convert_to_mode (HFmode, op1, 0);
4776: emit_move_insn (operands[0], op1);
4777: DONE;
4778: }"
4779: )
4780:
4781: (define_expand "floatdihf2"
4782: [(set (match_operand:HF 0 "general_operand" "")
4783: (float:HF (match_operand:DI 1 "general_operand" "")))]
4784: "TARGET_EITHER"
4785: "
4786: {
4787: rtx op1 = gen_reg_rtx (SFmode);
4788: expand_float (op1, operands[1], 0);
4789: op1 = convert_to_mode (HFmode, op1, 0);
4790: emit_move_insn (operands[0], op1);
4791: DONE;
4792: }"
4793: )
4794:
4795: (define_expand "floatsisf2"
4796: [(set (match_operand:SF 0 "s_register_operand" "")
4797: (float:SF (match_operand:SI 1 "s_register_operand" "")))]
4798: "TARGET_32BIT && TARGET_HARD_FLOAT"
4799: "
4800: ")
4801:
4802: (define_expand "floatsidf2"
4803: [(set (match_operand:DF 0 "s_register_operand" "")
4804: (float:DF (match_operand:SI 1 "s_register_operand" "")))]
4805: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4806: "
4807: ")
4808:
4809: (define_expand "fix_trunchfsi2"
4810: [(set (match_operand:SI 0 "general_operand" "")
4811: (fix:SI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4812: "TARGET_EITHER"
4813: "
4814: {
4815: rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4816: expand_fix (operands[0], op1, 0);
4817: DONE;
4818: }"
4819: )
4820:
4821: (define_expand "fix_trunchfdi2"
4822: [(set (match_operand:DI 0 "general_operand" "")
4823: (fix:DI (fix:HF (match_operand:HF 1 "general_operand" ""))))]
4824: "TARGET_EITHER"
4825: "
4826: {
4827: rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4828: expand_fix (operands[0], op1, 0);
4829: DONE;
4830: }"
4831: )
4832:
4833: (define_expand "fix_truncsfsi2"
4834: [(set (match_operand:SI 0 "s_register_operand" "")
4835: (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
4836: "TARGET_32BIT && TARGET_HARD_FLOAT"
4837: "
4838: ")
4839:
4840: (define_expand "fix_truncdfsi2"
4841: [(set (match_operand:SI 0 "s_register_operand" "")
4842: (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
4843: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4844: "
4845: ")
4846:
4847: ;; Truncation insns
4848:
4849: (define_expand "truncdfsf2"
4850: [(set (match_operand:SF 0 "s_register_operand" "")
4851: (float_truncate:SF
4852: (match_operand:DF 1 "s_register_operand" "")))]
4853: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4854: ""
4855: )
4856:
4857: /* DFmode -> HFmode conversions have to go through SFmode. */
4858: (define_expand "truncdfhf2"
4859: [(set (match_operand:HF 0 "general_operand" "")
4860: (float_truncate:HF
4861: (match_operand:DF 1 "general_operand" "")))]
4862: "TARGET_EITHER"
4863: "
4864: {
4865: rtx op1;
4866: op1 = convert_to_mode (SFmode, operands[1], 0);
4867: op1 = convert_to_mode (HFmode, op1, 0);
4868: emit_move_insn (operands[0], op1);
4869: DONE;
4870: }"
4871: )
4872:
4873: ;; Zero and sign extension instructions.
4874:
1.3 mrg 4875: (define_insn "zero_extend<mode>di2"
4876: [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,w")
4877: (zero_extend:DI (match_operand:QHSI 1 "<qhs_zextenddi_op>"
4878: "<qhs_zextenddi_cstr>")))]
4879: "TARGET_32BIT <qhs_zextenddi_cond>"
4880: "#"
4881: [(set_attr "length" "8,4,8,8")
1.5 mrg 4882: (set_attr "arch" "neon_for_64bits,*,*,avoid_neon_for_64bits")
1.3 mrg 4883: (set_attr "ce_count" "2")
1.5 mrg 4884: (set_attr "predicable" "yes")
4885: (set_attr "type" "multiple,mov_reg,multiple,multiple")]
1.1 mrg 4886: )
4887:
1.3 mrg 4888: (define_insn "extend<mode>di2"
4889: [(set (match_operand:DI 0 "s_register_operand" "=w,r,?r,?r,w")
4890: (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>"
4891: "<qhs_extenddi_cstr>")))]
4892: "TARGET_32BIT <qhs_sextenddi_cond>"
4893: "#"
4894: [(set_attr "length" "8,4,8,8,8")
4895: (set_attr "ce_count" "2")
4896: (set_attr "shift" "1")
1.1 mrg 4897: (set_attr "predicable" "yes")
1.5 mrg 4898: (set_attr "arch" "neon_for_64bits,*,a,t,avoid_neon_for_64bits")
4899: (set_attr "type" "multiple,mov_reg,multiple,multiple,multiple")]
1.1 mrg 4900: )
4901:
1.3 mrg 4902: ;; Splits for all extensions to DImode
4903: (define_split
1.1 mrg 4904: [(set (match_operand:DI 0 "s_register_operand" "")
1.3 mrg 4905: (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4906: "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
4907: [(set (match_dup 0) (match_dup 1))]
4908: {
4909: rtx lo_part = gen_lowpart (SImode, operands[0]);
1.5 mrg 4910: machine_mode src_mode = GET_MODE (operands[1]);
1.1 mrg 4911:
1.3 mrg 4912: if (REG_P (operands[0])
4913: && !reg_overlap_mentioned_p (operands[0], operands[1]))
4914: emit_clobber (operands[0]);
4915: if (!REG_P (lo_part) || src_mode != SImode
4916: || !rtx_equal_p (lo_part, operands[1]))
4917: {
4918: if (src_mode == SImode)
4919: emit_move_insn (lo_part, operands[1]);
4920: else
1.7 ! mrg 4921: emit_insn (gen_rtx_SET (lo_part,
1.1 mrg 4922: gen_rtx_ZERO_EXTEND (SImode, operands[1])));
1.3 mrg 4923: operands[1] = lo_part;
4924: }
4925: operands[0] = gen_highpart (SImode, operands[0]);
4926: operands[1] = const0_rtx;
4927: })
1.1 mrg 4928:
1.3 mrg 4929: (define_split
4930: [(set (match_operand:DI 0 "s_register_operand" "")
4931: (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4932: "TARGET_32BIT && reload_completed && !IS_VFP_REGNUM (REGNO (operands[0]))"
4933: [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4934: {
4935: rtx lo_part = gen_lowpart (SImode, operands[0]);
1.5 mrg 4936: machine_mode src_mode = GET_MODE (operands[1]);
1.1 mrg 4937:
1.3 mrg 4938: if (REG_P (operands[0])
4939: && !reg_overlap_mentioned_p (operands[0], operands[1]))
4940: emit_clobber (operands[0]);
1.1 mrg 4941:
1.3 mrg 4942: if (!REG_P (lo_part) || src_mode != SImode
4943: || !rtx_equal_p (lo_part, operands[1]))
4944: {
4945: if (src_mode == SImode)
4946: emit_move_insn (lo_part, operands[1]);
4947: else
1.7 ! mrg 4948: emit_insn (gen_rtx_SET (lo_part,
1.3 mrg 4949: gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4950: operands[1] = lo_part;
4951: }
4952: operands[0] = gen_highpart (SImode, operands[0]);
4953: })
1.1 mrg 4954:
1.3 mrg 4955: (define_expand "zero_extendhisi2"
4956: [(set (match_operand:SI 0 "s_register_operand" "")
4957: (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4958: "TARGET_EITHER"
4959: {
4960: if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4961: {
4962: emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4963: DONE;
4964: }
4965: if (!arm_arch6 && !MEM_P (operands[1]))
1.1 mrg 4966: {
1.3 mrg 4967: rtx t = gen_lowpart (SImode, operands[1]);
4968: rtx tmp = gen_reg_rtx (SImode);
4969: emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4970: emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4971: DONE;
4972: }
4973: })
1.1 mrg 4974:
1.3 mrg 4975: (define_split
4976: [(set (match_operand:SI 0 "s_register_operand" "")
4977: (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
4978: "!TARGET_THUMB2 && !arm_arch6"
4979: [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4980: (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4981: {
4982: operands[2] = gen_lowpart (SImode, operands[1]);
4983: })
1.1 mrg 4984:
4985: (define_insn "*arm_zero_extendhisi2"
1.3 mrg 4986: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4987: (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
1.1 mrg 4988: "TARGET_ARM && arm_arch4 && !arm_arch6"
1.3 mrg 4989: "@
4990: #
1.7 ! mrg 4991: ldrh%?\\t%0, %1"
1.5 mrg 4992: [(set_attr "type" "alu_shift_reg,load_byte")
1.3 mrg 4993: (set_attr "predicable" "yes")]
1.1 mrg 4994: )
4995:
4996: (define_insn "*arm_zero_extendhisi2_v6"
4997: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1.3 mrg 4998: (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
1.1 mrg 4999: "TARGET_ARM && arm_arch6"
5000: "@
5001: uxth%?\\t%0, %1
1.7 ! mrg 5002: ldrh%?\\t%0, %1"
1.3 mrg 5003: [(set_attr "predicable" "yes")
1.5 mrg 5004: (set_attr "type" "extend,load_byte")]
1.1 mrg 5005: )
5006:
5007: (define_insn "*arm_zero_extendhisi2addsi"
5008: [(set (match_operand:SI 0 "s_register_operand" "=r")
5009: (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5010: (match_operand:SI 2 "s_register_operand" "r")))]
5011: "TARGET_INT_SIMD"
5012: "uxtah%?\\t%0, %2, %1"
1.5 mrg 5013: [(set_attr "type" "alu_shift_reg")
5014: (set_attr "predicable" "yes")
5015: (set_attr "predicable_short_it" "no")]
1.1 mrg 5016: )
5017:
5018: (define_expand "zero_extendqisi2"
5019: [(set (match_operand:SI 0 "s_register_operand" "")
5020: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
5021: "TARGET_EITHER"
1.3 mrg 5022: {
5023: if (TARGET_ARM && !arm_arch6 && !MEM_P (operands[1]))
5024: {
5025: emit_insn (gen_andsi3 (operands[0],
5026: gen_lowpart (SImode, operands[1]),
5027: GEN_INT (255)));
5028: DONE;
5029: }
5030: if (!arm_arch6 && !MEM_P (operands[1]))
1.1 mrg 5031: {
1.3 mrg 5032: rtx t = gen_lowpart (SImode, operands[1]);
5033: rtx tmp = gen_reg_rtx (SImode);
5034: emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5035: emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
5036: DONE;
5037: }
5038: })
1.1 mrg 5039:
1.3 mrg 5040: (define_split
5041: [(set (match_operand:SI 0 "s_register_operand" "")
5042: (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
5043: "!arm_arch6"
5044: [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5045: (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
5046: {
5047: operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5048: if (TARGET_ARM)
5049: {
5050: emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
1.1 mrg 5051: DONE;
5052: }
1.3 mrg 5053: })
1.1 mrg 5054:
5055: (define_insn "*arm_zero_extendqisi2"
1.3 mrg 5056: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5057: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1.1 mrg 5058: "TARGET_ARM && !arm_arch6"
1.3 mrg 5059: "@
5060: #
1.7 ! mrg 5061: ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1.3 mrg 5062: [(set_attr "length" "8,4")
1.5 mrg 5063: (set_attr "type" "alu_shift_reg,load_byte")
1.3 mrg 5064: (set_attr "predicable" "yes")]
1.1 mrg 5065: )
5066:
5067: (define_insn "*arm_zero_extendqisi2_v6"
5068: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1.3 mrg 5069: (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))]
1.1 mrg 5070: "TARGET_ARM && arm_arch6"
5071: "@
1.7 ! mrg 5072: uxtb%?\\t%0, %1
! 5073: ldrb%?\\t%0, %1\\t%@ zero_extendqisi2"
1.5 mrg 5074: [(set_attr "type" "extend,load_byte")
1.3 mrg 5075: (set_attr "predicable" "yes")]
1.1 mrg 5076: )
5077:
5078: (define_insn "*arm_zero_extendqisi2addsi"
5079: [(set (match_operand:SI 0 "s_register_operand" "=r")
5080: (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5081: (match_operand:SI 2 "s_register_operand" "r")))]
5082: "TARGET_INT_SIMD"
5083: "uxtab%?\\t%0, %2, %1"
5084: [(set_attr "predicable" "yes")
1.5 mrg 5085: (set_attr "predicable_short_it" "no")
5086: (set_attr "type" "alu_shift_reg")]
1.1 mrg 5087: )
5088:
5089: (define_split
5090: [(set (match_operand:SI 0 "s_register_operand" "")
5091: (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
5092: (clobber (match_operand:SI 2 "s_register_operand" ""))]
1.3 mrg 5093: "TARGET_32BIT && (!MEM_P (operands[1])) && ! BYTES_BIG_ENDIAN"
1.1 mrg 5094: [(set (match_dup 2) (match_dup 1))
5095: (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5096: ""
5097: )
5098:
5099: (define_split
5100: [(set (match_operand:SI 0 "s_register_operand" "")
5101: (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
5102: (clobber (match_operand:SI 2 "s_register_operand" ""))]
1.3 mrg 5103: "TARGET_32BIT && (!MEM_P (operands[1])) && BYTES_BIG_ENDIAN"
1.1 mrg 5104: [(set (match_dup 2) (match_dup 1))
5105: (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
5106: ""
5107: )
5108:
5109:
5110: (define_split
5111: [(set (match_operand:SI 0 "s_register_operand" "")
1.7 ! mrg 5112: (IOR_XOR:SI (and:SI (ashift:SI
1.1 mrg 5113: (match_operand:SI 1 "s_register_operand" "")
5114: (match_operand:SI 2 "const_int_operand" ""))
5115: (match_operand:SI 3 "const_int_operand" ""))
5116: (zero_extend:SI
5117: (match_operator 5 "subreg_lowpart_operator"
5118: [(match_operand:SI 4 "s_register_operand" "")]))))]
5119: "TARGET_32BIT
5120: && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
5121: == (GET_MODE_MASK (GET_MODE (operands[5]))
5122: & (GET_MODE_MASK (GET_MODE (operands[5]))
5123: << (INTVAL (operands[2])))))"
1.7 ! mrg 5124: [(set (match_dup 0) (IOR_XOR:SI (ashift:SI (match_dup 1) (match_dup 2))
1.1 mrg 5125: (match_dup 4)))
5126: (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
5127: "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
5128: )
5129:
5130: (define_insn "*compareqi_eq0"
5131: [(set (reg:CC_Z CC_REGNUM)
5132: (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
5133: (const_int 0)))]
5134: "TARGET_32BIT"
1.3 mrg 5135: "tst%?\\t%0, #255"
5136: [(set_attr "conds" "set")
1.5 mrg 5137: (set_attr "predicable" "yes")
5138: (set_attr "predicable_short_it" "no")
5139: (set_attr "type" "logic_imm")]
1.1 mrg 5140: )
5141:
5142: (define_expand "extendhisi2"
1.3 mrg 5143: [(set (match_operand:SI 0 "s_register_operand" "")
5144: (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
1.1 mrg 5145: "TARGET_EITHER"
1.3 mrg 5146: {
5147: if (TARGET_THUMB1)
5148: {
5149: emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
5150: DONE;
5151: }
5152: if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
5153: {
5154: emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
5155: DONE;
5156: }
1.1 mrg 5157:
1.3 mrg 5158: if (!arm_arch6 && !MEM_P (operands[1]))
5159: {
5160: rtx t = gen_lowpart (SImode, operands[1]);
5161: rtx tmp = gen_reg_rtx (SImode);
5162: emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
5163: emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
5164: DONE;
5165: }
5166: })
1.1 mrg 5167:
1.3 mrg 5168: (define_split
5169: [(parallel
5170: [(set (match_operand:SI 0 "register_operand" "")
5171: (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
5172: (clobber (match_scratch:SI 2 ""))])]
5173: "!arm_arch6"
5174: [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5175: (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5176: {
5177: operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5178: })
1.1 mrg 5179:
5180: ;; This pattern will only be used when ldsh is not available
5181: (define_expand "extendhisi2_mem"
5182: [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
5183: (set (match_dup 3)
5184: (zero_extend:SI (match_dup 7)))
5185: (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
5186: (set (match_operand:SI 0 "" "")
5187: (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
5188: "TARGET_ARM"
5189: "
5190: {
5191: rtx mem1, mem2;
5192: rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
5193:
5194: mem1 = change_address (operands[1], QImode, addr);
1.3 mrg 5195: mem2 = change_address (operands[1], QImode,
5196: plus_constant (Pmode, addr, 1));
1.1 mrg 5197: operands[0] = gen_lowpart (SImode, operands[0]);
5198: operands[1] = mem1;
5199: operands[2] = gen_reg_rtx (SImode);
5200: operands[3] = gen_reg_rtx (SImode);
5201: operands[6] = gen_reg_rtx (SImode);
5202: operands[7] = mem2;
5203:
5204: if (BYTES_BIG_ENDIAN)
5205: {
5206: operands[4] = operands[2];
5207: operands[5] = operands[3];
5208: }
5209: else
5210: {
5211: operands[4] = operands[3];
5212: operands[5] = operands[2];
5213: }
5214: }"
5215: )
5216:
1.3 mrg 5217: (define_split
5218: [(set (match_operand:SI 0 "register_operand" "")
5219: (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
5220: "!arm_arch6"
5221: [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
5222: (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
5223: {
5224: operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
5225: })
5226:
1.1 mrg 5227: (define_insn "*arm_extendhisi2"
1.3 mrg 5228: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5229: (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
1.1 mrg 5230: "TARGET_ARM && arm_arch4 && !arm_arch6"
1.3 mrg 5231: "@
5232: #
1.7 ! mrg 5233: ldrsh%?\\t%0, %1"
1.3 mrg 5234: [(set_attr "length" "8,4")
1.5 mrg 5235: (set_attr "type" "alu_shift_reg,load_byte")
1.3 mrg 5236: (set_attr "predicable" "yes")]
1.1 mrg 5237: )
5238:
5239: ;; ??? Check Thumb-2 pool range
5240: (define_insn "*arm_extendhisi2_v6"
5241: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1.3 mrg 5242: (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))]
1.1 mrg 5243: "TARGET_32BIT && arm_arch6"
5244: "@
5245: sxth%?\\t%0, %1
1.7 ! mrg 5246: ldrsh%?\\t%0, %1"
1.5 mrg 5247: [(set_attr "type" "extend,load_byte")
5248: (set_attr "predicable" "yes")
5249: (set_attr "predicable_short_it" "no")]
1.1 mrg 5250: )
5251:
5252: (define_insn "*arm_extendhisi2addsi"
5253: [(set (match_operand:SI 0 "s_register_operand" "=r")
5254: (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
5255: (match_operand:SI 2 "s_register_operand" "r")))]
5256: "TARGET_INT_SIMD"
5257: "sxtah%?\\t%0, %2, %1"
1.5 mrg 5258: [(set_attr "type" "alu_shift_reg")]
1.1 mrg 5259: )
5260:
5261: (define_expand "extendqihi2"
5262: [(set (match_dup 2)
5263: (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
5264: (const_int 24)))
5265: (set (match_operand:HI 0 "s_register_operand" "")
5266: (ashiftrt:SI (match_dup 2)
5267: (const_int 24)))]
5268: "TARGET_ARM"
5269: "
5270: {
1.3 mrg 5271: if (arm_arch4 && MEM_P (operands[1]))
1.1 mrg 5272: {
1.7 ! mrg 5273: emit_insn (gen_rtx_SET (operands[0],
1.1 mrg 5274: gen_rtx_SIGN_EXTEND (HImode, operands[1])));
5275: DONE;
5276: }
5277: if (!s_register_operand (operands[1], QImode))
5278: operands[1] = copy_to_mode_reg (QImode, operands[1]);
5279: operands[0] = gen_lowpart (SImode, operands[0]);
5280: operands[1] = gen_lowpart (SImode, operands[1]);
5281: operands[2] = gen_reg_rtx (SImode);
5282: }"
5283: )
5284:
5285: (define_insn "*arm_extendqihi_insn"
5286: [(set (match_operand:HI 0 "s_register_operand" "=r")
5287: (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
5288: "TARGET_ARM && arm_arch4"
1.7 ! mrg 5289: "ldrsb%?\\t%0, %1"
1.1 mrg 5290: [(set_attr "type" "load_byte")
1.3 mrg 5291: (set_attr "predicable" "yes")]
1.1 mrg 5292: )
5293:
5294: (define_expand "extendqisi2"
1.3 mrg 5295: [(set (match_operand:SI 0 "s_register_operand" "")
5296: (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
1.1 mrg 5297: "TARGET_EITHER"
1.3 mrg 5298: {
5299: if (!arm_arch4 && MEM_P (operands[1]))
5300: operands[1] = copy_to_mode_reg (QImode, operands[1]);
1.1 mrg 5301:
1.3 mrg 5302: if (!arm_arch6 && !MEM_P (operands[1]))
5303: {
5304: rtx t = gen_lowpart (SImode, operands[1]);
5305: rtx tmp = gen_reg_rtx (SImode);
5306: emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
5307: emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
5308: DONE;
5309: }
5310: })
1.1 mrg 5311:
1.3 mrg 5312: (define_split
5313: [(set (match_operand:SI 0 "register_operand" "")
5314: (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
5315: "!arm_arch6"
5316: [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
5317: (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
5318: {
5319: operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
5320: })
1.1 mrg 5321:
5322: (define_insn "*arm_extendqisi"
1.3 mrg 5323: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5324: (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
1.1 mrg 5325: "TARGET_ARM && arm_arch4 && !arm_arch6"
1.3 mrg 5326: "@
5327: #
1.7 ! mrg 5328: ldrsb%?\\t%0, %1"
1.3 mrg 5329: [(set_attr "length" "8,4")
1.5 mrg 5330: (set_attr "type" "alu_shift_reg,load_byte")
1.3 mrg 5331: (set_attr "predicable" "yes")]
1.1 mrg 5332: )
5333:
5334: (define_insn "*arm_extendqisi_v6"
5335: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5336: (sign_extend:SI
5337: (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5338: "TARGET_ARM && arm_arch6"
5339: "@
5340: sxtb%?\\t%0, %1
1.7 ! mrg 5341: ldrsb%?\\t%0, %1"
1.5 mrg 5342: [(set_attr "type" "extend,load_byte")
1.3 mrg 5343: (set_attr "predicable" "yes")]
1.1 mrg 5344: )
5345:
5346: (define_insn "*arm_extendqisi2addsi"
5347: [(set (match_operand:SI 0 "s_register_operand" "=r")
5348: (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5349: (match_operand:SI 2 "s_register_operand" "r")))]
5350: "TARGET_INT_SIMD"
5351: "sxtab%?\\t%0, %2, %1"
1.5 mrg 5352: [(set_attr "type" "alu_shift_reg")
5353: (set_attr "predicable" "yes")
5354: (set_attr "predicable_short_it" "no")]
1.1 mrg 5355: )
5356:
5357: (define_expand "extendsfdf2"
5358: [(set (match_operand:DF 0 "s_register_operand" "")
5359: (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
5360: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5361: ""
5362: )
5363:
5364: /* HFmode -> DFmode conversions have to go through SFmode. */
5365: (define_expand "extendhfdf2"
5366: [(set (match_operand:DF 0 "general_operand" "")
5367: (float_extend:DF (match_operand:HF 1 "general_operand" "")))]
5368: "TARGET_EITHER"
5369: "
5370: {
5371: rtx op1;
5372: op1 = convert_to_mode (SFmode, operands[1], 0);
5373: op1 = convert_to_mode (DFmode, op1, 0);
5374: emit_insn (gen_movdf (operands[0], op1));
5375: DONE;
5376: }"
5377: )
5378:
5379: ;; Move insns (including loads and stores)
5380:
5381: ;; XXX Just some ideas about movti.
5382: ;; I don't think these are a good idea on the arm, there just aren't enough
5383: ;; registers
5384: ;;(define_expand "loadti"
5385: ;; [(set (match_operand:TI 0 "s_register_operand" "")
5386: ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
5387: ;; "" "")
5388:
5389: ;;(define_expand "storeti"
5390: ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
5391: ;; (match_operand:TI 1 "s_register_operand" ""))]
5392: ;; "" "")
5393:
5394: ;;(define_expand "movti"
5395: ;; [(set (match_operand:TI 0 "general_operand" "")
5396: ;; (match_operand:TI 1 "general_operand" ""))]
5397: ;; ""
5398: ;; "
5399: ;;{
5400: ;; rtx insn;
5401: ;;
1.3 mrg 5402: ;; if (MEM_P (operands[0]) && MEM_P (operands[1]))
1.1 mrg 5403: ;; operands[1] = copy_to_reg (operands[1]);
1.3 mrg 5404: ;; if (MEM_P (operands[0]))
1.1 mrg 5405: ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
1.3 mrg 5406: ;; else if (MEM_P (operands[1]))
1.1 mrg 5407: ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5408: ;; else
5409: ;; FAIL;
5410: ;;
5411: ;; emit_insn (insn);
5412: ;; DONE;
5413: ;;}")
5414:
5415: ;; Recognize garbage generated above.
5416:
5417: ;;(define_insn ""
5418: ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5419: ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5420: ;; ""
5421: ;; "*
5422: ;; {
5423: ;; register mem = (which_alternative < 3);
5424: ;; register const char *template;
5425: ;;
5426: ;; operands[mem] = XEXP (operands[mem], 0);
5427: ;; switch (which_alternative)
5428: ;; {
5429: ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5430: ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
5431: ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
5432: ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
5433: ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
5434: ;; case 5: template = \"stmia\\t%0, %M1\"; break;
5435: ;; }
5436: ;; output_asm_insn (template, operands);
5437: ;; return \"\";
5438: ;; }")
5439:
5440: (define_expand "movdi"
5441: [(set (match_operand:DI 0 "general_operand" "")
5442: (match_operand:DI 1 "general_operand" ""))]
5443: "TARGET_EITHER"
5444: "
5445: if (can_create_pseudo_p ())
5446: {
1.3 mrg 5447: if (!REG_P (operands[0]))
1.1 mrg 5448: operands[1] = force_reg (DImode, operands[1]);
5449: }
1.5 mrg 5450: if (REG_P (operands[0]) && REGNO (operands[0]) <= LAST_ARM_REGNUM
5451: && !HARD_REGNO_MODE_OK (REGNO (operands[0]), DImode))
5452: {
5453: /* Avoid LDRD's into an odd-numbered register pair in ARM state
5454: when expanding function calls. */
5455: gcc_assert (can_create_pseudo_p ());
5456: if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
5457: {
5458: /* Perform load into legal reg pair first, then move. */
5459: rtx reg = gen_reg_rtx (DImode);
5460: emit_insn (gen_movdi (reg, operands[1]));
5461: operands[1] = reg;
5462: }
5463: emit_move_insn (gen_lowpart (SImode, operands[0]),
5464: gen_lowpart (SImode, operands[1]));
5465: emit_move_insn (gen_highpart (SImode, operands[0]),
5466: gen_highpart (SImode, operands[1]));
5467: DONE;
5468: }
5469: else if (REG_P (operands[1]) && REGNO (operands[1]) <= LAST_ARM_REGNUM
5470: && !HARD_REGNO_MODE_OK (REGNO (operands[1]), DImode))
5471: {
5472: /* Avoid STRD's from an odd-numbered register pair in ARM state
5473: when expanding function prologue. */
5474: gcc_assert (can_create_pseudo_p ());
5475: rtx split_dest = (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
5476: ? gen_reg_rtx (DImode)
5477: : operands[0];
5478: emit_move_insn (gen_lowpart (SImode, split_dest),
5479: gen_lowpart (SImode, operands[1]));
5480: emit_move_insn (gen_highpart (SImode, split_dest),
5481: gen_highpart (SImode, operands[1]));
5482: if (split_dest != operands[0])
5483: emit_insn (gen_movdi (operands[0], split_dest));
5484: DONE;
5485: }
1.1 mrg 5486: "
5487: )
5488:
5489: (define_insn "*arm_movdi"
1.5 mrg 5490: [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, q, m")
5491: (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,q"))]
1.3 mrg 5492: "TARGET_32BIT
5493: && !(TARGET_HARD_FLOAT && TARGET_VFP)
1.1 mrg 5494: && !TARGET_IWMMXT
5495: && ( register_operand (operands[0], DImode)
5496: || register_operand (operands[1], DImode))"
5497: "*
5498: switch (which_alternative)
5499: {
5500: case 0:
5501: case 1:
5502: case 2:
5503: return \"#\";
5504: default:
1.3 mrg 5505: return output_move_double (operands, true, NULL);
1.1 mrg 5506: }
5507: "
5508: [(set_attr "length" "8,12,16,8,8")
1.5 mrg 5509: (set_attr "type" "multiple,multiple,multiple,load2,store2")
1.3 mrg 5510: (set_attr "arm_pool_range" "*,*,*,1020,*")
5511: (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
5512: (set_attr "thumb2_pool_range" "*,*,*,4094,*")
5513: (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
1.1 mrg 5514: )
5515:
5516: (define_split
5517: [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
1.5 mrg 5518: (match_operand:ANY64 1 "immediate_operand" ""))]
1.1 mrg 5519: "TARGET_32BIT
5520: && reload_completed
5521: && (arm_const_double_inline_cost (operands[1])
1.5 mrg 5522: <= arm_max_const_double_inline_cost ())"
1.1 mrg 5523: [(const_int 0)]
5524: "
5525: arm_split_constant (SET, SImode, curr_insn,
5526: INTVAL (gen_lowpart (SImode, operands[1])),
5527: gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5528: arm_split_constant (SET, SImode, curr_insn,
5529: INTVAL (gen_highpart_mode (SImode,
5530: GET_MODE (operands[0]),
5531: operands[1])),
5532: gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5533: DONE;
5534: "
5535: )
5536:
5537: ; If optimizing for size, or if we have load delay slots, then
5538: ; we want to split the constant into two separate operations.
5539: ; In both cases this may split a trivial part into a single data op
5540: ; leaving a single complex constant to load. We can also get longer
5541: ; offsets in a LDR which means we get better chances of sharing the pool
5542: ; entries. Finally, we can normally do a better job of scheduling
5543: ; LDR instructions than we can with LDM.
5544: ; This pattern will only match if the one above did not.
5545: (define_split
5546: [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5547: (match_operand:ANY64 1 "const_double_operand" ""))]
5548: "TARGET_ARM && reload_completed
5549: && arm_const_double_by_parts (operands[1])"
5550: [(set (match_dup 0) (match_dup 1))
5551: (set (match_dup 2) (match_dup 3))]
5552: "
5553: operands[2] = gen_highpart (SImode, operands[0]);
5554: operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5555: operands[1]);
5556: operands[0] = gen_lowpart (SImode, operands[0]);
5557: operands[1] = gen_lowpart (SImode, operands[1]);
5558: "
5559: )
5560:
5561: (define_split
5562: [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5563: (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5564: "TARGET_EITHER && reload_completed"
5565: [(set (match_dup 0) (match_dup 1))
5566: (set (match_dup 2) (match_dup 3))]
5567: "
5568: operands[2] = gen_highpart (SImode, operands[0]);
5569: operands[3] = gen_highpart (SImode, operands[1]);
5570: operands[0] = gen_lowpart (SImode, operands[0]);
5571: operands[1] = gen_lowpart (SImode, operands[1]);
5572:
5573: /* Handle a partial overlap. */
5574: if (rtx_equal_p (operands[0], operands[3]))
5575: {
5576: rtx tmp0 = operands[0];
5577: rtx tmp1 = operands[1];
5578:
5579: operands[0] = operands[2];
5580: operands[1] = operands[3];
5581: operands[2] = tmp0;
5582: operands[3] = tmp1;
5583: }
5584: "
5585: )
5586:
5587: ;; We can't actually do base+index doubleword loads if the index and
5588: ;; destination overlap. Split here so that we at least have chance to
5589: ;; schedule.
5590: (define_split
5591: [(set (match_operand:DI 0 "s_register_operand" "")
5592: (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5593: (match_operand:SI 2 "s_register_operand" ""))))]
5594: "TARGET_LDRD
5595: && reg_overlap_mentioned_p (operands[0], operands[1])
5596: && reg_overlap_mentioned_p (operands[0], operands[2])"
5597: [(set (match_dup 4)
5598: (plus:SI (match_dup 1)
5599: (match_dup 2)))
5600: (set (match_dup 0)
5601: (mem:DI (match_dup 4)))]
5602: "
5603: operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5604: "
5605: )
5606:
5607: (define_expand "movsi"
5608: [(set (match_operand:SI 0 "general_operand" "")
5609: (match_operand:SI 1 "general_operand" ""))]
5610: "TARGET_EITHER"
5611: "
5612: {
5613: rtx base, offset, tmp;
5614:
5615: if (TARGET_32BIT)
5616: {
5617: /* Everything except mem = const or mem = mem can be done easily. */
1.3 mrg 5618: if (MEM_P (operands[0]))
1.1 mrg 5619: operands[1] = force_reg (SImode, operands[1]);
5620: if (arm_general_register_operand (operands[0], SImode)
1.3 mrg 5621: && CONST_INT_P (operands[1])
1.1 mrg 5622: && !(const_ok_for_arm (INTVAL (operands[1]))
5623: || const_ok_for_arm (~INTVAL (operands[1]))))
5624: {
1.7 ! mrg 5625: if (DONT_EARLY_SPLIT_CONSTANT (INTVAL (operands[1]), SET))
! 5626: {
! 5627: emit_insn (gen_rtx_SET (operands[0], operands[1]));
! 5628: DONE;
! 5629: }
! 5630: else
! 5631: {
! 5632: arm_split_constant (SET, SImode, NULL_RTX,
! 5633: INTVAL (operands[1]), operands[0], NULL_RTX,
! 5634: optimize && can_create_pseudo_p ());
! 5635: DONE;
! 5636: }
1.1 mrg 5637: }
5638: }
5639: else /* TARGET_THUMB1... */
5640: {
5641: if (can_create_pseudo_p ())
5642: {
1.3 mrg 5643: if (!REG_P (operands[0]))
1.1 mrg 5644: operands[1] = force_reg (SImode, operands[1]);
5645: }
5646: }
5647:
5648: if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5649: {
5650: split_const (operands[1], &base, &offset);
5651: if (GET_CODE (base) == SYMBOL_REF
5652: && !offset_within_block_p (base, INTVAL (offset)))
5653: {
5654: tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5655: emit_move_insn (tmp, base);
5656: emit_insn (gen_addsi3 (operands[0], tmp, offset));
5657: DONE;
5658: }
5659: }
5660:
5661: /* Recognize the case where operand[1] is a reference to thread-local
5662: data and load its address to a register. */
5663: if (arm_tls_referenced_p (operands[1]))
5664: {
5665: rtx tmp = operands[1];
5666: rtx addend = NULL;
5667:
5668: if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5669: {
5670: addend = XEXP (XEXP (tmp, 0), 1);
5671: tmp = XEXP (XEXP (tmp, 0), 0);
5672: }
5673:
5674: gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5675: gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5676:
5677: tmp = legitimize_tls_address (tmp,
5678: !can_create_pseudo_p () ? operands[0] : 0);
5679: if (addend)
5680: {
5681: tmp = gen_rtx_PLUS (SImode, tmp, addend);
5682: tmp = force_operand (tmp, operands[0]);
5683: }
5684: operands[1] = tmp;
5685: }
5686: else if (flag_pic
5687: && (CONSTANT_P (operands[1])
5688: || symbol_mentioned_p (operands[1])
5689: || label_mentioned_p (operands[1])))
5690: operands[1] = legitimize_pic_address (operands[1], SImode,
5691: (!can_create_pseudo_p ()
5692: ? operands[0]
5693: : 0));
5694: }
5695: "
5696: )
5697:
5698: ;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5699: ;; LO_SUM adds in the high bits. Fortunately these are opaque operations
5700: ;; so this does not matter.
5701: (define_insn "*arm_movt"
5702: [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5703: (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5704: (match_operand:SI 2 "general_operand" "i")))]
1.5 mrg 5705: "arm_arch_thumb2 && arm_valid_symbolic_address_p (operands[2])"
1.1 mrg 5706: "movt%?\t%0, #:upper16:%c2"
5707: [(set_attr "predicable" "yes")
1.5 mrg 5708: (set_attr "predicable_short_it" "no")
5709: (set_attr "length" "4")
1.7 ! mrg 5710: (set_attr "type" "alu_sreg")]
1.1 mrg 5711: )
5712:
5713: (define_insn "*arm_movsi_insn"
5714: [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5715: (match_operand:SI 1 "general_operand" "rk, I,K,j,mi,rk"))]
5716: "TARGET_ARM && ! TARGET_IWMMXT
5717: && !(TARGET_HARD_FLOAT && TARGET_VFP)
5718: && ( register_operand (operands[0], SImode)
5719: || register_operand (operands[1], SImode))"
5720: "@
5721: mov%?\\t%0, %1
5722: mov%?\\t%0, %1
5723: mvn%?\\t%0, #%B1
5724: movw%?\\t%0, %1
5725: ldr%?\\t%0, %1
5726: str%?\\t%1, %0"
1.5 mrg 5727: [(set_attr "type" "mov_reg,mov_imm,mvn_imm,mov_imm,load1,store1")
1.1 mrg 5728: (set_attr "predicable" "yes")
5729: (set_attr "pool_range" "*,*,*,*,4096,*")
5730: (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5731: )
5732:
5733: (define_split
5734: [(set (match_operand:SI 0 "arm_general_register_operand" "")
5735: (match_operand:SI 1 "const_int_operand" ""))]
5736: "TARGET_32BIT
5737: && (!(const_ok_for_arm (INTVAL (operands[1]))
5738: || const_ok_for_arm (~INTVAL (operands[1]))))"
5739: [(clobber (const_int 0))]
5740: "
5741: arm_split_constant (SET, SImode, NULL_RTX,
5742: INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5743: DONE;
5744: "
5745: )
5746:
1.5 mrg 5747: ;; A normal way to do (symbol + offset) requires three instructions at least
5748: ;; (depends on how big the offset is) as below:
5749: ;; movw r0, #:lower16:g
5750: ;; movw r0, #:upper16:g
5751: ;; adds r0, #4
5752: ;;
5753: ;; A better way would be:
5754: ;; movw r0, #:lower16:g+4
5755: ;; movw r0, #:upper16:g+4
5756: ;;
5757: ;; The limitation of this way is that the length of offset should be a 16-bit
5758: ;; signed value, because current assembler only supports REL type relocation for
5759: ;; such case. If the more powerful RELA type is supported in future, we should
5760: ;; update this pattern to go with better way.
5761: (define_split
5762: [(set (match_operand:SI 0 "arm_general_register_operand" "")
5763: (const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
5764: (match_operand:SI 2 "const_int_operand" ""))))]
5765: "TARGET_THUMB2
5766: && arm_disable_literal_pool
5767: && reload_completed
5768: && GET_CODE (operands[1]) == SYMBOL_REF"
5769: [(clobber (const_int 0))]
5770: "
5771: int offset = INTVAL (operands[2]);
5772:
5773: if (offset < -0x8000 || offset > 0x7fff)
5774: {
5775: arm_emit_movpair (operands[0], operands[1]);
1.7 ! mrg 5776: emit_insn (gen_rtx_SET (operands[0],
1.5 mrg 5777: gen_rtx_PLUS (SImode, operands[0], operands[2])));
5778: }
5779: else
5780: {
5781: rtx op = gen_rtx_CONST (SImode,
5782: gen_rtx_PLUS (SImode, operands[1], operands[2]));
5783: arm_emit_movpair (operands[0], op);
5784: }
5785: "
5786: )
5787:
1.3 mrg 5788: ;; Split symbol_refs at the later stage (after cprop), instead of generating
5789: ;; movt/movw pair directly at expand. Otherwise corresponding high_sum
5790: ;; and lo_sum would be merged back into memory load at cprop. However,
5791: ;; if the default is to prefer movt/movw rather than a load from the constant
5792: ;; pool, the performance is better.
5793: (define_split
5794: [(set (match_operand:SI 0 "arm_general_register_operand" "")
5795: (match_operand:SI 1 "general_operand" ""))]
5796: "TARGET_32BIT
5797: && TARGET_USE_MOVT && GET_CODE (operands[1]) == SYMBOL_REF
5798: && !flag_pic && !target_word_relocations
5799: && !arm_tls_referenced_p (operands[1])"
5800: [(clobber (const_int 0))]
5801: {
5802: arm_emit_movpair (operands[0], operands[1]);
5803: DONE;
5804: })
5805:
1.5 mrg 5806: ;; When generating pic, we need to load the symbol offset into a register.
5807: ;; So that the optimizer does not confuse this with a normal symbol load
5808: ;; we use an unspec. The offset will be loaded from a constant pool entry,
5809: ;; since that is the only type of relocation we can use.
1.1 mrg 5810:
1.5 mrg 5811: ;; Wrap calculation of the whole PIC address in a single pattern for the
5812: ;; benefit of optimizers, particularly, PRE and HOIST. Calculation of
5813: ;; a PIC address involves two loads from memory, so we want to CSE it
5814: ;; as often as possible.
5815: ;; This pattern will be split into one of the pic_load_addr_* patterns
5816: ;; and a move after GCSE optimizations.
5817: ;;
5818: ;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5819: (define_expand "calculate_pic_address"
1.1 mrg 5820: [(set (match_operand:SI 0 "register_operand" "")
1.5 mrg 5821: (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5822: (unspec:SI [(match_operand:SI 2 "" "")]
5823: UNSPEC_PIC_SYM))))]
5824: "flag_pic"
1.1 mrg 5825: )
5826:
1.5 mrg 5827: ;; Split calculate_pic_address into pic_load_addr_* and a move.
1.3 mrg 5828: (define_split
5829: [(set (match_operand:SI 0 "register_operand" "")
5830: (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5831: (unspec:SI [(match_operand:SI 2 "" "")]
5832: UNSPEC_PIC_SYM))))]
5833: "flag_pic"
5834: [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5835: (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5836: "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5837: )
5838:
5839: ;; operand1 is the memory address to go into
5840: ;; pic_load_addr_32bit.
5841: ;; operand2 is the PIC label to be emitted
5842: ;; from pic_add_dot_plus_eight.
5843: ;; We do this to allow hoisting of the entire insn.
5844: (define_insn_and_split "pic_load_addr_unified"
5845: [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5846: (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5847: (match_operand:SI 2 "" "")]
5848: UNSPEC_PIC_UNIFIED))]
5849: "flag_pic"
5850: "#"
5851: "&& reload_completed"
5852: [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5853: (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5854: (match_dup 2)] UNSPEC_PIC_BASE))]
5855: "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5856: [(set_attr "type" "load1,load1,load1")
5857: (set_attr "pool_range" "4096,4094,1022")
5858: (set_attr "neg_pool_range" "4084,0,0")
5859: (set_attr "arch" "a,t2,t1")
5860: (set_attr "length" "8,6,4")]
5861: )
5862:
1.1 mrg 5863: ;; The rather odd constraints on the following are to force reload to leave
5864: ;; the insn alone, and to force the minipool generation pass to then move
5865: ;; the GOT symbol to memory.
5866:
5867: (define_insn "pic_load_addr_32bit"
5868: [(set (match_operand:SI 0 "s_register_operand" "=r")
5869: (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5870: "TARGET_32BIT && flag_pic"
5871: "ldr%?\\t%0, %1"
5872: [(set_attr "type" "load1")
1.3 mrg 5873: (set (attr "pool_range")
5874: (if_then_else (eq_attr "is_thumb" "no")
5875: (const_int 4096)
5876: (const_int 4094)))
1.1 mrg 5877: (set (attr "neg_pool_range")
5878: (if_then_else (eq_attr "is_thumb" "no")
5879: (const_int 4084)
5880: (const_int 0)))]
5881: )
5882:
5883: (define_insn "pic_load_addr_thumb1"
5884: [(set (match_operand:SI 0 "s_register_operand" "=l")
5885: (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5886: "TARGET_THUMB1 && flag_pic"
5887: "ldr\\t%0, %1"
5888: [(set_attr "type" "load1")
1.3 mrg 5889: (set (attr "pool_range") (const_int 1018))]
1.1 mrg 5890: )
5891:
5892: (define_insn "pic_add_dot_plus_four"
5893: [(set (match_operand:SI 0 "register_operand" "=r")
5894: (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5895: (const_int 4)
5896: (match_operand 2 "" "")]
5897: UNSPEC_PIC_BASE))]
5898: "TARGET_THUMB"
5899: "*
5900: (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5901: INTVAL (operands[2]));
5902: return \"add\\t%0, %|pc\";
5903: "
1.5 mrg 5904: [(set_attr "length" "2")
5905: (set_attr "type" "alu_sreg")]
1.1 mrg 5906: )
5907:
5908: (define_insn "pic_add_dot_plus_eight"
5909: [(set (match_operand:SI 0 "register_operand" "=r")
5910: (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5911: (const_int 8)
5912: (match_operand 2 "" "")]
5913: UNSPEC_PIC_BASE))]
5914: "TARGET_ARM"
5915: "*
5916: (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5917: INTVAL (operands[2]));
5918: return \"add%?\\t%0, %|pc, %1\";
5919: "
1.5 mrg 5920: [(set_attr "predicable" "yes")
5921: (set_attr "type" "alu_sreg")]
1.1 mrg 5922: )
5923:
5924: (define_insn "tls_load_dot_plus_eight"
5925: [(set (match_operand:SI 0 "register_operand" "=r")
5926: (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5927: (const_int 8)
5928: (match_operand 2 "" "")]
5929: UNSPEC_PIC_BASE)))]
5930: "TARGET_ARM"
5931: "*
5932: (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5933: INTVAL (operands[2]));
5934: return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5935: "
1.5 mrg 5936: [(set_attr "predicable" "yes")
5937: (set_attr "type" "load1")]
1.1 mrg 5938: )
5939:
5940: ;; PIC references to local variables can generate pic_add_dot_plus_eight
5941: ;; followed by a load. These sequences can be crunched down to
5942: ;; tls_load_dot_plus_eight by a peephole.
5943:
5944: (define_peephole2
5945: [(set (match_operand:SI 0 "register_operand" "")
5946: (unspec:SI [(match_operand:SI 3 "register_operand" "")
5947: (const_int 8)
5948: (match_operand 1 "" "")]
5949: UNSPEC_PIC_BASE))
1.3 mrg 5950: (set (match_operand:SI 2 "arm_general_register_operand" "")
5951: (mem:SI (match_dup 0)))]
1.1 mrg 5952: "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5953: [(set (match_dup 2)
5954: (mem:SI (unspec:SI [(match_dup 3)
5955: (const_int 8)
5956: (match_dup 1)]
5957: UNSPEC_PIC_BASE)))]
5958: ""
5959: )
5960:
5961: (define_insn "pic_offset_arm"
5962: [(set (match_operand:SI 0 "register_operand" "=r")
5963: (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5964: (unspec:SI [(match_operand:SI 2 "" "X")]
5965: UNSPEC_PIC_OFFSET))))]
5966: "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5967: "ldr%?\\t%0, [%1,%2]"
5968: [(set_attr "type" "load1")]
5969: )
5970:
5971: (define_expand "builtin_setjmp_receiver"
5972: [(label_ref (match_operand 0 "" ""))]
5973: "flag_pic"
5974: "
5975: {
5976: /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5977: register. */
5978: if (arm_pic_register != INVALID_REGNUM)
5979: arm_load_pic_register (1UL << 3);
5980: DONE;
5981: }")
5982:
5983: ;; If copying one reg to another we can set the condition codes according to
5984: ;; its value. Such a move is common after a return from subroutine and the
5985: ;; result is being tested against zero.
5986:
5987: (define_insn "*movsi_compare0"
5988: [(set (reg:CC CC_REGNUM)
5989: (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5990: (const_int 0)))
5991: (set (match_operand:SI 0 "s_register_operand" "=r,r")
5992: (match_dup 1))]
5993: "TARGET_32BIT"
5994: "@
5995: cmp%?\\t%0, #0
1.7 ! mrg 5996: subs%?\\t%0, %1, #0"
1.3 mrg 5997: [(set_attr "conds" "set")
1.5 mrg 5998: (set_attr "type" "alus_imm,alus_imm")]
1.1 mrg 5999: )
6000:
6001: ;; Subroutine to store a half word from a register into memory.
6002: ;; Operand 0 is the source register (HImode)
6003: ;; Operand 1 is the destination address in a register (SImode)
6004:
6005: ;; In both this routine and the next, we must be careful not to spill
6006: ;; a memory address of reg+large_const into a separate PLUS insn, since this
6007: ;; can generate unrecognizable rtl.
6008:
6009: (define_expand "storehi"
6010: [;; store the low byte
6011: (set (match_operand 1 "" "") (match_dup 3))
6012: ;; extract the high byte
6013: (set (match_dup 2)
6014: (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
6015: ;; store the high byte
6016: (set (match_dup 4) (match_dup 5))]
6017: "TARGET_ARM"
6018: "
6019: {
6020: rtx op1 = operands[1];
6021: rtx addr = XEXP (op1, 0);
6022: enum rtx_code code = GET_CODE (addr);
6023:
1.3 mrg 6024: if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
1.1 mrg 6025: || code == MINUS)
6026: op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
6027:
6028: operands[4] = adjust_address (op1, QImode, 1);
6029: operands[1] = adjust_address (operands[1], QImode, 0);
6030: operands[3] = gen_lowpart (QImode, operands[0]);
6031: operands[0] = gen_lowpart (SImode, operands[0]);
6032: operands[2] = gen_reg_rtx (SImode);
6033: operands[5] = gen_lowpart (QImode, operands[2]);
6034: }"
6035: )
6036:
6037: (define_expand "storehi_bigend"
6038: [(set (match_dup 4) (match_dup 3))
6039: (set (match_dup 2)
6040: (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
6041: (set (match_operand 1 "" "") (match_dup 5))]
6042: "TARGET_ARM"
6043: "
6044: {
6045: rtx op1 = operands[1];
6046: rtx addr = XEXP (op1, 0);
6047: enum rtx_code code = GET_CODE (addr);
6048:
1.3 mrg 6049: if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
1.1 mrg 6050: || code == MINUS)
6051: op1 = replace_equiv_address (op1, force_reg (SImode, addr));
6052:
6053: operands[4] = adjust_address (op1, QImode, 1);
6054: operands[1] = adjust_address (operands[1], QImode, 0);
6055: operands[3] = gen_lowpart (QImode, operands[0]);
6056: operands[0] = gen_lowpart (SImode, operands[0]);
6057: operands[2] = gen_reg_rtx (SImode);
6058: operands[5] = gen_lowpart (QImode, operands[2]);
6059: }"
6060: )
6061:
6062: ;; Subroutine to store a half word integer constant into memory.
6063: (define_expand "storeinthi"
6064: [(set (match_operand 0 "" "")
6065: (match_operand 1 "" ""))
6066: (set (match_dup 3) (match_dup 2))]
6067: "TARGET_ARM"
6068: "
6069: {
6070: HOST_WIDE_INT value = INTVAL (operands[1]);
6071: rtx addr = XEXP (operands[0], 0);
6072: rtx op0 = operands[0];
6073: enum rtx_code code = GET_CODE (addr);
6074:
1.3 mrg 6075: if ((code == PLUS && !CONST_INT_P (XEXP (addr, 1)))
1.1 mrg 6076: || code == MINUS)
6077: op0 = replace_equiv_address (op0, force_reg (SImode, addr));
6078:
6079: operands[1] = gen_reg_rtx (SImode);
6080: if (BYTES_BIG_ENDIAN)
6081: {
6082: emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
6083: if ((value & 255) == ((value >> 8) & 255))
6084: operands[2] = operands[1];
6085: else
6086: {
6087: operands[2] = gen_reg_rtx (SImode);
6088: emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
6089: }
6090: }
6091: else
6092: {
6093: emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
6094: if ((value & 255) == ((value >> 8) & 255))
6095: operands[2] = operands[1];
6096: else
6097: {
6098: operands[2] = gen_reg_rtx (SImode);
6099: emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
6100: }
6101: }
6102:
6103: operands[3] = adjust_address (op0, QImode, 1);
6104: operands[0] = adjust_address (operands[0], QImode, 0);
6105: operands[2] = gen_lowpart (QImode, operands[2]);
6106: operands[1] = gen_lowpart (QImode, operands[1]);
6107: }"
6108: )
6109:
6110: (define_expand "storehi_single_op"
6111: [(set (match_operand:HI 0 "memory_operand" "")
6112: (match_operand:HI 1 "general_operand" ""))]
6113: "TARGET_32BIT && arm_arch4"
6114: "
6115: if (!s_register_operand (operands[1], HImode))
6116: operands[1] = copy_to_mode_reg (HImode, operands[1]);
6117: "
6118: )
6119:
6120: (define_expand "movhi"
6121: [(set (match_operand:HI 0 "general_operand" "")
6122: (match_operand:HI 1 "general_operand" ""))]
6123: "TARGET_EITHER"
6124: "
6125: if (TARGET_ARM)
6126: {
6127: if (can_create_pseudo_p ())
6128: {
1.3 mrg 6129: if (MEM_P (operands[0]))
1.1 mrg 6130: {
6131: if (arm_arch4)
6132: {
6133: emit_insn (gen_storehi_single_op (operands[0], operands[1]));
6134: DONE;
6135: }
1.3 mrg 6136: if (CONST_INT_P (operands[1]))
1.1 mrg 6137: emit_insn (gen_storeinthi (operands[0], operands[1]));
6138: else
6139: {
1.3 mrg 6140: if (MEM_P (operands[1]))
1.1 mrg 6141: operands[1] = force_reg (HImode, operands[1]);
6142: if (BYTES_BIG_ENDIAN)
6143: emit_insn (gen_storehi_bigend (operands[1], operands[0]));
6144: else
6145: emit_insn (gen_storehi (operands[1], operands[0]));
6146: }
6147: DONE;
6148: }
6149: /* Sign extend a constant, and keep it in an SImode reg. */
1.3 mrg 6150: else if (CONST_INT_P (operands[1]))
1.1 mrg 6151: {
6152: rtx reg = gen_reg_rtx (SImode);
6153: HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6154:
6155: /* If the constant is already valid, leave it alone. */
6156: if (!const_ok_for_arm (val))
6157: {
6158: /* If setting all the top bits will make the constant
6159: loadable in a single instruction, then set them.
6160: Otherwise, sign extend the number. */
6161:
6162: if (const_ok_for_arm (~(val | ~0xffff)))
6163: val |= ~0xffff;
6164: else if (val & 0x8000)
6165: val |= ~0xffff;
6166: }
6167:
6168: emit_insn (gen_movsi (reg, GEN_INT (val)));
6169: operands[1] = gen_lowpart (HImode, reg);
6170: }
6171: else if (arm_arch4 && optimize && can_create_pseudo_p ()
1.3 mrg 6172: && MEM_P (operands[1]))
1.1 mrg 6173: {
6174: rtx reg = gen_reg_rtx (SImode);
6175:
6176: emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6177: operands[1] = gen_lowpart (HImode, reg);
6178: }
6179: else if (!arm_arch4)
6180: {
1.3 mrg 6181: if (MEM_P (operands[1]))
1.1 mrg 6182: {
6183: rtx base;
6184: rtx offset = const0_rtx;
6185: rtx reg = gen_reg_rtx (SImode);
6186:
1.3 mrg 6187: if ((REG_P (base = XEXP (operands[1], 0))
1.1 mrg 6188: || (GET_CODE (base) == PLUS
1.3 mrg 6189: && (CONST_INT_P (offset = XEXP (base, 1)))
1.1 mrg 6190: && ((INTVAL(offset) & 1) != 1)
1.3 mrg 6191: && REG_P (base = XEXP (base, 0))))
1.1 mrg 6192: && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
6193: {
6194: rtx new_rtx;
6195:
6196: new_rtx = widen_memory_access (operands[1], SImode,
6197: ((INTVAL (offset) & ~3)
6198: - INTVAL (offset)));
6199: emit_insn (gen_movsi (reg, new_rtx));
6200: if (((INTVAL (offset) & 2) != 0)
6201: ^ (BYTES_BIG_ENDIAN ? 1 : 0))
6202: {
6203: rtx reg2 = gen_reg_rtx (SImode);
6204:
6205: emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
6206: reg = reg2;
6207: }
6208: }
6209: else
6210: emit_insn (gen_movhi_bytes (reg, operands[1]));
6211:
6212: operands[1] = gen_lowpart (HImode, reg);
6213: }
6214: }
6215: }
6216: /* Handle loading a large integer during reload. */
1.3 mrg 6217: else if (CONST_INT_P (operands[1])
1.1 mrg 6218: && !const_ok_for_arm (INTVAL (operands[1]))
6219: && !const_ok_for_arm (~INTVAL (operands[1])))
6220: {
6221: /* Writing a constant to memory needs a scratch, which should
6222: be handled with SECONDARY_RELOADs. */
1.3 mrg 6223: gcc_assert (REG_P (operands[0]));
1.1 mrg 6224:
6225: operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6226: emit_insn (gen_movsi (operands[0], operands[1]));
6227: DONE;
6228: }
6229: }
6230: else if (TARGET_THUMB2)
6231: {
6232: /* Thumb-2 can do everything except mem=mem and mem=const easily. */
6233: if (can_create_pseudo_p ())
6234: {
1.3 mrg 6235: if (!REG_P (operands[0]))
1.1 mrg 6236: operands[1] = force_reg (HImode, operands[1]);
6237: /* Zero extend a constant, and keep it in an SImode reg. */
1.3 mrg 6238: else if (CONST_INT_P (operands[1]))
1.1 mrg 6239: {
6240: rtx reg = gen_reg_rtx (SImode);
6241: HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6242:
6243: emit_insn (gen_movsi (reg, GEN_INT (val)));
6244: operands[1] = gen_lowpart (HImode, reg);
6245: }
6246: }
6247: }
6248: else /* TARGET_THUMB1 */
6249: {
6250: if (can_create_pseudo_p ())
6251: {
1.3 mrg 6252: if (CONST_INT_P (operands[1]))
1.1 mrg 6253: {
6254: rtx reg = gen_reg_rtx (SImode);
6255:
6256: emit_insn (gen_movsi (reg, operands[1]));
6257: operands[1] = gen_lowpart (HImode, reg);
6258: }
6259:
6260: /* ??? We shouldn't really get invalid addresses here, but this can
6261: happen if we are passed a SP (never OK for HImode/QImode) or
6262: virtual register (also rejected as illegitimate for HImode/QImode)
6263: relative address. */
6264: /* ??? This should perhaps be fixed elsewhere, for instance, in
6265: fixup_stack_1, by checking for other kinds of invalid addresses,
6266: e.g. a bare reference to a virtual register. This may confuse the
6267: alpha though, which must handle this case differently. */
1.3 mrg 6268: if (MEM_P (operands[0])
1.1 mrg 6269: && !memory_address_p (GET_MODE (operands[0]),
6270: XEXP (operands[0], 0)))
6271: operands[0]
6272: = replace_equiv_address (operands[0],
6273: copy_to_reg (XEXP (operands[0], 0)));
6274:
1.3 mrg 6275: if (MEM_P (operands[1])
1.1 mrg 6276: && !memory_address_p (GET_MODE (operands[1]),
6277: XEXP (operands[1], 0)))
6278: operands[1]
6279: = replace_equiv_address (operands[1],
6280: copy_to_reg (XEXP (operands[1], 0)));
6281:
1.3 mrg 6282: if (MEM_P (operands[1]) && optimize > 0)
1.1 mrg 6283: {
6284: rtx reg = gen_reg_rtx (SImode);
6285:
6286: emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6287: operands[1] = gen_lowpart (HImode, reg);
6288: }
6289:
1.3 mrg 6290: if (MEM_P (operands[0]))
1.1 mrg 6291: operands[1] = force_reg (HImode, operands[1]);
6292: }
1.3 mrg 6293: else if (CONST_INT_P (operands[1])
1.1 mrg 6294: && !satisfies_constraint_I (operands[1]))
6295: {
6296: /* Handle loading a large integer during reload. */
6297:
6298: /* Writing a constant to memory needs a scratch, which should
6299: be handled with SECONDARY_RELOADs. */
1.3 mrg 6300: gcc_assert (REG_P (operands[0]));
1.1 mrg 6301:
6302: operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6303: emit_insn (gen_movsi (operands[0], operands[1]));
6304: DONE;
6305: }
6306: }
6307: "
6308: )
6309:
6310: (define_expand "movhi_bytes"
6311: [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
6312: (set (match_dup 3)
6313: (zero_extend:SI (match_dup 6)))
6314: (set (match_operand:SI 0 "" "")
6315: (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
6316: "TARGET_ARM"
6317: "
6318: {
6319: rtx mem1, mem2;
6320: rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6321:
6322: mem1 = change_address (operands[1], QImode, addr);
1.3 mrg 6323: mem2 = change_address (operands[1], QImode,
6324: plus_constant (Pmode, addr, 1));
1.1 mrg 6325: operands[0] = gen_lowpart (SImode, operands[0]);
6326: operands[1] = mem1;
6327: operands[2] = gen_reg_rtx (SImode);
6328: operands[3] = gen_reg_rtx (SImode);
6329: operands[6] = mem2;
6330:
6331: if (BYTES_BIG_ENDIAN)
6332: {
6333: operands[4] = operands[2];
6334: operands[5] = operands[3];
6335: }
6336: else
6337: {
6338: operands[4] = operands[3];
6339: operands[5] = operands[2];
6340: }
6341: }"
6342: )
6343:
6344: (define_expand "movhi_bigend"
6345: [(set (match_dup 2)
6346: (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6347: (const_int 16)))
6348: (set (match_dup 3)
6349: (ashiftrt:SI (match_dup 2) (const_int 16)))
6350: (set (match_operand:HI 0 "s_register_operand" "")
6351: (match_dup 4))]
6352: "TARGET_ARM"
6353: "
6354: operands[2] = gen_reg_rtx (SImode);
6355: operands[3] = gen_reg_rtx (SImode);
6356: operands[4] = gen_lowpart (HImode, operands[3]);
6357: "
6358: )
6359:
6360: ;; Pattern to recognize insn generated default case above
6361: (define_insn "*movhi_insn_arch4"
1.3 mrg 6362: [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r")
1.5 mrg 6363: (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))]
1.1 mrg 6364: "TARGET_ARM
6365: && arm_arch4
1.3 mrg 6366: && (register_operand (operands[0], HImode)
6367: || register_operand (operands[1], HImode))"
1.1 mrg 6368: "@
6369: mov%?\\t%0, %1\\t%@ movhi
6370: mvn%?\\t%0, #%B1\\t%@ movhi
1.3 mrg 6371: movw%?\\t%0, %L1\\t%@ movhi
1.7 ! mrg 6372: strh%?\\t%1, %0\\t%@ movhi
! 6373: ldrh%?\\t%0, %1\\t%@ movhi"
1.3 mrg 6374: [(set_attr "predicable" "yes")
6375: (set_attr "pool_range" "*,*,*,*,256")
6376: (set_attr "neg_pool_range" "*,*,*,*,244")
6377: (set_attr "arch" "*,*,v6t2,*,*")
6378: (set_attr_alternative "type"
6379: [(if_then_else (match_operand 1 "const_int_operand" "")
1.5 mrg 6380: (const_string "mov_imm" )
6381: (const_string "mov_reg"))
6382: (const_string "mvn_imm")
6383: (const_string "mov_imm")
1.3 mrg 6384: (const_string "store1")
6385: (const_string "load1")])]
1.1 mrg 6386: )
6387:
6388: (define_insn "*movhi_bytes"
1.3 mrg 6389: [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
1.5 mrg 6390: (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))]
1.1 mrg 6391: "TARGET_ARM"
6392: "@
6393: mov%?\\t%0, %1\\t%@ movhi
1.3 mrg 6394: mov%?\\t%0, %1\\t%@ movhi
1.1 mrg 6395: mvn%?\\t%0, #%B1\\t%@ movhi"
1.3 mrg 6396: [(set_attr "predicable" "yes")
1.5 mrg 6397: (set_attr "type" "mov_imm,mov_reg,mvn_imm")]
1.1 mrg 6398: )
6399:
6400: ;; We use a DImode scratch because we may occasionally need an additional
6401: ;; temporary if the address isn't offsettable -- push_reload doesn't seem
6402: ;; to take any notice of the "o" constraints on reload_memory_operand operand.
6403: (define_expand "reload_outhi"
6404: [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
6405: (match_operand:HI 1 "s_register_operand" "r")
6406: (match_operand:DI 2 "s_register_operand" "=&l")])]
6407: "TARGET_EITHER"
6408: "if (TARGET_ARM)
6409: arm_reload_out_hi (operands);
6410: else
6411: thumb_reload_out_hi (operands);
6412: DONE;
6413: "
6414: )
6415:
6416: (define_expand "reload_inhi"
6417: [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
6418: (match_operand:HI 1 "arm_reload_memory_operand" "o")
6419: (match_operand:DI 2 "s_register_operand" "=&r")])]
6420: "TARGET_EITHER"
6421: "
6422: if (TARGET_ARM)
6423: arm_reload_in_hi (operands);
6424: else
6425: thumb_reload_out_hi (operands);
6426: DONE;
6427: ")
6428:
6429: (define_expand "movqi"
6430: [(set (match_operand:QI 0 "general_operand" "")
6431: (match_operand:QI 1 "general_operand" ""))]
6432: "TARGET_EITHER"
6433: "
6434: /* Everything except mem = const or mem = mem can be done easily */
6435:
6436: if (can_create_pseudo_p ())
6437: {
1.3 mrg 6438: if (CONST_INT_P (operands[1]))
1.1 mrg 6439: {
6440: rtx reg = gen_reg_rtx (SImode);
6441:
6442: /* For thumb we want an unsigned immediate, then we are more likely
6443: to be able to use a movs insn. */
6444: if (TARGET_THUMB)
6445: operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6446:
6447: emit_insn (gen_movsi (reg, operands[1]));
6448: operands[1] = gen_lowpart (QImode, reg);
6449: }
6450:
6451: if (TARGET_THUMB)
6452: {
6453: /* ??? We shouldn't really get invalid addresses here, but this can
6454: happen if we are passed a SP (never OK for HImode/QImode) or
6455: virtual register (also rejected as illegitimate for HImode/QImode)
6456: relative address. */
6457: /* ??? This should perhaps be fixed elsewhere, for instance, in
6458: fixup_stack_1, by checking for other kinds of invalid addresses,
6459: e.g. a bare reference to a virtual register. This may confuse the
6460: alpha though, which must handle this case differently. */
1.3 mrg 6461: if (MEM_P (operands[0])
1.1 mrg 6462: && !memory_address_p (GET_MODE (operands[0]),
6463: XEXP (operands[0], 0)))
6464: operands[0]
6465: = replace_equiv_address (operands[0],
6466: copy_to_reg (XEXP (operands[0], 0)));
1.3 mrg 6467: if (MEM_P (operands[1])
1.1 mrg 6468: && !memory_address_p (GET_MODE (operands[1]),
6469: XEXP (operands[1], 0)))
6470: operands[1]
6471: = replace_equiv_address (operands[1],
6472: copy_to_reg (XEXP (operands[1], 0)));
6473: }
6474:
1.3 mrg 6475: if (MEM_P (operands[1]) && optimize > 0)
1.1 mrg 6476: {
6477: rtx reg = gen_reg_rtx (SImode);
6478:
6479: emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6480: operands[1] = gen_lowpart (QImode, reg);
6481: }
6482:
1.3 mrg 6483: if (MEM_P (operands[0]))
1.1 mrg 6484: operands[1] = force_reg (QImode, operands[1]);
6485: }
6486: else if (TARGET_THUMB
1.3 mrg 6487: && CONST_INT_P (operands[1])
1.1 mrg 6488: && !satisfies_constraint_I (operands[1]))
6489: {
6490: /* Handle loading a large integer during reload. */
6491:
6492: /* Writing a constant to memory needs a scratch, which should
6493: be handled with SECONDARY_RELOADs. */
1.3 mrg 6494: gcc_assert (REG_P (operands[0]));
1.1 mrg 6495:
6496: operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6497: emit_insn (gen_movsi (operands[0], operands[1]));
6498: DONE;
6499: }
6500: "
6501: )
6502:
6503: (define_insn "*arm_movqi_insn"
1.5 mrg 6504: [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,l,r,l,Uu,r,m")
6505: (match_operand:QI 1 "general_operand" "rk,rk,I,Py,K,Uu,l,Uh,r"))]
1.1 mrg 6506: "TARGET_32BIT
6507: && ( register_operand (operands[0], QImode)
6508: || register_operand (operands[1], QImode))"
6509: "@
6510: mov%?\\t%0, %1
1.3 mrg 6511: mov%?\\t%0, %1
1.5 mrg 6512: mov%?\\t%0, %1
6513: mov%?\\t%0, %1
1.1 mrg 6514: mvn%?\\t%0, #%B1
1.7 ! mrg 6515: ldrb%?\\t%0, %1
! 6516: strb%?\\t%1, %0
! 6517: ldrb%?\\t%0, %1
! 6518: strb%?\\t%1, %0"
1.5 mrg 6519: [(set_attr "type" "mov_reg,mov_reg,mov_imm,mov_imm,mvn_imm,load1,store1,load1,store1")
1.3 mrg 6520: (set_attr "predicable" "yes")
1.5 mrg 6521: (set_attr "predicable_short_it" "yes,yes,yes,no,no,no,no,no,no")
6522: (set_attr "arch" "t2,any,any,t2,any,t2,t2,any,any")
6523: (set_attr "length" "2,4,4,2,4,2,2,4,4")]
1.1 mrg 6524: )
6525:
6526: ;; HFmode moves
6527: (define_expand "movhf"
6528: [(set (match_operand:HF 0 "general_operand" "")
6529: (match_operand:HF 1 "general_operand" ""))]
6530: "TARGET_EITHER"
6531: "
6532: if (TARGET_32BIT)
6533: {
1.3 mrg 6534: if (MEM_P (operands[0]))
1.1 mrg 6535: operands[1] = force_reg (HFmode, operands[1]);
6536: }
6537: else /* TARGET_THUMB1 */
6538: {
6539: if (can_create_pseudo_p ())
6540: {
1.3 mrg 6541: if (!REG_P (operands[0]))
1.1 mrg 6542: operands[1] = force_reg (HFmode, operands[1]);
6543: }
6544: }
6545: "
6546: )
6547:
6548: (define_insn "*arm32_movhf"
6549: [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6550: (match_operand:HF 1 "general_operand" " m,r,r,F"))]
6551: "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
6552: && ( s_register_operand (operands[0], HFmode)
6553: || s_register_operand (operands[1], HFmode))"
6554: "*
6555: switch (which_alternative)
6556: {
6557: case 0: /* ARM register from memory */
1.7 ! mrg 6558: return \"ldrh%?\\t%0, %1\\t%@ __fp16\";
1.1 mrg 6559: case 1: /* memory from ARM register */
1.7 ! mrg 6560: return \"strh%?\\t%1, %0\\t%@ __fp16\";
1.1 mrg 6561: case 2: /* ARM register from ARM register */
6562: return \"mov%?\\t%0, %1\\t%@ __fp16\";
6563: case 3: /* ARM register from constant */
6564: {
6565: long bits;
6566: rtx ops[4];
6567:
1.7 ! mrg 6568: bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]),
! 6569: HFmode);
1.1 mrg 6570: ops[0] = operands[0];
6571: ops[1] = GEN_INT (bits);
6572: ops[2] = GEN_INT (bits & 0xff00);
6573: ops[3] = GEN_INT (bits & 0x00ff);
6574:
6575: if (arm_arch_thumb2)
6576: output_asm_insn (\"movw%?\\t%0, %1\", ops);
6577: else
6578: output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6579: return \"\";
6580: }
6581: default:
6582: gcc_unreachable ();
6583: }
6584: "
6585: [(set_attr "conds" "unconditional")
1.5 mrg 6586: (set_attr "type" "load1,store1,mov_reg,multiple")
1.1 mrg 6587: (set_attr "length" "4,4,4,8")
1.5 mrg 6588: (set_attr "predicable" "yes")
6589: (set_attr "predicable_short_it" "no")]
1.1 mrg 6590: )
6591:
6592: (define_expand "movsf"
6593: [(set (match_operand:SF 0 "general_operand" "")
6594: (match_operand:SF 1 "general_operand" ""))]
6595: "TARGET_EITHER"
6596: "
6597: if (TARGET_32BIT)
6598: {
1.3 mrg 6599: if (MEM_P (operands[0]))
1.1 mrg 6600: operands[1] = force_reg (SFmode, operands[1]);
6601: }
6602: else /* TARGET_THUMB1 */
6603: {
6604: if (can_create_pseudo_p ())
6605: {
1.3 mrg 6606: if (!REG_P (operands[0]))
1.1 mrg 6607: operands[1] = force_reg (SFmode, operands[1]);
6608: }
6609: }
6610: "
6611: )
6612:
6613: ;; Transform a floating-point move of a constant into a core register into
6614: ;; an SImode operation.
6615: (define_split
6616: [(set (match_operand:SF 0 "arm_general_register_operand" "")
6617: (match_operand:SF 1 "immediate_operand" ""))]
6618: "TARGET_EITHER
6619: && reload_completed
1.3 mrg 6620: && CONST_DOUBLE_P (operands[1])"
1.1 mrg 6621: [(set (match_dup 2) (match_dup 3))]
6622: "
6623: operands[2] = gen_lowpart (SImode, operands[0]);
6624: operands[3] = gen_lowpart (SImode, operands[1]);
6625: if (operands[2] == 0 || operands[3] == 0)
6626: FAIL;
6627: "
6628: )
6629:
6630: (define_insn "*arm_movsf_soft_insn"
6631: [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6632: (match_operand:SF 1 "general_operand" "r,mE,r"))]
1.3 mrg 6633: "TARGET_32BIT
1.1 mrg 6634: && TARGET_SOFT_FLOAT
1.3 mrg 6635: && (!MEM_P (operands[0])
1.1 mrg 6636: || register_operand (operands[1], SFmode))"
6637: "@
6638: mov%?\\t%0, %1
6639: ldr%?\\t%0, %1\\t%@ float
6640: str%?\\t%1, %0\\t%@ float"
1.3 mrg 6641: [(set_attr "predicable" "yes")
1.5 mrg 6642: (set_attr "predicable_short_it" "no")
6643: (set_attr "type" "mov_reg,load1,store1")
1.3 mrg 6644: (set_attr "arm_pool_range" "*,4096,*")
6645: (set_attr "thumb2_pool_range" "*,4094,*")
6646: (set_attr "arm_neg_pool_range" "*,4084,*")
6647: (set_attr "thumb2_neg_pool_range" "*,0,*")]
1.1 mrg 6648: )
6649:
6650: (define_expand "movdf"
6651: [(set (match_operand:DF 0 "general_operand" "")
6652: (match_operand:DF 1 "general_operand" ""))]
6653: "TARGET_EITHER"
6654: "
6655: if (TARGET_32BIT)
6656: {
1.3 mrg 6657: if (MEM_P (operands[0]))
1.1 mrg 6658: operands[1] = force_reg (DFmode, operands[1]);
6659: }
6660: else /* TARGET_THUMB */
6661: {
6662: if (can_create_pseudo_p ())
6663: {
1.3 mrg 6664: if (!REG_P (operands[0]))
1.1 mrg 6665: operands[1] = force_reg (DFmode, operands[1]);
6666: }
6667: }
6668: "
6669: )
6670:
6671: ;; Reloading a df mode value stored in integer regs to memory can require a
6672: ;; scratch reg.
6673: (define_expand "reload_outdf"
6674: [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6675: (match_operand:DF 1 "s_register_operand" "r")
6676: (match_operand:SI 2 "s_register_operand" "=&r")]
1.3 mrg 6677: "TARGET_THUMB2"
1.1 mrg 6678: "
6679: {
6680: enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6681:
6682: if (code == REG)
6683: operands[2] = XEXP (operands[0], 0);
6684: else if (code == POST_INC || code == PRE_DEC)
6685: {
6686: operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6687: operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6688: emit_insn (gen_movdi (operands[0], operands[1]));
6689: DONE;
6690: }
6691: else if (code == PRE_INC)
6692: {
6693: rtx reg = XEXP (XEXP (operands[0], 0), 0);
6694:
6695: emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6696: operands[2] = reg;
6697: }
6698: else if (code == POST_DEC)
6699: operands[2] = XEXP (XEXP (operands[0], 0), 0);
6700: else
6701: emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6702: XEXP (XEXP (operands[0], 0), 1)));
6703:
1.7 ! mrg 6704: emit_insn (gen_rtx_SET (replace_equiv_address (operands[0], operands[2]),
1.1 mrg 6705: operands[1]));
6706:
6707: if (code == POST_DEC)
6708: emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6709:
6710: DONE;
6711: }"
6712: )
6713:
6714: (define_insn "*movdf_soft_insn"
1.5 mrg 6715: [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,q,m")
6716: (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,q"))]
1.3 mrg 6717: "TARGET_32BIT && TARGET_SOFT_FLOAT
1.1 mrg 6718: && ( register_operand (operands[0], DFmode)
6719: || register_operand (operands[1], DFmode))"
6720: "*
6721: switch (which_alternative)
6722: {
6723: case 0:
6724: case 1:
6725: case 2:
6726: return \"#\";
6727: default:
1.3 mrg 6728: return output_move_double (operands, true, NULL);
1.1 mrg 6729: }
6730: "
6731: [(set_attr "length" "8,12,16,8,8")
1.5 mrg 6732: (set_attr "type" "multiple,multiple,multiple,load2,store2")
1.3 mrg 6733: (set_attr "arm_pool_range" "*,*,*,1020,*")
6734: (set_attr "thumb2_pool_range" "*,*,*,1018,*")
6735: (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
6736: (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
1.1 mrg 6737: )
1.3 mrg 6738:
1.1 mrg 6739:
6740: ;; load- and store-multiple insns
6741: ;; The arm can load/store any set of registers, provided that they are in
1.3 mrg 6742: ;; ascending order, but these expanders assume a contiguous set.
1.1 mrg 6743:
6744: (define_expand "load_multiple"
6745: [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6746: (match_operand:SI 1 "" ""))
6747: (use (match_operand:SI 2 "" ""))])]
6748: "TARGET_32BIT"
6749: {
6750: HOST_WIDE_INT offset = 0;
6751:
6752: /* Support only fixed point registers. */
1.3 mrg 6753: if (!CONST_INT_P (operands[2])
1.7 ! mrg 6754: || INTVAL (operands[2]) > MAX_LDM_STM_OPS
1.1 mrg 6755: || INTVAL (operands[2]) < 2
1.3 mrg 6756: || !MEM_P (operands[1])
6757: || !REG_P (operands[0])
1.1 mrg 6758: || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6759: || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6760: FAIL;
6761:
6762: operands[3]
1.3 mrg 6763: = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6764: INTVAL (operands[2]),
1.1 mrg 6765: force_reg (SImode, XEXP (operands[1], 0)),
1.3 mrg 6766: FALSE, operands[1], &offset);
1.1 mrg 6767: })
6768:
6769: (define_expand "store_multiple"
6770: [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6771: (match_operand:SI 1 "" ""))
6772: (use (match_operand:SI 2 "" ""))])]
6773: "TARGET_32BIT"
6774: {
6775: HOST_WIDE_INT offset = 0;
6776:
6777: /* Support only fixed point registers. */
1.3 mrg 6778: if (!CONST_INT_P (operands[2])
1.7 ! mrg 6779: || INTVAL (operands[2]) > MAX_LDM_STM_OPS
1.1 mrg 6780: || INTVAL (operands[2]) < 2
1.3 mrg 6781: || !REG_P (operands[1])
6782: || !MEM_P (operands[0])
1.1 mrg 6783: || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6784: || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6785: FAIL;
6786:
6787: operands[3]
1.3 mrg 6788: = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6789: INTVAL (operands[2]),
1.1 mrg 6790: force_reg (SImode, XEXP (operands[0], 0)),
1.3 mrg 6791: FALSE, operands[0], &offset);
1.1 mrg 6792: })
6793:
6794:
1.5 mrg 6795: (define_expand "setmemsi"
6796: [(match_operand:BLK 0 "general_operand" "")
6797: (match_operand:SI 1 "const_int_operand" "")
6798: (match_operand:SI 2 "const_int_operand" "")
6799: (match_operand:SI 3 "const_int_operand" "")]
6800: "TARGET_32BIT"
6801: {
6802: if (arm_gen_setmem (operands))
6803: DONE;
6804:
6805: FAIL;
6806: })
6807:
6808:
1.1 mrg 6809: ;; Move a block of memory if it is word aligned and MORE than 2 words long.
6810: ;; We could let this apply for blocks of less than this, but it clobbers so
6811: ;; many registers that there is then probably a better way.
6812:
6813: (define_expand "movmemqi"
6814: [(match_operand:BLK 0 "general_operand" "")
6815: (match_operand:BLK 1 "general_operand" "")
6816: (match_operand:SI 2 "const_int_operand" "")
6817: (match_operand:SI 3 "const_int_operand" "")]
1.5 mrg 6818: ""
1.1 mrg 6819: "
6820: if (TARGET_32BIT)
6821: {
1.5 mrg 6822: if (TARGET_LDRD && current_tune->prefer_ldrd_strd
6823: && !optimize_function_for_size_p (cfun))
6824: {
6825: if (gen_movmem_ldrd_strd (operands))
6826: DONE;
6827: FAIL;
6828: }
6829:
1.1 mrg 6830: if (arm_gen_movmemqi (operands))
6831: DONE;
6832: FAIL;
6833: }
6834: else /* TARGET_THUMB1 */
6835: {
6836: if ( INTVAL (operands[3]) != 4
6837: || INTVAL (operands[2]) > 48)
6838: FAIL;
6839:
6840: thumb_expand_movmemqi (operands);
6841: DONE;
6842: }
6843: "
6844: )
6845:
6846:
6847: ;; Compare & branch insns
6848: ;; The range calculations are based as follows:
6849: ;; For forward branches, the address calculation returns the address of
6850: ;; the next instruction. This is 2 beyond the branch instruction.
6851: ;; For backward branches, the address calculation returns the address of
6852: ;; the first instruction in this pattern (cmp). This is 2 before the branch
6853: ;; instruction for the shortest sequence, and 4 before the branch instruction
6854: ;; if we have to jump around an unconditional branch.
6855: ;; To the basic branch range the PC offset must be added (this is +4).
6856: ;; So for forward branches we have
6857: ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6858: ;; And for backward branches we have
6859: ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6860: ;;
6861: ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6862: ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
6863:
6864: (define_expand "cbranchsi4"
6865: [(set (pc) (if_then_else
1.3 mrg 6866: (match_operator 0 "expandable_comparison_operator"
1.1 mrg 6867: [(match_operand:SI 1 "s_register_operand" "")
6868: (match_operand:SI 2 "nonmemory_operand" "")])
6869: (label_ref (match_operand 3 "" ""))
6870: (pc)))]
1.3 mrg 6871: "TARGET_EITHER"
1.1 mrg 6872: "
6873: if (!TARGET_THUMB1)
6874: {
1.3 mrg 6875: if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6876: FAIL;
1.1 mrg 6877: emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6878: operands[3]));
6879: DONE;
6880: }
6881: if (thumb1_cmpneg_operand (operands[2], SImode))
6882: {
6883: emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6884: operands[3], operands[0]));
6885: DONE;
6886: }
6887: if (!thumb1_cmp_operand (operands[2], SImode))
6888: operands[2] = force_reg (SImode, operands[2]);
6889: ")
6890:
6891: (define_expand "cbranchsf4"
6892: [(set (pc) (if_then_else
1.3 mrg 6893: (match_operator 0 "expandable_comparison_operator"
1.1 mrg 6894: [(match_operand:SF 1 "s_register_operand" "")
6895: (match_operand:SF 2 "arm_float_compare_operand" "")])
6896: (label_ref (match_operand 3 "" ""))
6897: (pc)))]
6898: "TARGET_32BIT && TARGET_HARD_FLOAT"
6899: "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6900: operands[3])); DONE;"
6901: )
6902:
6903: (define_expand "cbranchdf4"
6904: [(set (pc) (if_then_else
1.3 mrg 6905: (match_operator 0 "expandable_comparison_operator"
1.1 mrg 6906: [(match_operand:DF 1 "s_register_operand" "")
6907: (match_operand:DF 2 "arm_float_compare_operand" "")])
6908: (label_ref (match_operand 3 "" ""))
6909: (pc)))]
6910: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6911: "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6912: operands[3])); DONE;"
6913: )
6914:
6915: (define_expand "cbranchdi4"
6916: [(set (pc) (if_then_else
1.3 mrg 6917: (match_operator 0 "expandable_comparison_operator"
6918: [(match_operand:DI 1 "s_register_operand" "")
6919: (match_operand:DI 2 "cmpdi_operand" "")])
1.1 mrg 6920: (label_ref (match_operand 3 "" ""))
6921: (pc)))]
1.3 mrg 6922: "TARGET_32BIT"
6923: "{
6924: if (!arm_validize_comparison (&operands[0], &operands[1], &operands[2]))
6925: FAIL;
6926: emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6927: operands[3]));
6928: DONE;
6929: }"
1.1 mrg 6930: )
6931:
6932: ;; Comparison and test insns
6933:
6934: (define_insn "*arm_cmpsi_insn"
6935: [(set (reg:CC CC_REGNUM)
1.5 mrg 6936: (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r,r")
6937: (match_operand:SI 1 "arm_add_operand" "Py,r,r,I,L")))]
1.1 mrg 6938: "TARGET_32BIT"
6939: "@
6940: cmp%?\\t%0, %1
1.3 mrg 6941: cmp%?\\t%0, %1
6942: cmp%?\\t%0, %1
1.5 mrg 6943: cmp%?\\t%0, %1
1.1 mrg 6944: cmn%?\\t%0, #%n1"
1.3 mrg 6945: [(set_attr "conds" "set")
1.5 mrg 6946: (set_attr "arch" "t2,t2,any,any,any")
6947: (set_attr "length" "2,2,4,4,4")
1.3 mrg 6948: (set_attr "predicable" "yes")
1.5 mrg 6949: (set_attr "predicable_short_it" "yes,yes,yes,no,no")
6950: (set_attr "type" "alus_imm,alus_sreg,alus_sreg,alus_imm,alus_imm")]
1.1 mrg 6951: )
6952:
1.3 mrg 6953: (define_insn "*cmpsi_shiftsi"
1.1 mrg 6954: [(set (reg:CC CC_REGNUM)
1.5 mrg 6955: (compare:CC (match_operand:SI 0 "s_register_operand" "r,r,r")
1.1 mrg 6956: (match_operator:SI 3 "shift_operator"
1.5 mrg 6957: [(match_operand:SI 1 "s_register_operand" "r,r,r")
6958: (match_operand:SI 2 "shift_amount_operand" "M,r,M")])))]
1.3 mrg 6959: "TARGET_32BIT"
1.5 mrg 6960: "cmp\\t%0, %1%S3"
1.1 mrg 6961: [(set_attr "conds" "set")
6962: (set_attr "shift" "1")
1.5 mrg 6963: (set_attr "arch" "32,a,a")
1.7 ! mrg 6964: (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
1.1 mrg 6965:
1.3 mrg 6966: (define_insn "*cmpsi_shiftsi_swp"
1.1 mrg 6967: [(set (reg:CC_SWP CC_REGNUM)
6968: (compare:CC_SWP (match_operator:SI 3 "shift_operator"
1.5 mrg 6969: [(match_operand:SI 1 "s_register_operand" "r,r,r")
6970: (match_operand:SI 2 "shift_amount_operand" "M,r,M")])
6971: (match_operand:SI 0 "s_register_operand" "r,r,r")))]
1.3 mrg 6972: "TARGET_32BIT"
1.1 mrg 6973: "cmp%?\\t%0, %1%S3"
6974: [(set_attr "conds" "set")
6975: (set_attr "shift" "1")
1.5 mrg 6976: (set_attr "arch" "32,a,a")
1.7 ! mrg 6977: (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
1.1 mrg 6978:
6979: (define_insn "*arm_cmpsi_negshiftsi_si"
6980: [(set (reg:CC_Z CC_REGNUM)
6981: (compare:CC_Z
6982: (neg:SI (match_operator:SI 1 "shift_operator"
6983: [(match_operand:SI 2 "s_register_operand" "r")
6984: (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6985: (match_operand:SI 0 "s_register_operand" "r")))]
6986: "TARGET_ARM"
6987: "cmn%?\\t%0, %2%S1"
6988: [(set_attr "conds" "set")
6989: (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
1.5 mrg 6990: (const_string "alus_shift_imm")
6991: (const_string "alus_shift_reg")))
1.3 mrg 6992: (set_attr "predicable" "yes")]
6993: )
6994:
6995: ;; DImode comparisons. The generic code generates branches that
6996: ;; if-conversion can not reduce to a conditional compare, so we do
6997: ;; that directly.
6998:
1.5 mrg 6999: (define_insn_and_split "*arm_cmpdi_insn"
1.3 mrg 7000: [(set (reg:CC_NCV CC_REGNUM)
7001: (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7002: (match_operand:DI 1 "arm_di_operand" "rDi")))
7003: (clobber (match_scratch:SI 2 "=r"))]
7004: "TARGET_32BIT"
1.5 mrg 7005: "#" ; "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7006: "&& reload_completed"
7007: [(set (reg:CC CC_REGNUM)
7008: (compare:CC (match_dup 0) (match_dup 1)))
7009: (parallel [(set (reg:CC CC_REGNUM)
7010: (compare:CC (match_dup 3) (match_dup 4)))
7011: (set (match_dup 2)
7012: (minus:SI (match_dup 5)
7013: (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))])]
7014: {
7015: operands[3] = gen_highpart (SImode, operands[0]);
7016: operands[0] = gen_lowpart (SImode, operands[0]);
7017: if (CONST_INT_P (operands[1]))
7018: {
7019: operands[4] = GEN_INT (~INTVAL (gen_highpart_mode (SImode,
7020: DImode,
7021: operands[1])));
7022: operands[5] = gen_rtx_PLUS (SImode, operands[3], operands[4]);
7023: }
7024: else
7025: {
7026: operands[4] = gen_highpart (SImode, operands[1]);
7027: operands[5] = gen_rtx_MINUS (SImode, operands[3], operands[4]);
7028: }
7029: operands[1] = gen_lowpart (SImode, operands[1]);
7030: operands[2] = gen_lowpart (SImode, operands[2]);
7031: }
1.3 mrg 7032: [(set_attr "conds" "set")
1.5 mrg 7033: (set_attr "length" "8")
7034: (set_attr "type" "multiple")]
1.3 mrg 7035: )
7036:
1.5 mrg 7037: (define_insn_and_split "*arm_cmpdi_unsigned"
1.3 mrg 7038: [(set (reg:CC_CZ CC_REGNUM)
1.5 mrg 7039: (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "l,r,r,r")
7040: (match_operand:DI 1 "arm_di_operand" "Py,r,Di,rDi")))]
7041:
1.3 mrg 7042: "TARGET_32BIT"
1.5 mrg 7043: "#" ; "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7044: "&& reload_completed"
7045: [(set (reg:CC CC_REGNUM)
7046: (compare:CC (match_dup 2) (match_dup 3)))
7047: (cond_exec (eq:SI (reg:CC CC_REGNUM) (const_int 0))
7048: (set (reg:CC CC_REGNUM)
7049: (compare:CC (match_dup 0) (match_dup 1))))]
7050: {
7051: operands[2] = gen_highpart (SImode, operands[0]);
7052: operands[0] = gen_lowpart (SImode, operands[0]);
7053: if (CONST_INT_P (operands[1]))
7054: operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
7055: else
7056: operands[3] = gen_highpart (SImode, operands[1]);
7057: operands[1] = gen_lowpart (SImode, operands[1]);
7058: }
1.3 mrg 7059: [(set_attr "conds" "set")
1.5 mrg 7060: (set_attr "enabled_for_depr_it" "yes,yes,no,*")
7061: (set_attr "arch" "t2,t2,t2,a")
7062: (set_attr "length" "6,6,10,8")
7063: (set_attr "type" "multiple")]
1.1 mrg 7064: )
7065:
1.3 mrg 7066: (define_insn "*arm_cmpdi_zero"
7067: [(set (reg:CC_Z CC_REGNUM)
7068: (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7069: (const_int 0)))
7070: (clobber (match_scratch:SI 1 "=r"))]
7071: "TARGET_32BIT"
1.7 ! mrg 7072: "orrs%?\\t%1, %Q0, %R0"
1.3 mrg 7073: [(set_attr "conds" "set")
1.5 mrg 7074: (set_attr "type" "logics_reg")]
1.1 mrg 7075: )
7076:
7077: ; This insn allows redundant compares to be removed by cse, nothing should
7078: ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7079: ; is deleted later on. The match_dup will match the mode here, so that
7080: ; mode changes of the condition codes aren't lost by this even though we don't
7081: ; specify what they are.
7082:
7083: (define_insn "*deleted_compare"
7084: [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7085: "TARGET_32BIT"
7086: "\\t%@ deleted compare"
7087: [(set_attr "conds" "set")
1.5 mrg 7088: (set_attr "length" "0")
7089: (set_attr "type" "no_insn")]
1.1 mrg 7090: )
7091:
7092:
7093: ;; Conditional branch insns
7094:
7095: (define_expand "cbranch_cc"
7096: [(set (pc)
7097: (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7098: (match_operand 2 "" "")])
7099: (label_ref (match_operand 3 "" ""))
7100: (pc)))]
7101: "TARGET_32BIT"
7102: "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
1.3 mrg 7103: operands[1], operands[2], NULL_RTX);
1.1 mrg 7104: operands[2] = const0_rtx;"
7105: )
7106:
7107: ;;
7108: ;; Patterns to match conditional branch insns.
7109: ;;
7110:
1.3 mrg 7111: (define_insn "arm_cond_branch"
1.1 mrg 7112: [(set (pc)
7113: (if_then_else (match_operator 1 "arm_comparison_operator"
7114: [(match_operand 2 "cc_register" "") (const_int 0)])
7115: (label_ref (match_operand 0 "" ""))
7116: (pc)))]
7117: "TARGET_32BIT"
7118: "*
7119: if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7120: {
7121: arm_ccfsm_state += 2;
7122: return \"\";
7123: }
7124: return \"b%d1\\t%l0\";
7125: "
7126: [(set_attr "conds" "use")
1.3 mrg 7127: (set_attr "type" "branch")
7128: (set (attr "length")
7129: (if_then_else
7130: (and (match_test "TARGET_THUMB2")
7131: (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7132: (le (minus (match_dup 0) (pc)) (const_int 256))))
7133: (const_int 2)
7134: (const_int 4)))]
1.1 mrg 7135: )
7136:
7137: (define_insn "*arm_cond_branch_reversed"
7138: [(set (pc)
7139: (if_then_else (match_operator 1 "arm_comparison_operator"
7140: [(match_operand 2 "cc_register" "") (const_int 0)])
7141: (pc)
7142: (label_ref (match_operand 0 "" ""))))]
7143: "TARGET_32BIT"
7144: "*
7145: if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7146: {
7147: arm_ccfsm_state += 2;
7148: return \"\";
7149: }
7150: return \"b%D1\\t%l0\";
7151: "
7152: [(set_attr "conds" "use")
1.3 mrg 7153: (set_attr "type" "branch")
7154: (set (attr "length")
7155: (if_then_else
7156: (and (match_test "TARGET_THUMB2")
7157: (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7158: (le (minus (match_dup 0) (pc)) (const_int 256))))
7159: (const_int 2)
7160: (const_int 4)))]
1.1 mrg 7161: )
7162:
7163:
7164:
7165: ; scc insns
7166:
7167: (define_expand "cstore_cc"
7168: [(set (match_operand:SI 0 "s_register_operand" "")
7169: (match_operator:SI 1 "" [(match_operand 2 "" "")
7170: (match_operand 3 "" "")]))]
7171: "TARGET_32BIT"
7172: "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
1.3 mrg 7173: operands[2], operands[3], NULL_RTX);
1.1 mrg 7174: operands[3] = const0_rtx;"
7175: )
7176:
1.5 mrg 7177: (define_insn_and_split "*mov_scc"
1.1 mrg 7178: [(set (match_operand:SI 0 "s_register_operand" "=r")
1.7 ! mrg 7179: (match_operator:SI 1 "arm_comparison_operator_mode"
1.1 mrg 7180: [(match_operand 2 "cc_register" "") (const_int 0)]))]
7181: "TARGET_ARM"
1.5 mrg 7182: "#" ; "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7183: "TARGET_ARM"
7184: [(set (match_dup 0)
7185: (if_then_else:SI (match_dup 1)
7186: (const_int 1)
7187: (const_int 0)))]
7188: ""
1.1 mrg 7189: [(set_attr "conds" "use")
1.5 mrg 7190: (set_attr "length" "8")
7191: (set_attr "type" "multiple")]
1.1 mrg 7192: )
7193:
1.5 mrg 7194: (define_insn_and_split "*mov_negscc"
1.1 mrg 7195: [(set (match_operand:SI 0 "s_register_operand" "=r")
1.7 ! mrg 7196: (neg:SI (match_operator:SI 1 "arm_comparison_operator_mode"
1.1 mrg 7197: [(match_operand 2 "cc_register" "") (const_int 0)])))]
7198: "TARGET_ARM"
1.5 mrg 7199: "#" ; "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7200: "TARGET_ARM"
7201: [(set (match_dup 0)
7202: (if_then_else:SI (match_dup 1)
7203: (match_dup 3)
7204: (const_int 0)))]
7205: {
7206: operands[3] = GEN_INT (~0);
7207: }
1.1 mrg 7208: [(set_attr "conds" "use")
1.5 mrg 7209: (set_attr "length" "8")
7210: (set_attr "type" "multiple")]
1.1 mrg 7211: )
7212:
1.5 mrg 7213: (define_insn_and_split "*mov_notscc"
1.1 mrg 7214: [(set (match_operand:SI 0 "s_register_operand" "=r")
7215: (not:SI (match_operator:SI 1 "arm_comparison_operator"
7216: [(match_operand 2 "cc_register" "") (const_int 0)])))]
7217: "TARGET_ARM"
1.5 mrg 7218: "#" ; "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7219: "TARGET_ARM"
7220: [(set (match_dup 0)
7221: (if_then_else:SI (match_dup 1)
7222: (match_dup 3)
7223: (match_dup 4)))]
7224: {
7225: operands[3] = GEN_INT (~1);
7226: operands[4] = GEN_INT (~0);
7227: }
1.1 mrg 7228: [(set_attr "conds" "use")
1.5 mrg 7229: (set_attr "length" "8")
7230: (set_attr "type" "multiple")]
1.1 mrg 7231: )
7232:
7233: (define_expand "cstoresi4"
7234: [(set (match_operand:SI 0 "s_register_operand" "")
1.3 mrg 7235: (match_operator:SI 1 "expandable_comparison_operator"
1.1 mrg 7236: [(match_operand:SI 2 "s_register_operand" "")
7237: (match_operand:SI 3 "reg_or_int_operand" "")]))]
7238: "TARGET_32BIT || TARGET_THUMB1"
7239: "{
7240: rtx op3, scratch, scratch2;
7241:
7242: if (!TARGET_THUMB1)
7243: {
7244: if (!arm_add_operand (operands[3], SImode))
7245: operands[3] = force_reg (SImode, operands[3]);
7246: emit_insn (gen_cstore_cc (operands[0], operands[1],
7247: operands[2], operands[3]));
7248: DONE;
7249: }
7250:
7251: if (operands[3] == const0_rtx)
7252: {
7253: switch (GET_CODE (operands[1]))
7254: {
7255: case EQ:
7256: emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7257: break;
7258:
7259: case NE:
7260: emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7261: break;
7262:
7263: case LE:
7264: scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7265: NULL_RTX, 0, OPTAB_WIDEN);
7266: scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7267: NULL_RTX, 0, OPTAB_WIDEN);
7268: expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7269: operands[0], 1, OPTAB_WIDEN);
7270: break;
7271:
7272: case GE:
7273: scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7274: NULL_RTX, 1);
7275: expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7276: NULL_RTX, 1, OPTAB_WIDEN);
7277: break;
7278:
7279: case GT:
7280: scratch = expand_binop (SImode, ashr_optab, operands[2],
7281: GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7282: scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7283: NULL_RTX, 0, OPTAB_WIDEN);
7284: expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7285: 0, OPTAB_WIDEN);
7286: break;
7287:
7288: /* LT is handled by generic code. No need for unsigned with 0. */
7289: default:
7290: FAIL;
7291: }
7292: DONE;
7293: }
7294:
7295: switch (GET_CODE (operands[1]))
7296: {
7297: case EQ:
7298: scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7299: NULL_RTX, 0, OPTAB_WIDEN);
7300: emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7301: break;
7302:
7303: case NE:
7304: scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7305: NULL_RTX, 0, OPTAB_WIDEN);
7306: emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7307: break;
7308:
7309: case LE:
7310: op3 = force_reg (SImode, operands[3]);
7311:
7312: scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7313: NULL_RTX, 1, OPTAB_WIDEN);
7314: scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7315: NULL_RTX, 0, OPTAB_WIDEN);
7316: emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7317: op3, operands[2]));
7318: break;
7319:
7320: case GE:
7321: op3 = operands[3];
7322: if (!thumb1_cmp_operand (op3, SImode))
7323: op3 = force_reg (SImode, op3);
7324: scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7325: NULL_RTX, 0, OPTAB_WIDEN);
7326: scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7327: NULL_RTX, 1, OPTAB_WIDEN);
7328: emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7329: operands[2], op3));
7330: break;
7331:
7332: case LEU:
7333: op3 = force_reg (SImode, operands[3]);
7334: scratch = force_reg (SImode, const0_rtx);
7335: emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7336: op3, operands[2]));
7337: break;
7338:
7339: case GEU:
7340: op3 = operands[3];
7341: if (!thumb1_cmp_operand (op3, SImode))
7342: op3 = force_reg (SImode, op3);
7343: scratch = force_reg (SImode, const0_rtx);
7344: emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7345: operands[2], op3));
7346: break;
7347:
7348: case LTU:
7349: op3 = operands[3];
7350: if (!thumb1_cmp_operand (op3, SImode))
7351: op3 = force_reg (SImode, op3);
7352: scratch = gen_reg_rtx (SImode);
7353: emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7354: break;
7355:
7356: case GTU:
7357: op3 = force_reg (SImode, operands[3]);
7358: scratch = gen_reg_rtx (SImode);
7359: emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7360: break;
7361:
7362: /* No good sequences for GT, LT. */
7363: default:
7364: FAIL;
7365: }
7366: DONE;
7367: }")
7368:
7369: (define_expand "cstoresf4"
7370: [(set (match_operand:SI 0 "s_register_operand" "")
1.3 mrg 7371: (match_operator:SI 1 "expandable_comparison_operator"
1.1 mrg 7372: [(match_operand:SF 2 "s_register_operand" "")
7373: (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7374: "TARGET_32BIT && TARGET_HARD_FLOAT"
7375: "emit_insn (gen_cstore_cc (operands[0], operands[1],
7376: operands[2], operands[3])); DONE;"
7377: )
7378:
7379: (define_expand "cstoredf4"
7380: [(set (match_operand:SI 0 "s_register_operand" "")
1.3 mrg 7381: (match_operator:SI 1 "expandable_comparison_operator"
1.1 mrg 7382: [(match_operand:DF 2 "s_register_operand" "")
7383: (match_operand:DF 3 "arm_float_compare_operand" "")]))]
1.3 mrg 7384: "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1.1 mrg 7385: "emit_insn (gen_cstore_cc (operands[0], operands[1],
7386: operands[2], operands[3])); DONE;"
7387: )
7388:
7389: (define_expand "cstoredi4"
7390: [(set (match_operand:SI 0 "s_register_operand" "")
1.3 mrg 7391: (match_operator:SI 1 "expandable_comparison_operator"
7392: [(match_operand:DI 2 "s_register_operand" "")
7393: (match_operand:DI 3 "cmpdi_operand" "")]))]
7394: "TARGET_32BIT"
7395: "{
7396: if (!arm_validize_comparison (&operands[1],
7397: &operands[2],
7398: &operands[3]))
7399: FAIL;
7400: emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7401: operands[3]));
7402: DONE;
7403: }"
1.1 mrg 7404: )
7405:
7406:
7407: ;; Conditional move insns
7408:
7409: (define_expand "movsicc"
7410: [(set (match_operand:SI 0 "s_register_operand" "")
1.3 mrg 7411: (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
1.1 mrg 7412: (match_operand:SI 2 "arm_not_operand" "")
7413: (match_operand:SI 3 "arm_not_operand" "")))]
7414: "TARGET_32BIT"
7415: "
7416: {
1.3 mrg 7417: enum rtx_code code;
1.1 mrg 7418: rtx ccreg;
7419:
1.3 mrg 7420: if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7421: &XEXP (operands[1], 1)))
1.1 mrg 7422: FAIL;
1.3 mrg 7423:
7424: code = GET_CODE (operands[1]);
1.1 mrg 7425: ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
1.3 mrg 7426: XEXP (operands[1], 1), NULL_RTX);
1.1 mrg 7427: operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7428: }"
7429: )
7430:
7431: (define_expand "movsfcc"
7432: [(set (match_operand:SF 0 "s_register_operand" "")
1.5 mrg 7433: (if_then_else:SF (match_operand 1 "arm_cond_move_operator" "")
1.1 mrg 7434: (match_operand:SF 2 "s_register_operand" "")
1.3 mrg 7435: (match_operand:SF 3 "s_register_operand" "")))]
1.1 mrg 7436: "TARGET_32BIT && TARGET_HARD_FLOAT"
7437: "
7438: {
7439: enum rtx_code code = GET_CODE (operands[1]);
7440: rtx ccreg;
7441:
1.3 mrg 7442: if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7443: &XEXP (operands[1], 1)))
7444: FAIL;
1.1 mrg 7445:
1.3 mrg 7446: code = GET_CODE (operands[1]);
1.1 mrg 7447: ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
1.3 mrg 7448: XEXP (operands[1], 1), NULL_RTX);
1.1 mrg 7449: operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7450: }"
7451: )
7452:
7453: (define_expand "movdfcc"
7454: [(set (match_operand:DF 0 "s_register_operand" "")
1.5 mrg 7455: (if_then_else:DF (match_operand 1 "arm_cond_move_operator" "")
1.1 mrg 7456: (match_operand:DF 2 "s_register_operand" "")
1.3 mrg 7457: (match_operand:DF 3 "s_register_operand" "")))]
7458: "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
1.1 mrg 7459: "
7460: {
7461: enum rtx_code code = GET_CODE (operands[1]);
7462: rtx ccreg;
7463:
1.3 mrg 7464: if (!arm_validize_comparison (&operands[1], &XEXP (operands[1], 0),
7465: &XEXP (operands[1], 1)))
7466: FAIL;
7467: code = GET_CODE (operands[1]);
1.1 mrg 7468: ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
1.3 mrg 7469: XEXP (operands[1], 1), NULL_RTX);
1.1 mrg 7470: operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7471: }"
7472: )
7473:
1.5 mrg 7474: (define_insn "*cmov<mode>"
7475: [(set (match_operand:SDF 0 "s_register_operand" "=<F_constraint>")
7476: (if_then_else:SDF (match_operator 1 "arm_vsel_comparison_operator"
7477: [(match_operand 2 "cc_register" "") (const_int 0)])
7478: (match_operand:SDF 3 "s_register_operand"
7479: "<F_constraint>")
7480: (match_operand:SDF 4 "s_register_operand"
7481: "<F_constraint>")))]
7482: "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>"
7483: "*
7484: {
7485: enum arm_cond_code code = maybe_get_arm_condition_code (operands[1]);
7486: switch (code)
7487: {
7488: case ARM_GE:
7489: case ARM_GT:
7490: case ARM_EQ:
7491: case ARM_VS:
7492: return \"vsel%d1.<V_if_elem>\\t%<V_reg>0, %<V_reg>3, %<V_reg>4\";
7493: case ARM_LT:
7494: case ARM_LE:
7495: case ARM_NE:
7496: case ARM_VC:
7497: return \"vsel%D1.<V_if_elem>\\t%<V_reg>0, %<V_reg>4, %<V_reg>3\";
7498: default:
7499: gcc_unreachable ();
7500: }
7501: return \"\";
7502: }"
7503: [(set_attr "conds" "use")
7504: (set_attr "type" "fcsel")]
7505: )
7506:
7507: (define_insn_and_split "*movsicc_insn"
1.1 mrg 7508: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7509: (if_then_else:SI
7510: (match_operator 3 "arm_comparison_operator"
7511: [(match_operand 4 "cc_register" "") (const_int 0)])
7512: (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7513: (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7514: "TARGET_ARM"
7515: "@
7516: mov%D3\\t%0, %2
7517: mvn%D3\\t%0, #%B2
7518: mov%d3\\t%0, %1
7519: mvn%d3\\t%0, #%B1
1.5 mrg 7520: #
7521: #
7522: #
7523: #"
7524: ; alt4: mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7525: ; alt5: mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7526: ; alt6: mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7527: ; alt7: mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7528: "&& reload_completed"
7529: [(const_int 0)]
7530: {
7531: enum rtx_code rev_code;
7532: machine_mode mode;
7533: rtx rev_cond;
7534:
7535: emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7536: operands[3],
1.7 ! mrg 7537: gen_rtx_SET (operands[0], operands[1])));
1.5 mrg 7538:
7539: rev_code = GET_CODE (operands[3]);
7540: mode = GET_MODE (operands[4]);
7541: if (mode == CCFPmode || mode == CCFPEmode)
7542: rev_code = reverse_condition_maybe_unordered (rev_code);
7543: else
7544: rev_code = reverse_condition (rev_code);
7545:
7546: rev_cond = gen_rtx_fmt_ee (rev_code,
7547: VOIDmode,
7548: operands[4],
7549: const0_rtx);
7550: emit_insn (gen_rtx_COND_EXEC (VOIDmode,
7551: rev_cond,
1.7 ! mrg 7552: gen_rtx_SET (operands[0], operands[2])));
1.5 mrg 7553: DONE;
7554: }
1.1 mrg 7555: [(set_attr "length" "4,4,4,4,8,8,8,8")
1.3 mrg 7556: (set_attr "conds" "use")
7557: (set_attr_alternative "type"
7558: [(if_then_else (match_operand 2 "const_int_operand" "")
1.5 mrg 7559: (const_string "mov_imm")
7560: (const_string "mov_reg"))
7561: (const_string "mvn_imm")
1.3 mrg 7562: (if_then_else (match_operand 1 "const_int_operand" "")
1.5 mrg 7563: (const_string "mov_imm")
7564: (const_string "mov_reg"))
7565: (const_string "mvn_imm")
1.7 ! mrg 7566: (const_string "multiple")
! 7567: (const_string "multiple")
! 7568: (const_string "multiple")
! 7569: (const_string "multiple")])]
1.1 mrg 7570: )
7571:
7572: (define_insn "*movsfcc_soft_insn"
7573: [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7574: (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7575: [(match_operand 4 "cc_register" "") (const_int 0)])
7576: (match_operand:SF 1 "s_register_operand" "0,r")
7577: (match_operand:SF 2 "s_register_operand" "r,0")))]
7578: "TARGET_ARM && TARGET_SOFT_FLOAT"
7579: "@
7580: mov%D3\\t%0, %2
7581: mov%d3\\t%0, %1"
1.3 mrg 7582: [(set_attr "conds" "use")
1.5 mrg 7583: (set_attr "type" "mov_reg")]
1.1 mrg 7584: )
7585:
7586:
7587: ;; Jump and linkage insns
7588:
7589: (define_expand "jump"
7590: [(set (pc)
7591: (label_ref (match_operand 0 "" "")))]
7592: "TARGET_EITHER"
7593: ""
7594: )
7595:
7596: (define_insn "*arm_jump"
7597: [(set (pc)
7598: (label_ref (match_operand 0 "" "")))]
7599: "TARGET_32BIT"
7600: "*
7601: {
7602: if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7603: {
7604: arm_ccfsm_state += 2;
7605: return \"\";
7606: }
7607: return \"b%?\\t%l0\";
7608: }
7609: "
1.3 mrg 7610: [(set_attr "predicable" "yes")
7611: (set (attr "length")
7612: (if_then_else
7613: (and (match_test "TARGET_THUMB2")
7614: (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7615: (le (minus (match_dup 0) (pc)) (const_int 2048))))
7616: (const_int 2)
1.5 mrg 7617: (const_int 4)))
7618: (set_attr "type" "branch")]
1.1 mrg 7619: )
7620:
7621: (define_expand "call"
7622: [(parallel [(call (match_operand 0 "memory_operand" "")
7623: (match_operand 1 "general_operand" ""))
7624: (use (match_operand 2 "" ""))
7625: (clobber (reg:SI LR_REGNUM))])]
7626: "TARGET_EITHER"
7627: "
7628: {
7629: rtx callee, pat;
7630:
7631: /* In an untyped call, we can get NULL for operand 2. */
7632: if (operands[2] == NULL_RTX)
7633: operands[2] = const0_rtx;
7634:
7635: /* Decide if we should generate indirect calls by loading the
7636: 32-bit address of the callee into a register before performing the
7637: branch and link. */
7638: callee = XEXP (operands[0], 0);
7639: if (GET_CODE (callee) == SYMBOL_REF
7640: ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7641: : !REG_P (callee))
7642: XEXP (operands[0], 0) = force_reg (Pmode, callee);
7643:
7644: pat = gen_call_internal (operands[0], operands[1], operands[2]);
1.5 mrg 7645: arm_emit_call_insn (pat, XEXP (operands[0], 0), false);
1.1 mrg 7646: DONE;
7647: }"
7648: )
7649:
7650: (define_expand "call_internal"
7651: [(parallel [(call (match_operand 0 "memory_operand" "")
7652: (match_operand 1 "general_operand" ""))
7653: (use (match_operand 2 "" ""))
7654: (clobber (reg:SI LR_REGNUM))])])
7655:
7656: (define_insn "*call_reg_armv5"
7657: [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7658: (match_operand 1 "" ""))
7659: (use (match_operand 2 "" ""))
7660: (clobber (reg:SI LR_REGNUM))]
1.5 mrg 7661: "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
1.1 mrg 7662: "blx%?\\t%0"
7663: [(set_attr "type" "call")]
7664: )
7665:
7666: (define_insn "*call_reg_arm"
7667: [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7668: (match_operand 1 "" ""))
7669: (use (match_operand 2 "" ""))
7670: (clobber (reg:SI LR_REGNUM))]
1.5 mrg 7671: "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
1.1 mrg 7672: "*
7673: return output_call (operands);
7674: "
7675: ;; length is worst case, normally it is only two
7676: [(set_attr "length" "12")
7677: (set_attr "type" "call")]
7678: )
7679:
7680:
7681: (define_expand "call_value"
7682: [(parallel [(set (match_operand 0 "" "")
7683: (call (match_operand 1 "memory_operand" "")
7684: (match_operand 2 "general_operand" "")))
7685: (use (match_operand 3 "" ""))
7686: (clobber (reg:SI LR_REGNUM))])]
7687: "TARGET_EITHER"
7688: "
7689: {
7690: rtx pat, callee;
7691:
7692: /* In an untyped call, we can get NULL for operand 2. */
7693: if (operands[3] == 0)
7694: operands[3] = const0_rtx;
7695:
7696: /* Decide if we should generate indirect calls by loading the
7697: 32-bit address of the callee into a register before performing the
7698: branch and link. */
7699: callee = XEXP (operands[1], 0);
7700: if (GET_CODE (callee) == SYMBOL_REF
7701: ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
7702: : !REG_P (callee))
7703: XEXP (operands[1], 0) = force_reg (Pmode, callee);
7704:
7705: pat = gen_call_value_internal (operands[0], operands[1],
7706: operands[2], operands[3]);
1.5 mrg 7707: arm_emit_call_insn (pat, XEXP (operands[1], 0), false);
1.1 mrg 7708: DONE;
7709: }"
7710: )
7711:
7712: (define_expand "call_value_internal"
7713: [(parallel [(set (match_operand 0 "" "")
7714: (call (match_operand 1 "memory_operand" "")
7715: (match_operand 2 "general_operand" "")))
7716: (use (match_operand 3 "" ""))
7717: (clobber (reg:SI LR_REGNUM))])])
7718:
7719: (define_insn "*call_value_reg_armv5"
7720: [(set (match_operand 0 "" "")
7721: (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7722: (match_operand 2 "" "")))
7723: (use (match_operand 3 "" ""))
7724: (clobber (reg:SI LR_REGNUM))]
1.5 mrg 7725: "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)"
1.1 mrg 7726: "blx%?\\t%1"
7727: [(set_attr "type" "call")]
7728: )
7729:
7730: (define_insn "*call_value_reg_arm"
7731: [(set (match_operand 0 "" "")
7732: (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7733: (match_operand 2 "" "")))
7734: (use (match_operand 3 "" ""))
7735: (clobber (reg:SI LR_REGNUM))]
1.5 mrg 7736: "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)"
1.1 mrg 7737: "*
7738: return output_call (&operands[1]);
7739: "
7740: [(set_attr "length" "12")
7741: (set_attr "type" "call")]
7742: )
7743:
7744: ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7745: ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7746:
7747: (define_insn "*call_symbol"
7748: [(call (mem:SI (match_operand:SI 0 "" ""))
7749: (match_operand 1 "" ""))
7750: (use (match_operand 2 "" ""))
7751: (clobber (reg:SI LR_REGNUM))]
1.3 mrg 7752: "TARGET_32BIT
1.5 mrg 7753: && !SIBLING_CALL_P (insn)
1.1 mrg 7754: && (GET_CODE (operands[0]) == SYMBOL_REF)
7755: && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
7756: "*
7757: {
1.7 ! mrg 7758: rtx op = operands[0];
! 7759:
! 7760: /* Switch mode now when possible. */
! 7761: if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
! 7762: && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
! 7763: return NEED_PLT_RELOC ? \"blx%?\\t%a0(PLT)\" : \"blx%?\\t(%a0)\";
! 7764:
1.1 mrg 7765: return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7766: }"
7767: [(set_attr "type" "call")]
7768: )
7769:
7770: (define_insn "*call_value_symbol"
7771: [(set (match_operand 0 "" "")
7772: (call (mem:SI (match_operand:SI 1 "" ""))
7773: (match_operand:SI 2 "" "")))
7774: (use (match_operand 3 "" ""))
7775: (clobber (reg:SI LR_REGNUM))]
1.3 mrg 7776: "TARGET_32BIT
1.5 mrg 7777: && !SIBLING_CALL_P (insn)
1.1 mrg 7778: && (GET_CODE (operands[1]) == SYMBOL_REF)
7779: && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
7780: "*
7781: {
1.7 ! mrg 7782: rtx op = operands[1];
! 7783:
! 7784: /* Switch mode now when possible. */
! 7785: if (SYMBOL_REF_DECL (op) && !TREE_PUBLIC (SYMBOL_REF_DECL (op))
! 7786: && arm_arch5 && arm_change_mode_p (SYMBOL_REF_DECL (op)))
! 7787: return NEED_PLT_RELOC ? \"blx%?\\t%a1(PLT)\" : \"blx%?\\t(%a1)\";
! 7788:
1.1 mrg 7789: return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7790: }"
7791: [(set_attr "type" "call")]
7792: )
7793:
1.5 mrg 7794: (define_expand "sibcall_internal"
7795: [(parallel [(call (match_operand 0 "memory_operand" "")
7796: (match_operand 1 "general_operand" ""))
7797: (return)
7798: (use (match_operand 2 "" ""))])])
1.1 mrg 7799:
7800: ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7801: (define_expand "sibcall"
7802: [(parallel [(call (match_operand 0 "memory_operand" "")
7803: (match_operand 1 "general_operand" ""))
7804: (return)
7805: (use (match_operand 2 "" ""))])]
1.3 mrg 7806: "TARGET_32BIT"
1.1 mrg 7807: "
7808: {
1.5 mrg 7809: rtx pat;
7810:
7811: if ((!REG_P (XEXP (operands[0], 0))
7812: && GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)
7813: || (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
7814: && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[0], 0)))))
7815: XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
7816:
1.1 mrg 7817: if (operands[2] == NULL_RTX)
7818: operands[2] = const0_rtx;
1.5 mrg 7819:
7820: pat = gen_sibcall_internal (operands[0], operands[1], operands[2]);
7821: arm_emit_call_insn (pat, operands[0], true);
7822: DONE;
1.1 mrg 7823: }"
7824: )
7825:
1.5 mrg 7826: (define_expand "sibcall_value_internal"
7827: [(parallel [(set (match_operand 0 "" "")
7828: (call (match_operand 1 "memory_operand" "")
7829: (match_operand 2 "general_operand" "")))
7830: (return)
7831: (use (match_operand 3 "" ""))])])
7832:
1.1 mrg 7833: (define_expand "sibcall_value"
7834: [(parallel [(set (match_operand 0 "" "")
7835: (call (match_operand 1 "memory_operand" "")
7836: (match_operand 2 "general_operand" "")))
7837: (return)
7838: (use (match_operand 3 "" ""))])]
1.3 mrg 7839: "TARGET_32BIT"
1.1 mrg 7840: "
7841: {
1.5 mrg 7842: rtx pat;
7843:
7844: if ((!REG_P (XEXP (operands[1], 0))
7845: && GET_CODE (XEXP (operands[1], 0)) != SYMBOL_REF)
7846: || (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
7847: && arm_is_long_call_p (SYMBOL_REF_DECL (XEXP (operands[1], 0)))))
7848: XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
7849:
1.1 mrg 7850: if (operands[3] == NULL_RTX)
7851: operands[3] = const0_rtx;
1.5 mrg 7852:
7853: pat = gen_sibcall_value_internal (operands[0], operands[1],
7854: operands[2], operands[3]);
7855: arm_emit_call_insn (pat, operands[1], true);
7856: DONE;
1.1 mrg 7857: }"
7858: )
7859:
7860: (define_insn "*sibcall_insn"
1.5 mrg 7861: [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs, US"))
1.1 mrg 7862: (match_operand 1 "" ""))
7863: (return)
7864: (use (match_operand 2 "" ""))]
1.5 mrg 7865: "TARGET_32BIT && SIBLING_CALL_P (insn)"
1.1 mrg 7866: "*
1.5 mrg 7867: if (which_alternative == 1)
7868: return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7869: else
7870: {
7871: if (arm_arch5 || arm_arch4t)
7872: return \"bx%?\\t%0\\t%@ indirect register sibling call\";
7873: else
7874: return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\";
7875: }
1.1 mrg 7876: "
7877: [(set_attr "type" "call")]
7878: )
7879:
7880: (define_insn "*sibcall_value_insn"
7881: [(set (match_operand 0 "" "")
1.5 mrg 7882: (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,US"))
1.1 mrg 7883: (match_operand 2 "" "")))
7884: (return)
7885: (use (match_operand 3 "" ""))]
1.5 mrg 7886: "TARGET_32BIT && SIBLING_CALL_P (insn)"
1.1 mrg 7887: "*
1.5 mrg 7888: if (which_alternative == 1)
7889: return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7890: else
7891: {
7892: if (arm_arch5 || arm_arch4t)
7893: return \"bx%?\\t%1\";
7894: else
7895: return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \";
7896: }
1.1 mrg 7897: "
7898: [(set_attr "type" "call")]
7899: )
7900:
1.5 mrg 7901: (define_expand "<return_str>return"
1.7 ! mrg 7902: [(RETURNS)]
1.3 mrg 7903: "(TARGET_ARM || (TARGET_THUMB2
7904: && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL
7905: && !IS_STACKALIGN (arm_current_func_type ())))
1.5 mrg 7906: <return_cond_false>"
1.3 mrg 7907: "
7908: {
7909: if (TARGET_THUMB2)
7910: {
1.5 mrg 7911: thumb2_expand_return (<return_simple_p>);
1.3 mrg 7912: DONE;
7913: }
7914: }
7915: "
7916: )
7917:
1.1 mrg 7918: ;; Often the return insn will be the same as loading from memory, so set attr
1.3 mrg 7919: (define_insn "*arm_return"
1.1 mrg 7920: [(return)]
7921: "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7922: "*
7923: {
7924: if (arm_ccfsm_state == 2)
7925: {
7926: arm_ccfsm_state += 2;
7927: return \"\";
7928: }
1.3 mrg 7929: return output_return_instruction (const_true_rtx, true, false, false);
1.1 mrg 7930: }"
7931: [(set_attr "type" "load1")
7932: (set_attr "length" "12")
7933: (set_attr "predicable" "yes")]
7934: )
7935:
1.5 mrg 7936: (define_insn "*cond_<return_str>return"
1.1 mrg 7937: [(set (pc)
7938: (if_then_else (match_operator 0 "arm_comparison_operator"
7939: [(match_operand 1 "cc_register" "") (const_int 0)])
1.7 ! mrg 7940: (RETURNS)
1.1 mrg 7941: (pc)))]
1.5 mrg 7942: "TARGET_ARM <return_cond_true>"
1.1 mrg 7943: "*
7944: {
7945: if (arm_ccfsm_state == 2)
7946: {
7947: arm_ccfsm_state += 2;
7948: return \"\";
7949: }
1.5 mrg 7950: return output_return_instruction (operands[0], true, false,
7951: <return_simple_p>);
1.1 mrg 7952: }"
7953: [(set_attr "conds" "use")
7954: (set_attr "length" "12")
7955: (set_attr "type" "load1")]
7956: )
7957:
1.5 mrg 7958: (define_insn "*cond_<return_str>return_inverted"
1.1 mrg 7959: [(set (pc)
7960: (if_then_else (match_operator 0 "arm_comparison_operator"
7961: [(match_operand 1 "cc_register" "") (const_int 0)])
7962: (pc)
1.7 ! mrg 7963: (RETURNS)))]
1.5 mrg 7964: "TARGET_ARM <return_cond_true>"
1.1 mrg 7965: "*
7966: {
7967: if (arm_ccfsm_state == 2)
7968: {
7969: arm_ccfsm_state += 2;
7970: return \"\";
7971: }
1.5 mrg 7972: return output_return_instruction (operands[0], true, true,
7973: <return_simple_p>);
1.1 mrg 7974: }"
7975: [(set_attr "conds" "use")
7976: (set_attr "length" "12")
7977: (set_attr "type" "load1")]
7978: )
7979:
1.3 mrg 7980: (define_insn "*arm_simple_return"
7981: [(simple_return)]
7982: "TARGET_ARM"
7983: "*
7984: {
7985: if (arm_ccfsm_state == 2)
7986: {
7987: arm_ccfsm_state += 2;
7988: return \"\";
7989: }
7990: return output_return_instruction (const_true_rtx, true, false, true);
7991: }"
7992: [(set_attr "type" "branch")
7993: (set_attr "length" "4")
7994: (set_attr "predicable" "yes")]
7995: )
7996:
1.1 mrg 7997: ;; Generate a sequence of instructions to determine if the processor is
7998: ;; in 26-bit or 32-bit mode, and return the appropriate return address
7999: ;; mask.
8000:
8001: (define_expand "return_addr_mask"
8002: [(set (match_dup 1)
8003: (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8004: (const_int 0)))
8005: (set (match_operand:SI 0 "s_register_operand" "")
8006: (if_then_else:SI (eq (match_dup 1) (const_int 0))
8007: (const_int -1)
8008: (const_int 67108860)))] ; 0x03fffffc
8009: "TARGET_ARM"
8010: "
8011: operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8012: ")
8013:
8014: (define_insn "*check_arch2"
8015: [(set (match_operand:CC_NOOV 0 "cc_register" "")
8016: (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8017: (const_int 0)))]
8018: "TARGET_ARM"
8019: "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8020: [(set_attr "length" "8")
1.5 mrg 8021: (set_attr "conds" "set")
8022: (set_attr "type" "multiple")]
1.1 mrg 8023: )
8024:
8025: ;; Call subroutine returning any type.
8026:
8027: (define_expand "untyped_call"
8028: [(parallel [(call (match_operand 0 "" "")
8029: (const_int 0))
8030: (match_operand 1 "" "")
8031: (match_operand 2 "" "")])]
8032: "TARGET_EITHER"
8033: "
8034: {
8035: int i;
8036: rtx par = gen_rtx_PARALLEL (VOIDmode,
8037: rtvec_alloc (XVECLEN (operands[2], 0)));
8038: rtx addr = gen_reg_rtx (Pmode);
8039: rtx mem;
8040: int size = 0;
8041:
8042: emit_move_insn (addr, XEXP (operands[1], 0));
8043: mem = change_address (operands[1], BLKmode, addr);
8044:
8045: for (i = 0; i < XVECLEN (operands[2], 0); i++)
8046: {
8047: rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8048:
8049: /* Default code only uses r0 as a return value, but we could
8050: be using anything up to 4 registers. */
8051: if (REGNO (src) == R0_REGNUM)
8052: src = gen_rtx_REG (TImode, R0_REGNUM);
8053:
8054: XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8055: GEN_INT (size));
8056: size += GET_MODE_SIZE (GET_MODE (src));
8057: }
8058:
1.7 ! mrg 8059: emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
1.1 mrg 8060:
8061: size = 0;
8062:
8063: for (i = 0; i < XVECLEN (par, 0); i++)
8064: {
8065: HOST_WIDE_INT offset = 0;
8066: rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8067:
8068: if (size != 0)
1.3 mrg 8069: emit_move_insn (addr, plus_constant (Pmode, addr, size));
1.1 mrg 8070:
8071: mem = change_address (mem, GET_MODE (reg), NULL);
8072: if (REGNO (reg) == R0_REGNUM)
8073: {
8074: /* On thumb we have to use a write-back instruction. */
1.3 mrg 8075: emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8076: TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1.1 mrg 8077: size = TARGET_ARM ? 16 : 0;
8078: }
8079: else
8080: {
8081: emit_move_insn (mem, reg);
8082: size = GET_MODE_SIZE (GET_MODE (reg));
8083: }
8084: }
8085:
8086: /* The optimizer does not know that the call sets the function value
8087: registers we stored in the result block. We avoid problems by
8088: claiming that all hard registers are used and clobbered at this
8089: point. */
8090: emit_insn (gen_blockage ());
8091:
8092: DONE;
8093: }"
8094: )
8095:
8096: (define_expand "untyped_return"
8097: [(match_operand:BLK 0 "memory_operand" "")
8098: (match_operand 1 "" "")]
8099: "TARGET_EITHER"
8100: "
8101: {
8102: int i;
8103: rtx addr = gen_reg_rtx (Pmode);
8104: rtx mem;
8105: int size = 0;
8106:
8107: emit_move_insn (addr, XEXP (operands[0], 0));
8108: mem = change_address (operands[0], BLKmode, addr);
8109:
8110: for (i = 0; i < XVECLEN (operands[1], 0); i++)
8111: {
8112: HOST_WIDE_INT offset = 0;
8113: rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8114:
8115: if (size != 0)
1.3 mrg 8116: emit_move_insn (addr, plus_constant (Pmode, addr, size));
1.1 mrg 8117:
8118: mem = change_address (mem, GET_MODE (reg), NULL);
8119: if (REGNO (reg) == R0_REGNUM)
8120: {
8121: /* On thumb we have to use a write-back instruction. */
1.3 mrg 8122: emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8123: TARGET_THUMB ? TRUE : FALSE, mem, &offset));
1.1 mrg 8124: size = TARGET_ARM ? 16 : 0;
8125: }
8126: else
8127: {
8128: emit_move_insn (reg, mem);
8129: size = GET_MODE_SIZE (GET_MODE (reg));
8130: }
8131: }
8132:
8133: /* Emit USE insns before the return. */
8134: for (i = 0; i < XVECLEN (operands[1], 0); i++)
8135: emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8136:
8137: /* Construct the return. */
8138: expand_naked_return ();
8139:
8140: DONE;
8141: }"
8142: )
8143:
8144: ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8145: ;; all of memory. This blocks insns from being moved across this point.
8146:
8147: (define_insn "blockage"
8148: [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8149: "TARGET_EITHER"
8150: ""
8151: [(set_attr "length" "0")
8152: (set_attr "type" "block")]
8153: )
8154:
1.7 ! mrg 8155: (define_insn "probe_stack"
! 8156: [(set (match_operand 0 "memory_operand" "=m")
! 8157: (unspec [(const_int 0)] UNSPEC_PROBE_STACK))]
! 8158: "TARGET_32BIT"
! 8159: "str%?\\tr0, %0"
! 8160: [(set_attr "type" "store1")
! 8161: (set_attr "predicable" "yes")]
! 8162: )
! 8163:
! 8164: (define_insn "probe_stack_range"
! 8165: [(set (match_operand:SI 0 "register_operand" "=r")
! 8166: (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")
! 8167: (match_operand:SI 2 "register_operand" "r")]
! 8168: VUNSPEC_PROBE_STACK_RANGE))]
! 8169: "TARGET_32BIT"
! 8170: {
! 8171: return output_probe_stack_range (operands[0], operands[2]);
! 8172: }
! 8173: [(set_attr "type" "multiple")
! 8174: (set_attr "conds" "clob")]
! 8175: )
! 8176:
1.1 mrg 8177: (define_expand "casesi"
8178: [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8179: (match_operand:SI 1 "const_int_operand" "") ; lower bound
8180: (match_operand:SI 2 "const_int_operand" "") ; total range
8181: (match_operand:SI 3 "" "") ; table label
8182: (match_operand:SI 4 "" "")] ; Out of range label
8183: "TARGET_32BIT || optimize_size || flag_pic"
8184: "
8185: {
8186: enum insn_code code;
8187: if (operands[1] != const0_rtx)
8188: {
8189: rtx reg = gen_reg_rtx (SImode);
8190:
8191: emit_insn (gen_addsi3 (reg, operands[0],
1.3 mrg 8192: gen_int_mode (-INTVAL (operands[1]),
8193: SImode)));
1.1 mrg 8194: operands[0] = reg;
8195: }
8196:
8197: if (TARGET_ARM)
8198: code = CODE_FOR_arm_casesi_internal;
8199: else if (TARGET_THUMB1)
8200: code = CODE_FOR_thumb1_casesi_internal_pic;
8201: else if (flag_pic)
8202: code = CODE_FOR_thumb2_casesi_internal_pic;
8203: else
8204: code = CODE_FOR_thumb2_casesi_internal;
8205:
8206: if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8207: operands[2] = force_reg (SImode, operands[2]);
8208:
8209: emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8210: operands[3], operands[4]));
8211: DONE;
8212: }"
8213: )
8214:
8215: ;; The USE in this pattern is needed to tell flow analysis that this is
8216: ;; a CASESI insn. It has no other purpose.
8217: (define_insn "arm_casesi_internal"
8218: [(parallel [(set (pc)
8219: (if_then_else
8220: (leu (match_operand:SI 0 "s_register_operand" "r")
8221: (match_operand:SI 1 "arm_rhs_operand" "rI"))
8222: (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8223: (label_ref (match_operand 2 "" ""))))
8224: (label_ref (match_operand 3 "" ""))))
8225: (clobber (reg:CC CC_REGNUM))
8226: (use (label_ref (match_dup 2)))])]
8227: "TARGET_ARM"
8228: "*
8229: if (flag_pic)
8230: return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8231: return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8232: "
8233: [(set_attr "conds" "clob")
1.5 mrg 8234: (set_attr "length" "12")
8235: (set_attr "type" "multiple")]
1.1 mrg 8236: )
8237:
8238: (define_expand "indirect_jump"
8239: [(set (pc)
8240: (match_operand:SI 0 "s_register_operand" ""))]
8241: "TARGET_EITHER"
8242: "
8243: /* Thumb-2 doesn't have mov pc, reg. Explicitly set the low bit of the
8244: address and use bx. */
8245: if (TARGET_THUMB2)
8246: {
8247: rtx tmp;
8248: tmp = gen_reg_rtx (SImode);
8249: emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8250: operands[0] = tmp;
8251: }
8252: "
8253: )
8254:
8255: ;; NB Never uses BX.
8256: (define_insn "*arm_indirect_jump"
8257: [(set (pc)
8258: (match_operand:SI 0 "s_register_operand" "r"))]
8259: "TARGET_ARM"
8260: "mov%?\\t%|pc, %0\\t%@ indirect register jump"
1.5 mrg 8261: [(set_attr "predicable" "yes")
8262: (set_attr "type" "branch")]
1.1 mrg 8263: )
8264:
8265: (define_insn "*load_indirect_jump"
8266: [(set (pc)
8267: (match_operand:SI 0 "memory_operand" "m"))]
8268: "TARGET_ARM"
8269: "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8270: [(set_attr "type" "load1")
8271: (set_attr "pool_range" "4096")
8272: (set_attr "neg_pool_range" "4084")
8273: (set_attr "predicable" "yes")]
8274: )
8275:
8276:
8277: ;; Misc insns
8278:
8279: (define_insn "nop"
8280: [(const_int 0)]
8281: "TARGET_EITHER"
1.7 ! mrg 8282: "nop"
1.1 mrg 8283: [(set (attr "length")
8284: (if_then_else (eq_attr "is_thumb" "yes")
8285: (const_int 2)
1.5 mrg 8286: (const_int 4)))
8287: (set_attr "type" "mov_reg")]
8288: )
8289:
8290: (define_insn "trap"
8291: [(trap_if (const_int 1) (const_int 0))]
8292: ""
8293: "*
8294: if (TARGET_ARM)
8295: return \".inst\\t0xe7f000f0\";
8296: else
8297: return \".inst\\t0xdeff\";
8298: "
8299: [(set (attr "length")
8300: (if_then_else (eq_attr "is_thumb" "yes")
8301: (const_int 2)
8302: (const_int 4)))
8303: (set_attr "type" "trap")
8304: (set_attr "conds" "unconditional")]
1.1 mrg 8305: )
8306:
8307:
8308: ;; Patterns to allow combination of arithmetic, cond code and shifts
8309:
1.5 mrg 8310: (define_insn "*<arith_shift_insn>_multsi"
8311: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1.7 ! mrg 8312: (SHIFTABLE_OPS:SI
1.5 mrg 8313: (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
8314: (match_operand:SI 3 "power_of_two_operand" ""))
8315: (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>")))]
1.3 mrg 8316: "TARGET_32BIT"
1.5 mrg 8317: "<arith_shift_insn>%?\\t%0, %1, %2, lsl %b3"
8318: [(set_attr "predicable" "yes")
8319: (set_attr "predicable_short_it" "no")
8320: (set_attr "shift" "2")
8321: (set_attr "arch" "a,t2")
8322: (set_attr "type" "alu_shift_imm")])
8323:
8324: (define_insn "*<arith_shift_insn>_shiftsi"
8325: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1.7 ! mrg 8326: (SHIFTABLE_OPS:SI
1.5 mrg 8327: (match_operator:SI 2 "shift_nomul_operator"
8328: [(match_operand:SI 3 "s_register_operand" "r,r,r")
8329: (match_operand:SI 4 "shift_amount_operand" "M,M,r")])
8330: (match_operand:SI 1 "s_register_operand" "rk,<t2_binop0>,rk")))]
8331: "TARGET_32BIT && GET_CODE (operands[2]) != MULT"
8332: "<arith_shift_insn>%?\\t%0, %1, %3%S2"
1.1 mrg 8333: [(set_attr "predicable" "yes")
1.5 mrg 8334: (set_attr "predicable_short_it" "no")
8335: (set_attr "shift" "3")
8336: (set_attr "arch" "a,t2,a")
8337: (set_attr "type" "alu_shift_imm,alu_shift_imm,alu_shift_reg")])
1.1 mrg 8338:
8339: (define_split
8340: [(set (match_operand:SI 0 "s_register_operand" "")
8341: (match_operator:SI 1 "shiftable_operator"
8342: [(match_operator:SI 2 "shiftable_operator"
8343: [(match_operator:SI 3 "shift_operator"
8344: [(match_operand:SI 4 "s_register_operand" "")
8345: (match_operand:SI 5 "reg_or_int_operand" "")])
8346: (match_operand:SI 6 "s_register_operand" "")])
8347: (match_operand:SI 7 "arm_rhs_operand" "")]))
8348: (clobber (match_operand:SI 8 "s_register_operand" ""))]
1.3 mrg 8349: "TARGET_32BIT"
1.1 mrg 8350: [(set (match_dup 8)
8351: (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8352: (match_dup 6)]))
8353: (set (match_dup 0)
8354: (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8355: "")
8356:
8357: (define_insn "*arith_shiftsi_compare0"
8358: [(set (reg:CC_NOOV CC_REGNUM)
1.3 mrg 8359: (compare:CC_NOOV
8360: (match_operator:SI 1 "shiftable_operator"
8361: [(match_operator:SI 3 "shift_operator"
8362: [(match_operand:SI 4 "s_register_operand" "r,r")
8363: (match_operand:SI 5 "shift_amount_operand" "M,r")])
8364: (match_operand:SI 2 "s_register_operand" "r,r")])
8365: (const_int 0)))
8366: (set (match_operand:SI 0 "s_register_operand" "=r,r")
1.1 mrg 8367: (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8368: (match_dup 2)]))]
1.3 mrg 8369: "TARGET_32BIT"
1.7 ! mrg 8370: "%i1s%?\\t%0, %2, %4%S3"
1.1 mrg 8371: [(set_attr "conds" "set")
8372: (set_attr "shift" "4")
1.3 mrg 8373: (set_attr "arch" "32,a")
1.5 mrg 8374: (set_attr "type" "alus_shift_imm,alus_shift_reg")])
1.1 mrg 8375:
8376: (define_insn "*arith_shiftsi_compare0_scratch"
8377: [(set (reg:CC_NOOV CC_REGNUM)
1.3 mrg 8378: (compare:CC_NOOV
8379: (match_operator:SI 1 "shiftable_operator"
8380: [(match_operator:SI 3 "shift_operator"
8381: [(match_operand:SI 4 "s_register_operand" "r,r")
8382: (match_operand:SI 5 "shift_amount_operand" "M,r")])
8383: (match_operand:SI 2 "s_register_operand" "r,r")])
8384: (const_int 0)))
8385: (clobber (match_scratch:SI 0 "=r,r"))]
8386: "TARGET_32BIT"
1.7 ! mrg 8387: "%i1s%?\\t%0, %2, %4%S3"
1.1 mrg 8388: [(set_attr "conds" "set")
8389: (set_attr "shift" "4")
1.3 mrg 8390: (set_attr "arch" "32,a")
1.5 mrg 8391: (set_attr "type" "alus_shift_imm,alus_shift_reg")])
1.1 mrg 8392:
8393: (define_insn "*sub_shiftsi"
1.3 mrg 8394: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8395: (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
1.1 mrg 8396: (match_operator:SI 2 "shift_operator"
1.3 mrg 8397: [(match_operand:SI 3 "s_register_operand" "r,r")
8398: (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
8399: "TARGET_32BIT"
1.1 mrg 8400: "sub%?\\t%0, %1, %3%S2"
8401: [(set_attr "predicable" "yes")
8402: (set_attr "shift" "3")
1.3 mrg 8403: (set_attr "arch" "32,a")
1.5 mrg 8404: (set_attr "type" "alus_shift_imm,alus_shift_reg")])
1.1 mrg 8405:
8406: (define_insn "*sub_shiftsi_compare0"
8407: [(set (reg:CC_NOOV CC_REGNUM)
8408: (compare:CC_NOOV
1.5 mrg 8409: (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1.1 mrg 8410: (match_operator:SI 2 "shift_operator"
1.5 mrg 8411: [(match_operand:SI 3 "s_register_operand" "r,r,r")
8412: (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
1.1 mrg 8413: (const_int 0)))
1.5 mrg 8414: (set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1.3 mrg 8415: (minus:SI (match_dup 1)
8416: (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
8417: "TARGET_32BIT"
1.7 ! mrg 8418: "subs%?\\t%0, %1, %3%S2"
1.1 mrg 8419: [(set_attr "conds" "set")
8420: (set_attr "shift" "3")
1.5 mrg 8421: (set_attr "arch" "32,a,a")
8422: (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
1.1 mrg 8423:
8424: (define_insn "*sub_shiftsi_compare0_scratch"
8425: [(set (reg:CC_NOOV CC_REGNUM)
8426: (compare:CC_NOOV
1.5 mrg 8427: (minus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1.1 mrg 8428: (match_operator:SI 2 "shift_operator"
1.5 mrg 8429: [(match_operand:SI 3 "s_register_operand" "r,r,r")
8430: (match_operand:SI 4 "shift_amount_operand" "M,r,M")]))
1.1 mrg 8431: (const_int 0)))
1.5 mrg 8432: (clobber (match_scratch:SI 0 "=r,r,r"))]
1.3 mrg 8433: "TARGET_32BIT"
1.7 ! mrg 8434: "subs%?\\t%0, %1, %3%S2"
1.1 mrg 8435: [(set_attr "conds" "set")
8436: (set_attr "shift" "3")
1.5 mrg 8437: (set_attr "arch" "32,a,a")
8438: (set_attr "type" "alus_shift_imm,alus_shift_reg,alus_shift_imm")])
1.1 mrg 8439:
8440:
1.5 mrg 8441: (define_insn_and_split "*and_scc"
1.1 mrg 8442: [(set (match_operand:SI 0 "s_register_operand" "=r")
8443: (and:SI (match_operator:SI 1 "arm_comparison_operator"
1.5 mrg 8444: [(match_operand 2 "cc_register" "") (const_int 0)])
8445: (match_operand:SI 3 "s_register_operand" "r")))]
1.1 mrg 8446: "TARGET_ARM"
1.5 mrg 8447: "#" ; "mov%D1\\t%0, #0\;and%d1\\t%0, %3, #1"
8448: "&& reload_completed"
8449: [(cond_exec (match_dup 5) (set (match_dup 0) (const_int 0)))
8450: (cond_exec (match_dup 4) (set (match_dup 0)
8451: (and:SI (match_dup 3) (const_int 1))))]
8452: {
8453: machine_mode mode = GET_MODE (operands[2]);
8454: enum rtx_code rc = GET_CODE (operands[1]);
8455:
8456: /* Note that operands[4] is the same as operands[1],
8457: but with VOIDmode as the result. */
8458: operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8459: if (mode == CCFPmode || mode == CCFPEmode)
8460: rc = reverse_condition_maybe_unordered (rc);
8461: else
8462: rc = reverse_condition (rc);
8463: operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8464: }
1.1 mrg 8465: [(set_attr "conds" "use")
1.5 mrg 8466: (set_attr "type" "multiple")
1.1 mrg 8467: (set_attr "length" "8")]
8468: )
8469:
1.5 mrg 8470: (define_insn_and_split "*ior_scc"
1.1 mrg 8471: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1.5 mrg 8472: (ior:SI (match_operator:SI 1 "arm_comparison_operator"
8473: [(match_operand 2 "cc_register" "") (const_int 0)])
8474: (match_operand:SI 3 "s_register_operand" "0,?r")))]
1.1 mrg 8475: "TARGET_ARM"
8476: "@
1.5 mrg 8477: orr%d1\\t%0, %3, #1
8478: #"
8479: "&& reload_completed
8480: && REGNO (operands [0]) != REGNO (operands[3])"
8481: ;; && which_alternative == 1
8482: ; mov%D1\\t%0, %3\;orr%d1\\t%0, %3, #1
8483: [(cond_exec (match_dup 5) (set (match_dup 0) (match_dup 3)))
8484: (cond_exec (match_dup 4) (set (match_dup 0)
8485: (ior:SI (match_dup 3) (const_int 1))))]
8486: {
8487: machine_mode mode = GET_MODE (operands[2]);
8488: enum rtx_code rc = GET_CODE (operands[1]);
8489:
8490: /* Note that operands[4] is the same as operands[1],
8491: but with VOIDmode as the result. */
8492: operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8493: if (mode == CCFPmode || mode == CCFPEmode)
8494: rc = reverse_condition_maybe_unordered (rc);
8495: else
8496: rc = reverse_condition (rc);
8497: operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
8498: }
1.1 mrg 8499: [(set_attr "conds" "use")
1.5 mrg 8500: (set_attr "length" "4,8")
8501: (set_attr "type" "logic_imm,multiple")]
1.1 mrg 8502: )
8503:
1.3 mrg 8504: ; A series of splitters for the compare_scc pattern below. Note that
8505: ; order is important.
8506: (define_split
8507: [(set (match_operand:SI 0 "s_register_operand" "")
8508: (lt:SI (match_operand:SI 1 "s_register_operand" "")
8509: (const_int 0)))
8510: (clobber (reg:CC CC_REGNUM))]
8511: "TARGET_32BIT && reload_completed"
8512: [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
8513:
8514: (define_split
8515: [(set (match_operand:SI 0 "s_register_operand" "")
8516: (ge:SI (match_operand:SI 1 "s_register_operand" "")
8517: (const_int 0)))
8518: (clobber (reg:CC CC_REGNUM))]
8519: "TARGET_32BIT && reload_completed"
8520: [(set (match_dup 0) (not:SI (match_dup 1)))
8521: (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
8522:
8523: (define_split
8524: [(set (match_operand:SI 0 "s_register_operand" "")
8525: (eq:SI (match_operand:SI 1 "s_register_operand" "")
8526: (const_int 0)))
8527: (clobber (reg:CC CC_REGNUM))]
1.5 mrg 8528: "arm_arch5 && TARGET_32BIT"
8529: [(set (match_dup 0) (clz:SI (match_dup 1)))
8530: (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8531: )
8532:
8533: (define_split
8534: [(set (match_operand:SI 0 "s_register_operand" "")
8535: (eq:SI (match_operand:SI 1 "s_register_operand" "")
8536: (const_int 0)))
8537: (clobber (reg:CC CC_REGNUM))]
1.3 mrg 8538: "TARGET_32BIT && reload_completed"
8539: [(parallel
8540: [(set (reg:CC CC_REGNUM)
8541: (compare:CC (const_int 1) (match_dup 1)))
8542: (set (match_dup 0)
8543: (minus:SI (const_int 1) (match_dup 1)))])
8544: (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
8545: (set (match_dup 0) (const_int 0)))])
8546:
8547: (define_split
8548: [(set (match_operand:SI 0 "s_register_operand" "")
8549: (ne:SI (match_operand:SI 1 "s_register_operand" "")
8550: (match_operand:SI 2 "const_int_operand" "")))
8551: (clobber (reg:CC CC_REGNUM))]
8552: "TARGET_32BIT && reload_completed"
8553: [(parallel
8554: [(set (reg:CC CC_REGNUM)
8555: (compare:CC (match_dup 1) (match_dup 2)))
8556: (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
8557: (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
8558: (set (match_dup 0) (const_int 1)))]
8559: {
8560: operands[3] = GEN_INT (-INTVAL (operands[2]));
8561: })
8562:
8563: (define_split
8564: [(set (match_operand:SI 0 "s_register_operand" "")
8565: (ne:SI (match_operand:SI 1 "s_register_operand" "")
8566: (match_operand:SI 2 "arm_add_operand" "")))
8567: (clobber (reg:CC CC_REGNUM))]
8568: "TARGET_32BIT && reload_completed"
8569: [(parallel
8570: [(set (reg:CC_NOOV CC_REGNUM)
8571: (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
8572: (const_int 0)))
8573: (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
8574: (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
8575: (set (match_dup 0) (const_int 1)))])
8576:
8577: (define_insn_and_split "*compare_scc"
1.5 mrg 8578: [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
1.1 mrg 8579: (match_operator:SI 1 "arm_comparison_operator"
8580: [(match_operand:SI 2 "s_register_operand" "r,r")
8581: (match_operand:SI 3 "arm_add_operand" "rI,L")]))
1.3 mrg 8582: (clobber (reg:CC CC_REGNUM))]
8583: "TARGET_32BIT"
8584: "#"
8585: "&& reload_completed"
8586: [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
8587: (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
8588: (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
8589: {
8590: rtx tmp1;
1.5 mrg 8591: machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
1.3 mrg 8592: operands[2], operands[3]);
8593: enum rtx_code rc = GET_CODE (operands[1]);
8594:
8595: tmp1 = gen_rtx_REG (mode, CC_REGNUM);
8596:
8597: operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
8598: if (mode == CCFPmode || mode == CCFPEmode)
8599: rc = reverse_condition_maybe_unordered (rc);
8600: else
8601: rc = reverse_condition (rc);
8602: operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
1.5 mrg 8603: }
8604: [(set_attr "type" "multiple")]
8605: )
1.1 mrg 8606:
1.3 mrg 8607: ;; Attempt to improve the sequence generated by the compare_scc splitters
8608: ;; not to use conditional execution.
1.5 mrg 8609:
8610: ;; Rd = (eq (reg1) (const_int0)) // ARMv5
8611: ;; clz Rd, reg1
8612: ;; lsr Rd, Rd, #5
8613: (define_peephole2
8614: [(set (reg:CC CC_REGNUM)
8615: (compare:CC (match_operand:SI 1 "register_operand" "")
8616: (const_int 0)))
8617: (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8618: (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8619: (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8620: (set (match_dup 0) (const_int 1)))]
8621: "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8622: [(set (match_dup 0) (clz:SI (match_dup 1)))
8623: (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8624: )
8625:
8626: ;; Rd = (eq (reg1) (const_int0)) // !ARMv5
8627: ;; negs Rd, reg1
8628: ;; adc Rd, Rd, reg1
8629: (define_peephole2
8630: [(set (reg:CC CC_REGNUM)
8631: (compare:CC (match_operand:SI 1 "register_operand" "")
8632: (const_int 0)))
8633: (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8634: (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8635: (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8636: (set (match_dup 0) (const_int 1)))
8637: (match_scratch:SI 2 "r")]
8638: "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8639: [(parallel
8640: [(set (reg:CC CC_REGNUM)
8641: (compare:CC (const_int 0) (match_dup 1)))
8642: (set (match_dup 2) (minus:SI (const_int 0) (match_dup 1)))])
8643: (set (match_dup 0)
8644: (plus:SI (plus:SI (match_dup 1) (match_dup 2))
8645: (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8646: )
8647:
8648: ;; Rd = (eq (reg1) (reg2/imm)) // ARMv5 and optimising for speed.
8649: ;; sub Rd, Reg1, reg2
8650: ;; clz Rd, Rd
8651: ;; lsr Rd, Rd, #5
8652: (define_peephole2
8653: [(set (reg:CC CC_REGNUM)
8654: (compare:CC (match_operand:SI 1 "register_operand" "")
8655: (match_operand:SI 2 "arm_rhs_operand" "")))
8656: (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8657: (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8658: (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8659: (set (match_dup 0) (const_int 1)))]
8660: "arm_arch5 && TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)
8661: && !(TARGET_THUMB2 && optimize_insn_for_size_p ())"
8662: [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))
8663: (set (match_dup 0) (clz:SI (match_dup 0)))
8664: (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 5)))]
8665: )
8666:
8667:
8668: ;; Rd = (eq (reg1) (reg2)) // ! ARMv5 or optimising for size.
8669: ;; sub T1, Reg1, reg2
8670: ;; negs Rd, T1
8671: ;; adc Rd, Rd, T1
1.3 mrg 8672: (define_peephole2
8673: [(set (reg:CC CC_REGNUM)
8674: (compare:CC (match_operand:SI 1 "register_operand" "")
8675: (match_operand:SI 2 "arm_rhs_operand" "")))
8676: (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
8677: (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
8678: (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
8679: (set (match_dup 0) (const_int 1)))
8680: (match_scratch:SI 3 "r")]
1.5 mrg 8681: "TARGET_32BIT && peep2_regno_dead_p (3, CC_REGNUM)"
8682: [(set (match_dup 3) (match_dup 4))
1.3 mrg 8683: (parallel
8684: [(set (reg:CC CC_REGNUM)
8685: (compare:CC (const_int 0) (match_dup 3)))
8686: (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
1.5 mrg 8687: (set (match_dup 0)
8688: (plus:SI (plus:SI (match_dup 0) (match_dup 3))
8689: (geu:SI (reg:CC CC_REGNUM) (const_int 0))))]
8690: "
8691: if (CONST_INT_P (operands[2]))
8692: operands[4] = plus_constant (SImode, operands[1], -INTVAL (operands[2]));
8693: else
8694: operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[2]);
8695: ")
1.1 mrg 8696:
8697: (define_insn "*cond_move"
8698: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8699: (if_then_else:SI (match_operator 3 "equality_operator"
8700: [(match_operator 4 "arm_comparison_operator"
8701: [(match_operand 5 "cc_register" "") (const_int 0)])
8702: (const_int 0)])
8703: (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8704: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8705: "TARGET_ARM"
8706: "*
8707: if (GET_CODE (operands[3]) == NE)
8708: {
8709: if (which_alternative != 1)
8710: output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8711: if (which_alternative != 0)
8712: output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8713: return \"\";
8714: }
8715: if (which_alternative != 0)
8716: output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8717: if (which_alternative != 1)
8718: output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8719: return \"\";
8720: "
8721: [(set_attr "conds" "use")
1.7 ! mrg 8722: (set_attr_alternative "type"
! 8723: [(if_then_else (match_operand 2 "const_int_operand" "")
! 8724: (const_string "mov_imm")
! 8725: (const_string "mov_reg"))
! 8726: (if_then_else (match_operand 1 "const_int_operand" "")
! 8727: (const_string "mov_imm")
! 8728: (const_string "mov_reg"))
! 8729: (const_string "multiple")])
1.1 mrg 8730: (set_attr "length" "4,4,8")]
8731: )
8732:
8733: (define_insn "*cond_arith"
8734: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8735: (match_operator:SI 5 "shiftable_operator"
8736: [(match_operator:SI 4 "arm_comparison_operator"
8737: [(match_operand:SI 2 "s_register_operand" "r,r")
8738: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8739: (match_operand:SI 1 "s_register_operand" "0,?r")]))
8740: (clobber (reg:CC CC_REGNUM))]
8741: "TARGET_ARM"
8742: "*
8743: if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8744: return \"%i5\\t%0, %1, %2, lsr #31\";
8745:
8746: output_asm_insn (\"cmp\\t%2, %3\", operands);
8747: if (GET_CODE (operands[5]) == AND)
8748: output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8749: else if (GET_CODE (operands[5]) == MINUS)
8750: output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8751: else if (which_alternative != 0)
8752: output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8753: return \"%i5%d4\\t%0, %1, #1\";
8754: "
8755: [(set_attr "conds" "clob")
1.5 mrg 8756: (set_attr "length" "12")
8757: (set_attr "type" "multiple")]
1.1 mrg 8758: )
8759:
8760: (define_insn "*cond_sub"
8761: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8762: (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8763: (match_operator:SI 4 "arm_comparison_operator"
8764: [(match_operand:SI 2 "s_register_operand" "r,r")
8765: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8766: (clobber (reg:CC CC_REGNUM))]
8767: "TARGET_ARM"
8768: "*
8769: output_asm_insn (\"cmp\\t%2, %3\", operands);
8770: if (which_alternative != 0)
8771: output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8772: return \"sub%d4\\t%0, %1, #1\";
8773: "
8774: [(set_attr "conds" "clob")
1.5 mrg 8775: (set_attr "length" "8,12")
8776: (set_attr "type" "multiple")]
1.1 mrg 8777: )
8778:
8779: (define_insn "*cmp_ite0"
8780: [(set (match_operand 6 "dominant_cc_register" "")
8781: (compare
8782: (if_then_else:SI
8783: (match_operator 4 "arm_comparison_operator"
1.3 mrg 8784: [(match_operand:SI 0 "s_register_operand"
8785: "l,l,l,r,r,r,r,r,r")
8786: (match_operand:SI 1 "arm_add_operand"
8787: "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
1.1 mrg 8788: (match_operator:SI 5 "arm_comparison_operator"
1.3 mrg 8789: [(match_operand:SI 2 "s_register_operand"
8790: "l,r,r,l,l,r,r,r,r")
8791: (match_operand:SI 3 "arm_add_operand"
8792: "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
1.1 mrg 8793: (const_int 0))
8794: (const_int 0)))]
1.3 mrg 8795: "TARGET_32BIT"
1.1 mrg 8796: "*
8797: {
1.3 mrg 8798: static const char * const cmp1[NUM_OF_COND_CMP][2] =
8799: {
8800: {\"cmp%d5\\t%0, %1\",
8801: \"cmp%d4\\t%2, %3\"},
8802: {\"cmn%d5\\t%0, #%n1\",
8803: \"cmp%d4\\t%2, %3\"},
8804: {\"cmp%d5\\t%0, %1\",
8805: \"cmn%d4\\t%2, #%n3\"},
8806: {\"cmn%d5\\t%0, #%n1\",
8807: \"cmn%d4\\t%2, #%n3\"}
8808: };
8809: static const char * const cmp2[NUM_OF_COND_CMP][2] =
8810: {
8811: {\"cmp\\t%2, %3\",
8812: \"cmp\\t%0, %1\"},
8813: {\"cmp\\t%2, %3\",
8814: \"cmn\\t%0, #%n1\"},
8815: {\"cmn\\t%2, #%n3\",
8816: \"cmp\\t%0, %1\"},
8817: {\"cmn\\t%2, #%n3\",
8818: \"cmn\\t%0, #%n1\"}
8819: };
8820: static const char * const ite[2] =
1.1 mrg 8821: {
1.3 mrg 8822: \"it\\t%d5\",
8823: \"it\\t%d4\"
1.1 mrg 8824: };
1.3 mrg 8825: static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8826: CMP_CMP, CMN_CMP, CMP_CMP,
8827: CMN_CMP, CMP_CMN, CMN_CMN};
1.1 mrg 8828: int swap =
8829: comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8830:
1.3 mrg 8831: output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8832: if (TARGET_THUMB2) {
8833: output_asm_insn (ite[swap], operands);
8834: }
8835: output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8836: return \"\";
1.1 mrg 8837: }"
8838: [(set_attr "conds" "set")
1.3 mrg 8839: (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
1.5 mrg 8840: (set_attr "type" "multiple")
1.3 mrg 8841: (set_attr_alternative "length"
8842: [(const_int 6)
8843: (const_int 8)
8844: (const_int 8)
8845: (const_int 8)
8846: (const_int 8)
8847: (if_then_else (eq_attr "is_thumb" "no")
8848: (const_int 8)
8849: (const_int 10))
8850: (if_then_else (eq_attr "is_thumb" "no")
8851: (const_int 8)
8852: (const_int 10))
8853: (if_then_else (eq_attr "is_thumb" "no")
8854: (const_int 8)
8855: (const_int 10))
8856: (if_then_else (eq_attr "is_thumb" "no")
8857: (const_int 8)
8858: (const_int 10))])]
1.1 mrg 8859: )
8860:
8861: (define_insn "*cmp_ite1"
8862: [(set (match_operand 6 "dominant_cc_register" "")
8863: (compare
8864: (if_then_else:SI
8865: (match_operator 4 "arm_comparison_operator"
1.3 mrg 8866: [(match_operand:SI 0 "s_register_operand"
8867: "l,l,l,r,r,r,r,r,r")
8868: (match_operand:SI 1 "arm_add_operand"
8869: "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
1.1 mrg 8870: (match_operator:SI 5 "arm_comparison_operator"
1.3 mrg 8871: [(match_operand:SI 2 "s_register_operand"
8872: "l,r,r,l,l,r,r,r,r")
8873: (match_operand:SI 3 "arm_add_operand"
8874: "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
1.1 mrg 8875: (const_int 1))
8876: (const_int 0)))]
1.3 mrg 8877: "TARGET_32BIT"
1.1 mrg 8878: "*
8879: {
1.3 mrg 8880: static const char * const cmp1[NUM_OF_COND_CMP][2] =
8881: {
8882: {\"cmp\\t%0, %1\",
8883: \"cmp\\t%2, %3\"},
8884: {\"cmn\\t%0, #%n1\",
8885: \"cmp\\t%2, %3\"},
8886: {\"cmp\\t%0, %1\",
8887: \"cmn\\t%2, #%n3\"},
8888: {\"cmn\\t%0, #%n1\",
8889: \"cmn\\t%2, #%n3\"}
8890: };
8891: static const char * const cmp2[NUM_OF_COND_CMP][2] =
1.1 mrg 8892: {
1.3 mrg 8893: {\"cmp%d4\\t%2, %3\",
8894: \"cmp%D5\\t%0, %1\"},
8895: {\"cmp%d4\\t%2, %3\",
8896: \"cmn%D5\\t%0, #%n1\"},
8897: {\"cmn%d4\\t%2, #%n3\",
8898: \"cmp%D5\\t%0, %1\"},
8899: {\"cmn%d4\\t%2, #%n3\",
8900: \"cmn%D5\\t%0, #%n1\"}
1.1 mrg 8901: };
1.3 mrg 8902: static const char * const ite[2] =
8903: {
8904: \"it\\t%d4\",
8905: \"it\\t%D5\"
8906: };
8907: static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8908: CMP_CMP, CMN_CMP, CMP_CMP,
8909: CMN_CMP, CMP_CMN, CMN_CMN};
1.1 mrg 8910: int swap =
8911: comparison_dominates_p (GET_CODE (operands[5]),
8912: reverse_condition (GET_CODE (operands[4])));
8913:
1.3 mrg 8914: output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
8915: if (TARGET_THUMB2) {
8916: output_asm_insn (ite[swap], operands);
8917: }
8918: output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8919: return \"\";
1.1 mrg 8920: }"
8921: [(set_attr "conds" "set")
1.3 mrg 8922: (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
8923: (set_attr_alternative "length"
8924: [(const_int 6)
8925: (const_int 8)
8926: (const_int 8)
8927: (const_int 8)
8928: (const_int 8)
8929: (if_then_else (eq_attr "is_thumb" "no")
8930: (const_int 8)
8931: (const_int 10))
8932: (if_then_else (eq_attr "is_thumb" "no")
8933: (const_int 8)
8934: (const_int 10))
8935: (if_then_else (eq_attr "is_thumb" "no")
8936: (const_int 8)
8937: (const_int 10))
8938: (if_then_else (eq_attr "is_thumb" "no")
8939: (const_int 8)
1.5 mrg 8940: (const_int 10))])
8941: (set_attr "type" "multiple")]
1.1 mrg 8942: )
8943:
8944: (define_insn "*cmp_and"
8945: [(set (match_operand 6 "dominant_cc_register" "")
8946: (compare
8947: (and:SI
8948: (match_operator 4 "arm_comparison_operator"
1.3 mrg 8949: [(match_operand:SI 0 "s_register_operand"
8950: "l,l,l,r,r,r,r,r,r")
8951: (match_operand:SI 1 "arm_add_operand"
8952: "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
1.1 mrg 8953: (match_operator:SI 5 "arm_comparison_operator"
1.3 mrg 8954: [(match_operand:SI 2 "s_register_operand"
8955: "l,r,r,l,l,r,r,r,r")
8956: (match_operand:SI 3 "arm_add_operand"
8957: "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
1.1 mrg 8958: (const_int 0)))]
1.3 mrg 8959: "TARGET_32BIT"
1.1 mrg 8960: "*
8961: {
1.3 mrg 8962: static const char *const cmp1[NUM_OF_COND_CMP][2] =
1.1 mrg 8963: {
1.3 mrg 8964: {\"cmp%d5\\t%0, %1\",
8965: \"cmp%d4\\t%2, %3\"},
8966: {\"cmn%d5\\t%0, #%n1\",
8967: \"cmp%d4\\t%2, %3\"},
8968: {\"cmp%d5\\t%0, %1\",
8969: \"cmn%d4\\t%2, #%n3\"},
8970: {\"cmn%d5\\t%0, #%n1\",
8971: \"cmn%d4\\t%2, #%n3\"}
1.1 mrg 8972: };
1.3 mrg 8973: static const char *const cmp2[NUM_OF_COND_CMP][2] =
8974: {
8975: {\"cmp\\t%2, %3\",
8976: \"cmp\\t%0, %1\"},
8977: {\"cmp\\t%2, %3\",
8978: \"cmn\\t%0, #%n1\"},
8979: {\"cmn\\t%2, #%n3\",
8980: \"cmp\\t%0, %1\"},
8981: {\"cmn\\t%2, #%n3\",
8982: \"cmn\\t%0, #%n1\"}
8983: };
8984: static const char *const ite[2] =
8985: {
8986: \"it\\t%d5\",
8987: \"it\\t%d4\"
8988: };
8989: static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
8990: CMP_CMP, CMN_CMP, CMP_CMP,
8991: CMN_CMP, CMP_CMN, CMN_CMN};
1.1 mrg 8992: int swap =
8993: comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8994:
1.3 mrg 8995: output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
8996: if (TARGET_THUMB2) {
8997: output_asm_insn (ite[swap], operands);
8998: }
8999: output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9000: return \"\";
1.1 mrg 9001: }"
9002: [(set_attr "conds" "set")
9003: (set_attr "predicable" "no")
1.3 mrg 9004: (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9005: (set_attr_alternative "length"
9006: [(const_int 6)
9007: (const_int 8)
9008: (const_int 8)
9009: (const_int 8)
9010: (const_int 8)
9011: (if_then_else (eq_attr "is_thumb" "no")
9012: (const_int 8)
9013: (const_int 10))
9014: (if_then_else (eq_attr "is_thumb" "no")
9015: (const_int 8)
9016: (const_int 10))
9017: (if_then_else (eq_attr "is_thumb" "no")
9018: (const_int 8)
9019: (const_int 10))
9020: (if_then_else (eq_attr "is_thumb" "no")
9021: (const_int 8)
1.5 mrg 9022: (const_int 10))])
9023: (set_attr "type" "multiple")]
1.1 mrg 9024: )
9025:
9026: (define_insn "*cmp_ior"
9027: [(set (match_operand 6 "dominant_cc_register" "")
9028: (compare
9029: (ior:SI
9030: (match_operator 4 "arm_comparison_operator"
1.3 mrg 9031: [(match_operand:SI 0 "s_register_operand"
9032: "l,l,l,r,r,r,r,r,r")
9033: (match_operand:SI 1 "arm_add_operand"
9034: "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
1.1 mrg 9035: (match_operator:SI 5 "arm_comparison_operator"
1.3 mrg 9036: [(match_operand:SI 2 "s_register_operand"
9037: "l,r,r,l,l,r,r,r,r")
9038: (match_operand:SI 3 "arm_add_operand"
9039: "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
1.1 mrg 9040: (const_int 0)))]
1.3 mrg 9041: "TARGET_32BIT"
1.1 mrg 9042: "*
9043: {
1.3 mrg 9044: static const char *const cmp1[NUM_OF_COND_CMP][2] =
9045: {
9046: {\"cmp\\t%0, %1\",
9047: \"cmp\\t%2, %3\"},
9048: {\"cmn\\t%0, #%n1\",
9049: \"cmp\\t%2, %3\"},
9050: {\"cmp\\t%0, %1\",
9051: \"cmn\\t%2, #%n3\"},
9052: {\"cmn\\t%0, #%n1\",
9053: \"cmn\\t%2, #%n3\"}
9054: };
9055: static const char *const cmp2[NUM_OF_COND_CMP][2] =
9056: {
9057: {\"cmp%D4\\t%2, %3\",
9058: \"cmp%D5\\t%0, %1\"},
9059: {\"cmp%D4\\t%2, %3\",
9060: \"cmn%D5\\t%0, #%n1\"},
9061: {\"cmn%D4\\t%2, #%n3\",
9062: \"cmp%D5\\t%0, %1\"},
9063: {\"cmn%D4\\t%2, #%n3\",
9064: \"cmn%D5\\t%0, #%n1\"}
9065: };
9066: static const char *const ite[2] =
9067: {
9068: \"it\\t%D4\",
9069: \"it\\t%D5\"
9070: };
9071: static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9072: CMP_CMP, CMN_CMP, CMP_CMP,
9073: CMN_CMP, CMP_CMN, CMN_CMN};
9074: int swap =
9075: comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
1.1 mrg 9076:
1.3 mrg 9077: output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9078: if (TARGET_THUMB2) {
9079: output_asm_insn (ite[swap], operands);
9080: }
9081: output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9082: return \"\";
9083: }
9084: "
1.1 mrg 9085: [(set_attr "conds" "set")
1.3 mrg 9086: (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9087: (set_attr_alternative "length"
9088: [(const_int 6)
9089: (const_int 8)
9090: (const_int 8)
9091: (const_int 8)
9092: (const_int 8)
9093: (if_then_else (eq_attr "is_thumb" "no")
9094: (const_int 8)
9095: (const_int 10))
9096: (if_then_else (eq_attr "is_thumb" "no")
9097: (const_int 8)
9098: (const_int 10))
9099: (if_then_else (eq_attr "is_thumb" "no")
9100: (const_int 8)
9101: (const_int 10))
9102: (if_then_else (eq_attr "is_thumb" "no")
9103: (const_int 8)
1.5 mrg 9104: (const_int 10))])
9105: (set_attr "type" "multiple")]
1.1 mrg 9106: )
9107:
9108: (define_insn_and_split "*ior_scc_scc"
1.5 mrg 9109: [(set (match_operand:SI 0 "s_register_operand" "=Ts")
1.1 mrg 9110: (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9111: [(match_operand:SI 1 "s_register_operand" "r")
9112: (match_operand:SI 2 "arm_add_operand" "rIL")])
9113: (match_operator:SI 6 "arm_comparison_operator"
9114: [(match_operand:SI 4 "s_register_operand" "r")
9115: (match_operand:SI 5 "arm_add_operand" "rIL")])))
9116: (clobber (reg:CC CC_REGNUM))]
1.3 mrg 9117: "TARGET_32BIT
1.1 mrg 9118: && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9119: != CCmode)"
9120: "#"
1.3 mrg 9121: "TARGET_32BIT && reload_completed"
1.1 mrg 9122: [(set (match_dup 7)
9123: (compare
9124: (ior:SI
9125: (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9126: (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9127: (const_int 0)))
9128: (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9129: "operands[7]
9130: = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9131: DOM_CC_X_OR_Y),
9132: CC_REGNUM);"
9133: [(set_attr "conds" "clob")
1.5 mrg 9134: (set_attr "length" "16")
9135: (set_attr "type" "multiple")]
9136: )
1.1 mrg 9137:
9138: ; If the above pattern is followed by a CMP insn, then the compare is
9139: ; redundant, since we can rework the conditional instruction that follows.
9140: (define_insn_and_split "*ior_scc_scc_cmp"
9141: [(set (match_operand 0 "dominant_cc_register" "")
9142: (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9143: [(match_operand:SI 1 "s_register_operand" "r")
9144: (match_operand:SI 2 "arm_add_operand" "rIL")])
9145: (match_operator:SI 6 "arm_comparison_operator"
9146: [(match_operand:SI 4 "s_register_operand" "r")
9147: (match_operand:SI 5 "arm_add_operand" "rIL")]))
9148: (const_int 0)))
1.5 mrg 9149: (set (match_operand:SI 7 "s_register_operand" "=Ts")
1.1 mrg 9150: (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9151: (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
1.3 mrg 9152: "TARGET_32BIT"
1.1 mrg 9153: "#"
1.3 mrg 9154: "TARGET_32BIT && reload_completed"
1.1 mrg 9155: [(set (match_dup 0)
9156: (compare
9157: (ior:SI
9158: (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9159: (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9160: (const_int 0)))
9161: (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9162: ""
9163: [(set_attr "conds" "set")
1.5 mrg 9164: (set_attr "length" "16")
9165: (set_attr "type" "multiple")]
9166: )
1.1 mrg 9167:
9168: (define_insn_and_split "*and_scc_scc"
1.5 mrg 9169: [(set (match_operand:SI 0 "s_register_operand" "=Ts")
1.1 mrg 9170: (and:SI (match_operator:SI 3 "arm_comparison_operator"
9171: [(match_operand:SI 1 "s_register_operand" "r")
9172: (match_operand:SI 2 "arm_add_operand" "rIL")])
9173: (match_operator:SI 6 "arm_comparison_operator"
9174: [(match_operand:SI 4 "s_register_operand" "r")
9175: (match_operand:SI 5 "arm_add_operand" "rIL")])))
9176: (clobber (reg:CC CC_REGNUM))]
1.3 mrg 9177: "TARGET_32BIT
1.1 mrg 9178: && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9179: != CCmode)"
9180: "#"
1.3 mrg 9181: "TARGET_32BIT && reload_completed
1.1 mrg 9182: && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9183: != CCmode)"
9184: [(set (match_dup 7)
9185: (compare
9186: (and:SI
9187: (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9188: (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9189: (const_int 0)))
9190: (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9191: "operands[7]
9192: = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9193: DOM_CC_X_AND_Y),
9194: CC_REGNUM);"
9195: [(set_attr "conds" "clob")
1.5 mrg 9196: (set_attr "length" "16")
9197: (set_attr "type" "multiple")]
9198: )
1.1 mrg 9199:
9200: ; If the above pattern is followed by a CMP insn, then the compare is
9201: ; redundant, since we can rework the conditional instruction that follows.
9202: (define_insn_and_split "*and_scc_scc_cmp"
9203: [(set (match_operand 0 "dominant_cc_register" "")
9204: (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9205: [(match_operand:SI 1 "s_register_operand" "r")
9206: (match_operand:SI 2 "arm_add_operand" "rIL")])
9207: (match_operator:SI 6 "arm_comparison_operator"
9208: [(match_operand:SI 4 "s_register_operand" "r")
9209: (match_operand:SI 5 "arm_add_operand" "rIL")]))
9210: (const_int 0)))
1.5 mrg 9211: (set (match_operand:SI 7 "s_register_operand" "=Ts")
1.1 mrg 9212: (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9213: (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
1.3 mrg 9214: "TARGET_32BIT"
1.1 mrg 9215: "#"
1.3 mrg 9216: "TARGET_32BIT && reload_completed"
1.1 mrg 9217: [(set (match_dup 0)
9218: (compare
9219: (and:SI
9220: (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9221: (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9222: (const_int 0)))
9223: (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9224: ""
9225: [(set_attr "conds" "set")
1.5 mrg 9226: (set_attr "length" "16")
9227: (set_attr "type" "multiple")]
9228: )
1.1 mrg 9229:
9230: ;; If there is no dominance in the comparison, then we can still save an
9231: ;; instruction in the AND case, since we can know that the second compare
9232: ;; need only zero the value if false (if true, then the value is already
9233: ;; correct).
9234: (define_insn_and_split "*and_scc_scc_nodom"
1.5 mrg 9235: [(set (match_operand:SI 0 "s_register_operand" "=&Ts,&Ts,&Ts")
1.1 mrg 9236: (and:SI (match_operator:SI 3 "arm_comparison_operator"
9237: [(match_operand:SI 1 "s_register_operand" "r,r,0")
9238: (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9239: (match_operator:SI 6 "arm_comparison_operator"
9240: [(match_operand:SI 4 "s_register_operand" "r,r,r")
9241: (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9242: (clobber (reg:CC CC_REGNUM))]
1.3 mrg 9243: "TARGET_32BIT
1.1 mrg 9244: && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9245: == CCmode)"
9246: "#"
1.3 mrg 9247: "TARGET_32BIT && reload_completed"
1.1 mrg 9248: [(parallel [(set (match_dup 0)
9249: (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9250: (clobber (reg:CC CC_REGNUM))])
9251: (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9252: (set (match_dup 0)
9253: (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9254: (match_dup 0)
9255: (const_int 0)))]
9256: "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9257: operands[4], operands[5]),
9258: CC_REGNUM);
9259: operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9260: operands[5]);"
9261: [(set_attr "conds" "clob")
1.5 mrg 9262: (set_attr "length" "20")
9263: (set_attr "type" "multiple")]
9264: )
1.1 mrg 9265:
9266: (define_split
9267: [(set (reg:CC_NOOV CC_REGNUM)
9268: (compare:CC_NOOV (ior:SI
9269: (and:SI (match_operand:SI 0 "s_register_operand" "")
9270: (const_int 1))
9271: (match_operator:SI 1 "arm_comparison_operator"
9272: [(match_operand:SI 2 "s_register_operand" "")
9273: (match_operand:SI 3 "arm_add_operand" "")]))
9274: (const_int 0)))
9275: (clobber (match_operand:SI 4 "s_register_operand" ""))]
9276: "TARGET_ARM"
9277: [(set (match_dup 4)
9278: (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9279: (match_dup 0)))
9280: (set (reg:CC_NOOV CC_REGNUM)
9281: (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9282: (const_int 0)))]
9283: "")
9284:
9285: (define_split
9286: [(set (reg:CC_NOOV CC_REGNUM)
9287: (compare:CC_NOOV (ior:SI
9288: (match_operator:SI 1 "arm_comparison_operator"
9289: [(match_operand:SI 2 "s_register_operand" "")
9290: (match_operand:SI 3 "arm_add_operand" "")])
9291: (and:SI (match_operand:SI 0 "s_register_operand" "")
9292: (const_int 1)))
9293: (const_int 0)))
9294: (clobber (match_operand:SI 4 "s_register_operand" ""))]
9295: "TARGET_ARM"
9296: [(set (match_dup 4)
9297: (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9298: (match_dup 0)))
9299: (set (reg:CC_NOOV CC_REGNUM)
9300: (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9301: (const_int 0)))]
9302: "")
9303: ;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9304:
1.5 mrg 9305: (define_insn_and_split "*negscc"
1.1 mrg 9306: [(set (match_operand:SI 0 "s_register_operand" "=r")
9307: (neg:SI (match_operator 3 "arm_comparison_operator"
9308: [(match_operand:SI 1 "s_register_operand" "r")
9309: (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9310: (clobber (reg:CC CC_REGNUM))]
9311: "TARGET_ARM"
1.5 mrg 9312: "#"
9313: "&& reload_completed"
9314: [(const_int 0)]
9315: {
9316: rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
9317:
9318: if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9319: {
9320: /* Emit mov\\t%0, %1, asr #31 */
1.7 ! mrg 9321: emit_insn (gen_rtx_SET (operands[0],
1.5 mrg 9322: gen_rtx_ASHIFTRT (SImode,
9323: operands[1],
9324: GEN_INT (31))));
9325: DONE;
9326: }
9327: else if (GET_CODE (operands[3]) == NE)
9328: {
9329: /* Emit subs\\t%0, %1, %2\;mvnne\\t%0, #0 */
9330: if (CONST_INT_P (operands[2]))
9331: emit_insn (gen_cmpsi2_addneg (operands[0], operands[1], operands[2],
9332: GEN_INT (- INTVAL (operands[2]))));
9333: else
9334: emit_insn (gen_subsi3_compare (operands[0], operands[1], operands[2]));
9335:
9336: emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9337: gen_rtx_NE (SImode,
9338: cc_reg,
9339: const0_rtx),
1.7 ! mrg 9340: gen_rtx_SET (operands[0],
1.5 mrg 9341: GEN_INT (~0))));
9342: DONE;
9343: }
9344: else
9345: {
9346: /* Emit: cmp\\t%1, %2\;mov%D3\\t%0, #0\;mvn%d3\\t%0, #0 */
1.7 ! mrg 9347: emit_insn (gen_rtx_SET (cc_reg,
1.5 mrg 9348: gen_rtx_COMPARE (CCmode, operands[1], operands[2])));
9349: enum rtx_code rc = GET_CODE (operands[3]);
9350:
9351: rc = reverse_condition (rc);
9352: emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9353: gen_rtx_fmt_ee (rc,
9354: VOIDmode,
9355: cc_reg,
9356: const0_rtx),
1.7 ! mrg 9357: gen_rtx_SET (operands[0], const0_rtx)));
1.5 mrg 9358: rc = GET_CODE (operands[3]);
9359: emit_insn (gen_rtx_COND_EXEC (VOIDmode,
9360: gen_rtx_fmt_ee (rc,
9361: VOIDmode,
9362: cc_reg,
9363: const0_rtx),
1.7 ! mrg 9364: gen_rtx_SET (operands[0],
1.5 mrg 9365: GEN_INT (~0))));
9366: DONE;
9367: }
9368: FAIL;
9369: }
9370: [(set_attr "conds" "clob")
9371: (set_attr "length" "12")
9372: (set_attr "type" "multiple")]
9373: )
1.1 mrg 9374:
1.5 mrg 9375: (define_insn_and_split "movcond_addsi"
9376: [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
9377: (if_then_else:SI
9378: (match_operator 5 "comparison_operator"
9379: [(plus:SI (match_operand:SI 3 "s_register_operand" "r,r,r")
9380: (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL"))
9381: (const_int 0)])
9382: (match_operand:SI 1 "arm_rhs_operand" "rI,rPy,r")
9383: (match_operand:SI 2 "arm_rhs_operand" "rI,rPy,r")))
9384: (clobber (reg:CC CC_REGNUM))]
9385: "TARGET_32BIT"
9386: "#"
9387: "&& reload_completed"
9388: [(set (reg:CC_NOOV CC_REGNUM)
9389: (compare:CC_NOOV
9390: (plus:SI (match_dup 3)
9391: (match_dup 4))
9392: (const_int 0)))
9393: (set (match_dup 0) (match_dup 1))
9394: (cond_exec (match_dup 6)
9395: (set (match_dup 0) (match_dup 2)))]
9396: "
9397: {
9398: machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]),
9399: operands[3], operands[4]);
9400: enum rtx_code rc = GET_CODE (operands[5]);
9401: operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9402: gcc_assert (!(mode == CCFPmode || mode == CCFPEmode));
9403: if (!REG_P (operands[2]) || REGNO (operands[2]) != REGNO (operands[0]))
9404: rc = reverse_condition (rc);
9405: else
9406: std::swap (operands[1], operands[2]);
1.1 mrg 9407:
1.5 mrg 9408: operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9409: }
1.1 mrg 9410: "
9411: [(set_attr "conds" "clob")
1.5 mrg 9412: (set_attr "enabled_for_depr_it" "no,yes,yes")
9413: (set_attr "type" "multiple")]
1.1 mrg 9414: )
9415:
9416: (define_insn "movcond"
9417: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9418: (if_then_else:SI
9419: (match_operator 5 "arm_comparison_operator"
9420: [(match_operand:SI 3 "s_register_operand" "r,r,r")
9421: (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9422: (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9423: (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9424: (clobber (reg:CC CC_REGNUM))]
9425: "TARGET_ARM"
9426: "*
9427: if (GET_CODE (operands[5]) == LT
9428: && (operands[4] == const0_rtx))
9429: {
1.3 mrg 9430: if (which_alternative != 1 && REG_P (operands[1]))
1.1 mrg 9431: {
9432: if (operands[2] == const0_rtx)
9433: return \"and\\t%0, %1, %3, asr #31\";
9434: return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9435: }
1.3 mrg 9436: else if (which_alternative != 0 && REG_P (operands[2]))
1.1 mrg 9437: {
9438: if (operands[1] == const0_rtx)
9439: return \"bic\\t%0, %2, %3, asr #31\";
9440: return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9441: }
9442: /* The only case that falls through to here is when both ops 1 & 2
9443: are constants. */
9444: }
9445:
9446: if (GET_CODE (operands[5]) == GE
9447: && (operands[4] == const0_rtx))
9448: {
1.3 mrg 9449: if (which_alternative != 1 && REG_P (operands[1]))
1.1 mrg 9450: {
9451: if (operands[2] == const0_rtx)
9452: return \"bic\\t%0, %1, %3, asr #31\";
9453: return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9454: }
1.3 mrg 9455: else if (which_alternative != 0 && REG_P (operands[2]))
1.1 mrg 9456: {
9457: if (operands[1] == const0_rtx)
9458: return \"and\\t%0, %2, %3, asr #31\";
9459: return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9460: }
9461: /* The only case that falls through to here is when both ops 1 & 2
9462: are constants. */
9463: }
1.3 mrg 9464: if (CONST_INT_P (operands[4])
1.1 mrg 9465: && !const_ok_for_arm (INTVAL (operands[4])))
9466: output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9467: else
9468: output_asm_insn (\"cmp\\t%3, %4\", operands);
9469: if (which_alternative != 0)
9470: output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9471: if (which_alternative != 1)
9472: output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9473: return \"\";
9474: "
9475: [(set_attr "conds" "clob")
1.5 mrg 9476: (set_attr "length" "8,8,12")
9477: (set_attr "type" "multiple")]
1.1 mrg 9478: )
9479:
9480: ;; ??? The patterns below need checking for Thumb-2 usefulness.
9481:
9482: (define_insn "*ifcompare_plus_move"
9483: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9484: (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9485: [(match_operand:SI 4 "s_register_operand" "r,r")
9486: (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9487: (plus:SI
9488: (match_operand:SI 2 "s_register_operand" "r,r")
9489: (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9490: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9491: (clobber (reg:CC CC_REGNUM))]
9492: "TARGET_ARM"
9493: "#"
9494: [(set_attr "conds" "clob")
1.5 mrg 9495: (set_attr "length" "8,12")
9496: (set_attr "type" "multiple")]
1.1 mrg 9497: )
9498:
9499: (define_insn "*if_plus_move"
9500: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9501: (if_then_else:SI
9502: (match_operator 4 "arm_comparison_operator"
9503: [(match_operand 5 "cc_register" "") (const_int 0)])
9504: (plus:SI
9505: (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9506: (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9507: (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9508: "TARGET_ARM"
9509: "@
9510: add%d4\\t%0, %2, %3
9511: sub%d4\\t%0, %2, #%n3
9512: add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9513: sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9514: [(set_attr "conds" "use")
9515: (set_attr "length" "4,4,8,8")
1.3 mrg 9516: (set_attr_alternative "type"
9517: [(if_then_else (match_operand 3 "const_int_operand" "")
1.5 mrg 9518: (const_string "alu_imm" )
9519: (const_string "alu_sreg"))
9520: (const_string "alu_imm")
1.7 ! mrg 9521: (const_string "multiple")
! 9522: (const_string "multiple")])]
1.1 mrg 9523: )
9524:
9525: (define_insn "*ifcompare_move_plus"
9526: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9527: (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9528: [(match_operand:SI 4 "s_register_operand" "r,r")
9529: (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9530: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9531: (plus:SI
9532: (match_operand:SI 2 "s_register_operand" "r,r")
9533: (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9534: (clobber (reg:CC CC_REGNUM))]
9535: "TARGET_ARM"
9536: "#"
9537: [(set_attr "conds" "clob")
1.5 mrg 9538: (set_attr "length" "8,12")
9539: (set_attr "type" "multiple")]
1.1 mrg 9540: )
9541:
9542: (define_insn "*if_move_plus"
9543: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9544: (if_then_else:SI
9545: (match_operator 4 "arm_comparison_operator"
9546: [(match_operand 5 "cc_register" "") (const_int 0)])
9547: (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9548: (plus:SI
9549: (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9550: (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9551: "TARGET_ARM"
9552: "@
9553: add%D4\\t%0, %2, %3
9554: sub%D4\\t%0, %2, #%n3
9555: add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9556: sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9557: [(set_attr "conds" "use")
9558: (set_attr "length" "4,4,8,8")
1.7 ! mrg 9559: (set_attr_alternative "type"
! 9560: [(if_then_else (match_operand 3 "const_int_operand" "")
! 9561: (const_string "alu_imm" )
! 9562: (const_string "alu_sreg"))
! 9563: (const_string "alu_imm")
! 9564: (const_string "multiple")
! 9565: (const_string "multiple")])]
1.1 mrg 9566: )
9567:
9568: (define_insn "*ifcompare_arith_arith"
9569: [(set (match_operand:SI 0 "s_register_operand" "=r")
9570: (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9571: [(match_operand:SI 5 "s_register_operand" "r")
9572: (match_operand:SI 6 "arm_add_operand" "rIL")])
9573: (match_operator:SI 8 "shiftable_operator"
9574: [(match_operand:SI 1 "s_register_operand" "r")
9575: (match_operand:SI 2 "arm_rhs_operand" "rI")])
9576: (match_operator:SI 7 "shiftable_operator"
9577: [(match_operand:SI 3 "s_register_operand" "r")
9578: (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9579: (clobber (reg:CC CC_REGNUM))]
9580: "TARGET_ARM"
9581: "#"
9582: [(set_attr "conds" "clob")
1.5 mrg 9583: (set_attr "length" "12")
9584: (set_attr "type" "multiple")]
1.1 mrg 9585: )
9586:
9587: (define_insn "*if_arith_arith"
9588: [(set (match_operand:SI 0 "s_register_operand" "=r")
9589: (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9590: [(match_operand 8 "cc_register" "") (const_int 0)])
9591: (match_operator:SI 6 "shiftable_operator"
9592: [(match_operand:SI 1 "s_register_operand" "r")
9593: (match_operand:SI 2 "arm_rhs_operand" "rI")])
9594: (match_operator:SI 7 "shiftable_operator"
9595: [(match_operand:SI 3 "s_register_operand" "r")
9596: (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9597: "TARGET_ARM"
9598: "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9599: [(set_attr "conds" "use")
1.5 mrg 9600: (set_attr "length" "8")
9601: (set_attr "type" "multiple")]
1.1 mrg 9602: )
9603:
9604: (define_insn "*ifcompare_arith_move"
9605: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9606: (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9607: [(match_operand:SI 2 "s_register_operand" "r,r")
9608: (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9609: (match_operator:SI 7 "shiftable_operator"
9610: [(match_operand:SI 4 "s_register_operand" "r,r")
9611: (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9612: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9613: (clobber (reg:CC CC_REGNUM))]
9614: "TARGET_ARM"
9615: "*
9616: /* If we have an operation where (op x 0) is the identity operation and
9617: the conditional operator is LT or GE and we are comparing against zero and
9618: everything is in registers then we can do this in two instructions. */
9619: if (operands[3] == const0_rtx
9620: && GET_CODE (operands[7]) != AND
1.3 mrg 9621: && REG_P (operands[5])
9622: && REG_P (operands[1])
1.1 mrg 9623: && REGNO (operands[1]) == REGNO (operands[4])
9624: && REGNO (operands[4]) != REGNO (operands[0]))
9625: {
9626: if (GET_CODE (operands[6]) == LT)
9627: return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9628: else if (GET_CODE (operands[6]) == GE)
9629: return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9630: }
1.3 mrg 9631: if (CONST_INT_P (operands[3])
1.1 mrg 9632: && !const_ok_for_arm (INTVAL (operands[3])))
9633: output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9634: else
9635: output_asm_insn (\"cmp\\t%2, %3\", operands);
9636: output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9637: if (which_alternative != 0)
9638: return \"mov%D6\\t%0, %1\";
9639: return \"\";
9640: "
9641: [(set_attr "conds" "clob")
1.5 mrg 9642: (set_attr "length" "8,12")
9643: (set_attr "type" "multiple")]
1.1 mrg 9644: )
9645:
9646: (define_insn "*if_arith_move"
9647: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9648: (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9649: [(match_operand 6 "cc_register" "") (const_int 0)])
9650: (match_operator:SI 5 "shiftable_operator"
9651: [(match_operand:SI 2 "s_register_operand" "r,r")
9652: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9653: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9654: "TARGET_ARM"
9655: "@
9656: %I5%d4\\t%0, %2, %3
9657: %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9658: [(set_attr "conds" "use")
9659: (set_attr "length" "4,8")
1.7 ! mrg 9660: (set_attr_alternative "type"
! 9661: [(if_then_else (match_operand 3 "const_int_operand" "")
! 9662: (const_string "alu_shift_imm" )
! 9663: (const_string "alu_shift_reg"))
! 9664: (const_string "multiple")])]
1.1 mrg 9665: )
9666:
9667: (define_insn "*ifcompare_move_arith"
9668: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9669: (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9670: [(match_operand:SI 4 "s_register_operand" "r,r")
9671: (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9672: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9673: (match_operator:SI 7 "shiftable_operator"
9674: [(match_operand:SI 2 "s_register_operand" "r,r")
9675: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9676: (clobber (reg:CC CC_REGNUM))]
9677: "TARGET_ARM"
9678: "*
9679: /* If we have an operation where (op x 0) is the identity operation and
9680: the conditional operator is LT or GE and we are comparing against zero and
9681: everything is in registers then we can do this in two instructions */
9682: if (operands[5] == const0_rtx
9683: && GET_CODE (operands[7]) != AND
1.3 mrg 9684: && REG_P (operands[3])
9685: && REG_P (operands[1])
1.1 mrg 9686: && REGNO (operands[1]) == REGNO (operands[2])
9687: && REGNO (operands[2]) != REGNO (operands[0]))
9688: {
9689: if (GET_CODE (operands[6]) == GE)
9690: return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9691: else if (GET_CODE (operands[6]) == LT)
9692: return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9693: }
9694:
1.3 mrg 9695: if (CONST_INT_P (operands[5])
1.1 mrg 9696: && !const_ok_for_arm (INTVAL (operands[5])))
9697: output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9698: else
9699: output_asm_insn (\"cmp\\t%4, %5\", operands);
9700:
9701: if (which_alternative != 0)
9702: output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9703: return \"%I7%D6\\t%0, %2, %3\";
9704: "
9705: [(set_attr "conds" "clob")
1.5 mrg 9706: (set_attr "length" "8,12")
9707: (set_attr "type" "multiple")]
1.1 mrg 9708: )
9709:
9710: (define_insn "*if_move_arith"
9711: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9712: (if_then_else:SI
9713: (match_operator 4 "arm_comparison_operator"
9714: [(match_operand 6 "cc_register" "") (const_int 0)])
9715: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9716: (match_operator:SI 5 "shiftable_operator"
9717: [(match_operand:SI 2 "s_register_operand" "r,r")
9718: (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9719: "TARGET_ARM"
9720: "@
9721: %I5%D4\\t%0, %2, %3
9722: %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9723: [(set_attr "conds" "use")
9724: (set_attr "length" "4,8")
1.7 ! mrg 9725: (set_attr_alternative "type"
! 9726: [(if_then_else (match_operand 3 "const_int_operand" "")
! 9727: (const_string "alu_shift_imm" )
! 9728: (const_string "alu_shift_reg"))
! 9729: (const_string "multiple")])]
1.1 mrg 9730: )
9731:
9732: (define_insn "*ifcompare_move_not"
9733: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9734: (if_then_else:SI
9735: (match_operator 5 "arm_comparison_operator"
9736: [(match_operand:SI 3 "s_register_operand" "r,r")
9737: (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9738: (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9739: (not:SI
9740: (match_operand:SI 2 "s_register_operand" "r,r"))))
9741: (clobber (reg:CC CC_REGNUM))]
9742: "TARGET_ARM"
9743: "#"
9744: [(set_attr "conds" "clob")
1.5 mrg 9745: (set_attr "length" "8,12")
9746: (set_attr "type" "multiple")]
1.1 mrg 9747: )
9748:
9749: (define_insn "*if_move_not"
9750: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9751: (if_then_else:SI
9752: (match_operator 4 "arm_comparison_operator"
9753: [(match_operand 3 "cc_register" "") (const_int 0)])
9754: (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9755: (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9756: "TARGET_ARM"
9757: "@
9758: mvn%D4\\t%0, %2
9759: mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9760: mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9761: [(set_attr "conds" "use")
1.5 mrg 9762: (set_attr "type" "mvn_reg")
9763: (set_attr "length" "4,8,8")
9764: (set_attr "type" "mvn_reg,multiple,multiple")]
1.1 mrg 9765: )
9766:
9767: (define_insn "*ifcompare_not_move"
9768: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9769: (if_then_else:SI
9770: (match_operator 5 "arm_comparison_operator"
9771: [(match_operand:SI 3 "s_register_operand" "r,r")
9772: (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9773: (not:SI
9774: (match_operand:SI 2 "s_register_operand" "r,r"))
9775: (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9776: (clobber (reg:CC CC_REGNUM))]
9777: "TARGET_ARM"
9778: "#"
9779: [(set_attr "conds" "clob")
1.5 mrg 9780: (set_attr "length" "8,12")
9781: (set_attr "type" "multiple")]
1.1 mrg 9782: )
9783:
9784: (define_insn "*if_not_move"
9785: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9786: (if_then_else:SI
9787: (match_operator 4 "arm_comparison_operator"
9788: [(match_operand 3 "cc_register" "") (const_int 0)])
9789: (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9790: (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9791: "TARGET_ARM"
9792: "@
9793: mvn%d4\\t%0, %2
9794: mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9795: mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9796: [(set_attr "conds" "use")
1.5 mrg 9797: (set_attr "type" "mvn_reg,multiple,multiple")
1.1 mrg 9798: (set_attr "length" "4,8,8")]
9799: )
9800:
9801: (define_insn "*ifcompare_shift_move"
9802: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9803: (if_then_else:SI
9804: (match_operator 6 "arm_comparison_operator"
9805: [(match_operand:SI 4 "s_register_operand" "r,r")
9806: (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9807: (match_operator:SI 7 "shift_operator"
9808: [(match_operand:SI 2 "s_register_operand" "r,r")
9809: (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9810: (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9811: (clobber (reg:CC CC_REGNUM))]
9812: "TARGET_ARM"
9813: "#"
9814: [(set_attr "conds" "clob")
1.5 mrg 9815: (set_attr "length" "8,12")
9816: (set_attr "type" "multiple")]
1.1 mrg 9817: )
9818:
9819: (define_insn "*if_shift_move"
9820: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9821: (if_then_else:SI
9822: (match_operator 5 "arm_comparison_operator"
9823: [(match_operand 6 "cc_register" "") (const_int 0)])
9824: (match_operator:SI 4 "shift_operator"
9825: [(match_operand:SI 2 "s_register_operand" "r,r,r")
9826: (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9827: (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9828: "TARGET_ARM"
9829: "@
9830: mov%d5\\t%0, %2%S4
9831: mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9832: mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9833: [(set_attr "conds" "use")
9834: (set_attr "shift" "2")
9835: (set_attr "length" "4,8,8")
1.7 ! mrg 9836: (set_attr_alternative "type"
! 9837: [(if_then_else (match_operand 3 "const_int_operand" "")
! 9838: (const_string "mov_shift" )
! 9839: (const_string "mov_shift_reg"))
! 9840: (const_string "multiple")
! 9841: (const_string "multiple")])]
1.1 mrg 9842: )
9843:
9844: (define_insn "*ifcompare_move_shift"
9845: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9846: (if_then_else:SI
9847: (match_operator 6 "arm_comparison_operator"
9848: [(match_operand:SI 4 "s_register_operand" "r,r")
9849: (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9850: (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9851: (match_operator:SI 7 "shift_operator"
9852: [(match_operand:SI 2 "s_register_operand" "r,r")
9853: (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9854: (clobber (reg:CC CC_REGNUM))]
9855: "TARGET_ARM"
9856: "#"
9857: [(set_attr "conds" "clob")
1.5 mrg 9858: (set_attr "length" "8,12")
9859: (set_attr "type" "multiple")]
1.1 mrg 9860: )
9861:
9862: (define_insn "*if_move_shift"
9863: [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9864: (if_then_else:SI
9865: (match_operator 5 "arm_comparison_operator"
9866: [(match_operand 6 "cc_register" "") (const_int 0)])
9867: (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9868: (match_operator:SI 4 "shift_operator"
9869: [(match_operand:SI 2 "s_register_operand" "r,r,r")
9870: (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9871: "TARGET_ARM"
9872: "@
9873: mov%D5\\t%0, %2%S4
9874: mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9875: mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9876: [(set_attr "conds" "use")
9877: (set_attr "shift" "2")
9878: (set_attr "length" "4,8,8")
1.7 ! mrg 9879: (set_attr_alternative "type"
! 9880: [(if_then_else (match_operand 3 "const_int_operand" "")
! 9881: (const_string "mov_shift" )
! 9882: (const_string "mov_shift_reg"))
! 9883: (const_string "multiple")
! 9884: (const_string "multiple")])]
1.1 mrg 9885: )
9886:
9887: (define_insn "*ifcompare_shift_shift"
9888: [(set (match_operand:SI 0 "s_register_operand" "=r")
9889: (if_then_else:SI
9890: (match_operator 7 "arm_comparison_operator"
9891: [(match_operand:SI 5 "s_register_operand" "r")
9892: (match_operand:SI 6 "arm_add_operand" "rIL")])
9893: (match_operator:SI 8 "shift_operator"
9894: [(match_operand:SI 1 "s_register_operand" "r")
9895: (match_operand:SI 2 "arm_rhs_operand" "rM")])
9896: (match_operator:SI 9 "shift_operator"
9897: [(match_operand:SI 3 "s_register_operand" "r")
9898: (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9899: (clobber (reg:CC CC_REGNUM))]
9900: "TARGET_ARM"
9901: "#"
9902: [(set_attr "conds" "clob")
1.5 mrg 9903: (set_attr "length" "12")
9904: (set_attr "type" "multiple")]
1.1 mrg 9905: )
9906:
9907: (define_insn "*if_shift_shift"
9908: [(set (match_operand:SI 0 "s_register_operand" "=r")
9909: (if_then_else:SI
9910: (match_operator 5 "arm_comparison_operator"
9911: [(match_operand 8 "cc_register" "") (const_int 0)])
9912: (match_operator:SI 6 "shift_operator"
9913: [(match_operand:SI 1 "s_register_operand" "r")
9914: (match_operand:SI 2 "arm_rhs_operand" "rM")])
9915: (match_operator:SI 7 "shift_operator"
9916: [(match_operand:SI 3 "s_register_operand" "r")
9917: (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9918: "TARGET_ARM"
9919: "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9920: [(set_attr "conds" "use")
9921: (set_attr "shift" "1")
9922: (set_attr "length" "8")
9923: (set (attr "type") (if_then_else
9924: (and (match_operand 2 "const_int_operand" "")
9925: (match_operand 4 "const_int_operand" ""))
1.5 mrg 9926: (const_string "mov_shift")
9927: (const_string "mov_shift_reg")))]
1.1 mrg 9928: )
9929:
9930: (define_insn "*ifcompare_not_arith"
9931: [(set (match_operand:SI 0 "s_register_operand" "=r")
9932: (if_then_else:SI
9933: (match_operator 6 "arm_comparison_operator"
9934: [(match_operand:SI 4 "s_register_operand" "r")
9935: (match_operand:SI 5 "arm_add_operand" "rIL")])
9936: (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9937: (match_operator:SI 7 "shiftable_operator"
9938: [(match_operand:SI 2 "s_register_operand" "r")
9939: (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9940: (clobber (reg:CC CC_REGNUM))]
9941: "TARGET_ARM"
9942: "#"
9943: [(set_attr "conds" "clob")
1.5 mrg 9944: (set_attr "length" "12")
9945: (set_attr "type" "multiple")]
1.1 mrg 9946: )
9947:
9948: (define_insn "*if_not_arith"
9949: [(set (match_operand:SI 0 "s_register_operand" "=r")
9950: (if_then_else:SI
9951: (match_operator 5 "arm_comparison_operator"
9952: [(match_operand 4 "cc_register" "") (const_int 0)])
9953: (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9954: (match_operator:SI 6 "shiftable_operator"
9955: [(match_operand:SI 2 "s_register_operand" "r")
9956: (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9957: "TARGET_ARM"
9958: "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9959: [(set_attr "conds" "use")
1.5 mrg 9960: (set_attr "type" "mvn_reg")
1.1 mrg 9961: (set_attr "length" "8")]
9962: )
9963:
9964: (define_insn "*ifcompare_arith_not"
9965: [(set (match_operand:SI 0 "s_register_operand" "=r")
9966: (if_then_else:SI
9967: (match_operator 6 "arm_comparison_operator"
9968: [(match_operand:SI 4 "s_register_operand" "r")
9969: (match_operand:SI 5 "arm_add_operand" "rIL")])
9970: (match_operator:SI 7 "shiftable_operator"
9971: [(match_operand:SI 2 "s_register_operand" "r")
9972: (match_operand:SI 3 "arm_rhs_operand" "rI")])
9973: (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9974: (clobber (reg:CC CC_REGNUM))]
9975: "TARGET_ARM"
9976: "#"
9977: [(set_attr "conds" "clob")
1.5 mrg 9978: (set_attr "length" "12")
9979: (set_attr "type" "multiple")]
1.1 mrg 9980: )
9981:
9982: (define_insn "*if_arith_not"
9983: [(set (match_operand:SI 0 "s_register_operand" "=r")
9984: (if_then_else:SI
9985: (match_operator 5 "arm_comparison_operator"
9986: [(match_operand 4 "cc_register" "") (const_int 0)])
9987: (match_operator:SI 6 "shiftable_operator"
9988: [(match_operand:SI 2 "s_register_operand" "r")
9989: (match_operand:SI 3 "arm_rhs_operand" "rI")])
9990: (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9991: "TARGET_ARM"
9992: "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9993: [(set_attr "conds" "use")
1.5 mrg 9994: (set_attr "type" "multiple")
1.1 mrg 9995: (set_attr "length" "8")]
9996: )
9997:
9998: (define_insn "*ifcompare_neg_move"
9999: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10000: (if_then_else:SI
10001: (match_operator 5 "arm_comparison_operator"
10002: [(match_operand:SI 3 "s_register_operand" "r,r")
10003: (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10004: (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10005: (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10006: (clobber (reg:CC CC_REGNUM))]
10007: "TARGET_ARM"
10008: "#"
10009: [(set_attr "conds" "clob")
1.5 mrg 10010: (set_attr "length" "8,12")
10011: (set_attr "type" "multiple")]
1.1 mrg 10012: )
10013:
1.7 ! mrg 10014: (define_insn_and_split "*if_neg_move"
! 10015: [(set (match_operand:SI 0 "s_register_operand" "=l,r")
1.1 mrg 10016: (if_then_else:SI
10017: (match_operator 4 "arm_comparison_operator"
10018: [(match_operand 3 "cc_register" "") (const_int 0)])
1.7 ! mrg 10019: (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))
! 10020: (match_operand:SI 1 "s_register_operand" "0,0")))]
! 10021: "TARGET_32BIT"
! 10022: "#"
! 10023: "&& reload_completed"
! 10024: [(cond_exec (match_op_dup 4 [(match_dup 3) (const_int 0)])
! 10025: (set (match_dup 0) (neg:SI (match_dup 2))))]
! 10026: ""
1.1 mrg 10027: [(set_attr "conds" "use")
1.7 ! mrg 10028: (set_attr "length" "4")
! 10029: (set_attr "arch" "t2,32")
! 10030: (set_attr "enabled_for_depr_it" "yes,no")
! 10031: (set_attr "type" "logic_shift_imm")]
1.1 mrg 10032: )
10033:
10034: (define_insn "*ifcompare_move_neg"
10035: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10036: (if_then_else:SI
10037: (match_operator 5 "arm_comparison_operator"
10038: [(match_operand:SI 3 "s_register_operand" "r,r")
10039: (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10040: (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10041: (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10042: (clobber (reg:CC CC_REGNUM))]
10043: "TARGET_ARM"
10044: "#"
10045: [(set_attr "conds" "clob")
1.5 mrg 10046: (set_attr "length" "8,12")
10047: (set_attr "type" "multiple")]
1.1 mrg 10048: )
10049:
1.7 ! mrg 10050: (define_insn_and_split "*if_move_neg"
! 10051: [(set (match_operand:SI 0 "s_register_operand" "=l,r")
1.1 mrg 10052: (if_then_else:SI
10053: (match_operator 4 "arm_comparison_operator"
10054: [(match_operand 3 "cc_register" "") (const_int 0)])
1.7 ! mrg 10055: (match_operand:SI 1 "s_register_operand" "0,0")
! 10056: (neg:SI (match_operand:SI 2 "s_register_operand" "l,r"))))]
! 10057: "TARGET_32BIT"
! 10058: "#"
! 10059: "&& reload_completed"
! 10060: [(cond_exec (match_dup 5)
! 10061: (set (match_dup 0) (neg:SI (match_dup 2))))]
! 10062: {
! 10063: machine_mode mode = GET_MODE (operands[3]);
! 10064: rtx_code rc = GET_CODE (operands[4]);
! 10065:
! 10066: if (mode == CCFPmode || mode == CCFPEmode)
! 10067: rc = reverse_condition_maybe_unordered (rc);
! 10068: else
! 10069: rc = reverse_condition (rc);
! 10070:
! 10071: operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, operands[3], const0_rtx);
! 10072: }
1.1 mrg 10073: [(set_attr "conds" "use")
1.7 ! mrg 10074: (set_attr "length" "4")
! 10075: (set_attr "arch" "t2,32")
! 10076: (set_attr "enabled_for_depr_it" "yes,no")
! 10077: (set_attr "type" "logic_shift_imm")]
1.1 mrg 10078: )
10079:
10080: (define_insn "*arith_adjacentmem"
10081: [(set (match_operand:SI 0 "s_register_operand" "=r")
10082: (match_operator:SI 1 "shiftable_operator"
10083: [(match_operand:SI 2 "memory_operand" "m")
10084: (match_operand:SI 3 "memory_operand" "m")]))
10085: (clobber (match_scratch:SI 4 "=r"))]
10086: "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10087: "*
10088: {
10089: rtx ldm[3];
10090: rtx arith[4];
10091: rtx base_reg;
10092: HOST_WIDE_INT val1 = 0, val2 = 0;
10093:
10094: if (REGNO (operands[0]) > REGNO (operands[4]))
10095: {
10096: ldm[1] = operands[4];
10097: ldm[2] = operands[0];
10098: }
10099: else
10100: {
10101: ldm[1] = operands[0];
10102: ldm[2] = operands[4];
10103: }
10104:
10105: base_reg = XEXP (operands[2], 0);
10106:
10107: if (!REG_P (base_reg))
10108: {
10109: val1 = INTVAL (XEXP (base_reg, 1));
10110: base_reg = XEXP (base_reg, 0);
10111: }
10112:
10113: if (!REG_P (XEXP (operands[3], 0)))
10114: val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10115:
10116: arith[0] = operands[0];
10117: arith[3] = operands[1];
10118:
10119: if (val1 < val2)
10120: {
10121: arith[1] = ldm[1];
10122: arith[2] = ldm[2];
10123: }
10124: else
10125: {
10126: arith[1] = ldm[2];
10127: arith[2] = ldm[1];
10128: }
10129:
10130: ldm[0] = base_reg;
10131: if (val1 !=0 && val2 != 0)
10132: {
10133: rtx ops[3];
10134:
10135: if (val1 == 4 || val2 == 4)
10136: /* Other val must be 8, since we know they are adjacent and neither
10137: is zero. */
1.7 ! mrg 10138: output_asm_insn (\"ldmib%?\\t%0, {%1, %2}\", ldm);
1.1 mrg 10139: else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10140: {
10141: ldm[0] = ops[0] = operands[4];
10142: ops[1] = base_reg;
10143: ops[2] = GEN_INT (val1);
10144: output_add_immediate (ops);
10145: if (val1 < val2)
1.7 ! mrg 10146: output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
1.1 mrg 10147: else
1.7 ! mrg 10148: output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
1.1 mrg 10149: }
10150: else
10151: {
10152: /* Offset is out of range for a single add, so use two ldr. */
10153: ops[0] = ldm[1];
10154: ops[1] = base_reg;
10155: ops[2] = GEN_INT (val1);
10156: output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10157: ops[0] = ldm[2];
10158: ops[2] = GEN_INT (val2);
10159: output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10160: }
10161: }
10162: else if (val1 != 0)
10163: {
10164: if (val1 < val2)
1.7 ! mrg 10165: output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
1.1 mrg 10166: else
1.7 ! mrg 10167: output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
1.1 mrg 10168: }
10169: else
10170: {
10171: if (val1 < val2)
1.7 ! mrg 10172: output_asm_insn (\"ldmia%?\\t%0, {%1, %2}\", ldm);
1.1 mrg 10173: else
1.7 ! mrg 10174: output_asm_insn (\"ldmda%?\\t%0, {%1, %2}\", ldm);
1.1 mrg 10175: }
10176: output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10177: return \"\";
10178: }"
10179: [(set_attr "length" "12")
10180: (set_attr "predicable" "yes")
10181: (set_attr "type" "load1")]
10182: )
10183:
10184: ; This pattern is never tried by combine, so do it as a peephole
10185:
10186: (define_peephole2
10187: [(set (match_operand:SI 0 "arm_general_register_operand" "")
10188: (match_operand:SI 1 "arm_general_register_operand" ""))
10189: (set (reg:CC CC_REGNUM)
10190: (compare:CC (match_dup 1) (const_int 0)))]
10191: "TARGET_ARM"
10192: [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10193: (set (match_dup 0) (match_dup 1))])]
10194: ""
10195: )
10196:
10197: (define_split
10198: [(set (match_operand:SI 0 "s_register_operand" "")
10199: (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10200: (const_int 0))
10201: (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10202: [(match_operand:SI 3 "s_register_operand" "")
10203: (match_operand:SI 4 "arm_rhs_operand" "")]))))
10204: (clobber (match_operand:SI 5 "s_register_operand" ""))]
10205: "TARGET_ARM"
10206: [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10207: (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10208: (match_dup 5)))]
10209: ""
10210: )
10211:
10212: ;; This split can be used because CC_Z mode implies that the following
10213: ;; branch will be an equality, or an unsigned inequality, so the sign
10214: ;; extension is not needed.
10215:
10216: (define_split
10217: [(set (reg:CC_Z CC_REGNUM)
10218: (compare:CC_Z
10219: (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10220: (const_int 24))
10221: (match_operand 1 "const_int_operand" "")))
10222: (clobber (match_scratch:SI 2 ""))]
10223: "TARGET_ARM
10224: && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10225: == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10226: [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10227: (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10228: "
10229: operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10230: "
10231: )
10232: ;; ??? Check the patterns above for Thumb-2 usefulness
10233:
10234: (define_expand "prologue"
10235: [(clobber (const_int 0))]
10236: "TARGET_EITHER"
10237: "if (TARGET_32BIT)
10238: arm_expand_prologue ();
10239: else
10240: thumb1_expand_prologue ();
10241: DONE;
10242: "
10243: )
10244:
10245: (define_expand "epilogue"
10246: [(clobber (const_int 0))]
10247: "TARGET_EITHER"
10248: "
10249: if (crtl->calls_eh_return)
1.3 mrg 10250: emit_insn (gen_force_register_use (gen_rtx_REG (Pmode, 2)));
1.1 mrg 10251: if (TARGET_THUMB1)
1.3 mrg 10252: {
10253: thumb1_expand_epilogue ();
10254: emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10255: gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10256: }
10257: else if (HAVE_return)
10258: {
10259: /* HAVE_return is testing for USE_RETURN_INSN (FALSE). Hence,
10260: no need for explicit testing again. */
10261: emit_jump_insn (gen_return ());
10262: }
10263: else if (TARGET_32BIT)
10264: {
10265: arm_expand_epilogue (true);
10266: }
1.1 mrg 10267: DONE;
10268: "
10269: )
10270:
10271: ;; Note - although unspec_volatile's USE all hard registers,
10272: ;; USEs are ignored after relaod has completed. Thus we need
10273: ;; to add an unspec of the link register to ensure that flow
10274: ;; does not think that it is unused by the sibcall branch that
10275: ;; will replace the standard function epilogue.
1.3 mrg 10276: (define_expand "sibcall_epilogue"
10277: [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_REGISTER_USE)
10278: (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10279: "TARGET_32BIT"
10280: "
10281: arm_expand_epilogue (false);
10282: DONE;
10283: "
1.1 mrg 10284: )
10285:
10286: (define_expand "eh_epilogue"
10287: [(use (match_operand:SI 0 "register_operand" ""))
10288: (use (match_operand:SI 1 "register_operand" ""))
10289: (use (match_operand:SI 2 "register_operand" ""))]
10290: "TARGET_EITHER"
10291: "
10292: {
10293: cfun->machine->eh_epilogue_sp_ofs = operands[1];
1.3 mrg 10294: if (!REG_P (operands[2]) || REGNO (operands[2]) != 2)
1.1 mrg 10295: {
10296: rtx ra = gen_rtx_REG (Pmode, 2);
10297:
10298: emit_move_insn (ra, operands[2]);
10299: operands[2] = ra;
10300: }
10301: /* This is a hack -- we may have crystalized the function type too
10302: early. */
10303: cfun->machine->func_type = 0;
10304: }"
10305: )
10306:
10307: ;; This split is only used during output to reduce the number of patterns
10308: ;; that need assembler instructions adding to them. We allowed the setting
10309: ;; of the conditions to be implicit during rtl generation so that
10310: ;; the conditional compare patterns would work. However this conflicts to
10311: ;; some extent with the conditional data operations, so we have to split them
10312: ;; up again here.
10313:
10314: ;; ??? Need to audit these splitters for Thumb-2. Why isn't normal
10315: ;; conditional execution sufficient?
10316:
10317: (define_split
10318: [(set (match_operand:SI 0 "s_register_operand" "")
10319: (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10320: [(match_operand 2 "" "") (match_operand 3 "" "")])
10321: (match_dup 0)
10322: (match_operand 4 "" "")))
10323: (clobber (reg:CC CC_REGNUM))]
10324: "TARGET_ARM && reload_completed"
10325: [(set (match_dup 5) (match_dup 6))
10326: (cond_exec (match_dup 7)
10327: (set (match_dup 0) (match_dup 4)))]
10328: "
10329: {
1.5 mrg 10330: machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
1.1 mrg 10331: operands[2], operands[3]);
10332: enum rtx_code rc = GET_CODE (operands[1]);
10333:
10334: operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10335: operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10336: if (mode == CCFPmode || mode == CCFPEmode)
10337: rc = reverse_condition_maybe_unordered (rc);
10338: else
10339: rc = reverse_condition (rc);
10340:
10341: operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10342: }"
10343: )
10344:
10345: (define_split
10346: [(set (match_operand:SI 0 "s_register_operand" "")
10347: (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10348: [(match_operand 2 "" "") (match_operand 3 "" "")])
10349: (match_operand 4 "" "")
10350: (match_dup 0)))
10351: (clobber (reg:CC CC_REGNUM))]
10352: "TARGET_ARM && reload_completed"
10353: [(set (match_dup 5) (match_dup 6))
10354: (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10355: (set (match_dup 0) (match_dup 4)))]
10356: "
10357: {
1.5 mrg 10358: machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
1.1 mrg 10359: operands[2], operands[3]);
10360:
10361: operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10362: operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10363: }"
10364: )
10365:
10366: (define_split
10367: [(set (match_operand:SI 0 "s_register_operand" "")
10368: (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10369: [(match_operand 2 "" "") (match_operand 3 "" "")])
10370: (match_operand 4 "" "")
10371: (match_operand 5 "" "")))
10372: (clobber (reg:CC CC_REGNUM))]
10373: "TARGET_ARM && reload_completed"
10374: [(set (match_dup 6) (match_dup 7))
10375: (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10376: (set (match_dup 0) (match_dup 4)))
10377: (cond_exec (match_dup 8)
10378: (set (match_dup 0) (match_dup 5)))]
10379: "
10380: {
1.5 mrg 10381: machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
1.1 mrg 10382: operands[2], operands[3]);
10383: enum rtx_code rc = GET_CODE (operands[1]);
10384:
10385: operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10386: operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10387: if (mode == CCFPmode || mode == CCFPEmode)
10388: rc = reverse_condition_maybe_unordered (rc);
10389: else
10390: rc = reverse_condition (rc);
10391:
10392: operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10393: }"
10394: )
10395:
10396: (define_split
10397: [(set (match_operand:SI 0 "s_register_operand" "")
10398: (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10399: [(match_operand:SI 2 "s_register_operand" "")
10400: (match_operand:SI 3 "arm_add_operand" "")])
10401: (match_operand:SI 4 "arm_rhs_operand" "")
10402: (not:SI
10403: (match_operand:SI 5 "s_register_operand" ""))))
10404: (clobber (reg:CC CC_REGNUM))]
10405: "TARGET_ARM && reload_completed"
10406: [(set (match_dup 6) (match_dup 7))
10407: (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10408: (set (match_dup 0) (match_dup 4)))
10409: (cond_exec (match_dup 8)
10410: (set (match_dup 0) (not:SI (match_dup 5))))]
10411: "
10412: {
1.5 mrg 10413: machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
1.1 mrg 10414: operands[2], operands[3]);
10415: enum rtx_code rc = GET_CODE (operands[1]);
10416:
10417: operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10418: operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10419: if (mode == CCFPmode || mode == CCFPEmode)
10420: rc = reverse_condition_maybe_unordered (rc);
10421: else
10422: rc = reverse_condition (rc);
10423:
10424: operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10425: }"
10426: )
10427:
10428: (define_insn "*cond_move_not"
10429: [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10430: (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10431: [(match_operand 3 "cc_register" "") (const_int 0)])
10432: (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10433: (not:SI
10434: (match_operand:SI 2 "s_register_operand" "r,r"))))]
10435: "TARGET_ARM"
10436: "@
10437: mvn%D4\\t%0, %2
10438: mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10439: [(set_attr "conds" "use")
1.5 mrg 10440: (set_attr "type" "mvn_reg,multiple")
1.1 mrg 10441: (set_attr "length" "4,8")]
10442: )
10443:
10444: ;; The next two patterns occur when an AND operation is followed by a
10445: ;; scc insn sequence
10446:
10447: (define_insn "*sign_extract_onebit"
10448: [(set (match_operand:SI 0 "s_register_operand" "=r")
10449: (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10450: (const_int 1)
10451: (match_operand:SI 2 "const_int_operand" "n")))
10452: (clobber (reg:CC CC_REGNUM))]
10453: "TARGET_ARM"
10454: "*
10455: operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10456: output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10457: return \"mvnne\\t%0, #0\";
10458: "
10459: [(set_attr "conds" "clob")
1.5 mrg 10460: (set_attr "length" "8")
10461: (set_attr "type" "multiple")]
1.1 mrg 10462: )
10463:
10464: (define_insn "*not_signextract_onebit"
10465: [(set (match_operand:SI 0 "s_register_operand" "=r")
10466: (not:SI
10467: (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10468: (const_int 1)
10469: (match_operand:SI 2 "const_int_operand" "n"))))
10470: (clobber (reg:CC CC_REGNUM))]
10471: "TARGET_ARM"
10472: "*
10473: operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10474: output_asm_insn (\"tst\\t%1, %2\", operands);
10475: output_asm_insn (\"mvneq\\t%0, #0\", operands);
10476: return \"movne\\t%0, #0\";
10477: "
10478: [(set_attr "conds" "clob")
1.5 mrg 10479: (set_attr "length" "12")
10480: (set_attr "type" "multiple")]
1.1 mrg 10481: )
10482: ;; ??? The above patterns need auditing for Thumb-2
10483:
10484: ;; Push multiple registers to the stack. Registers are in parallel (use ...)
10485: ;; expressions. For simplicity, the first register is also in the unspec
10486: ;; part.
1.3 mrg 10487: ;; To avoid the usage of GNU extension, the length attribute is computed
10488: ;; in a C function arm_attr_length_push_multi.
1.1 mrg 10489: (define_insn "*push_multi"
10490: [(match_parallel 2 "multi_register_push"
1.3 mrg 10491: [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
1.1 mrg 10492: (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10493: UNSPEC_PUSH_MULT))])]
1.3 mrg 10494: ""
1.1 mrg 10495: "*
10496: {
10497: int num_saves = XVECLEN (operands[2], 0);
10498:
10499: /* For the StrongARM at least it is faster to
10500: use STR to store only a single register.
10501: In Thumb mode always use push, and the assembler will pick
10502: something appropriate. */
10503: if (num_saves == 1 && TARGET_ARM)
1.3 mrg 10504: output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
1.1 mrg 10505: else
10506: {
10507: int i;
10508: char pattern[100];
10509:
1.7 ! mrg 10510: if (TARGET_32BIT)
1.3 mrg 10511: strcpy (pattern, \"push%?\\t{%1\");
1.1 mrg 10512: else
10513: strcpy (pattern, \"push\\t{%1\");
10514:
10515: for (i = 1; i < num_saves; i++)
10516: {
10517: strcat (pattern, \", %|\");
10518: strcat (pattern,
10519: reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10520: }
10521:
10522: strcat (pattern, \"}\");
10523: output_asm_insn (pattern, operands);
10524: }
10525:
10526: return \"\";
10527: }"
1.3 mrg 10528: [(set_attr "type" "store4")
10529: (set (attr "length")
10530: (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
1.1 mrg 10531: )
10532:
10533: (define_insn "stack_tie"
10534: [(set (mem:BLK (scratch))
10535: (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10536: (match_operand:SI 1 "s_register_operand" "rk")]
10537: UNSPEC_PRLG_STK))]
10538: ""
10539: ""
1.5 mrg 10540: [(set_attr "length" "0")
10541: (set_attr "type" "block")]
1.1 mrg 10542: )
10543:
1.3 mrg 10544: ;; Pop (as used in epilogue RTL)
10545: ;;
10546: (define_insn "*load_multiple_with_writeback"
10547: [(match_parallel 0 "load_multiple_operation"
10548: [(set (match_operand:SI 1 "s_register_operand" "+rk")
10549: (plus:SI (match_dup 1)
1.5 mrg 10550: (match_operand:SI 2 "const_int_I_operand" "I")))
1.3 mrg 10551: (set (match_operand:SI 3 "s_register_operand" "=rk")
10552: (mem:SI (match_dup 1)))
10553: ])]
10554: "TARGET_32BIT && (reload_in_progress || reload_completed)"
10555: "*
10556: {
10557: arm_output_multireg_pop (operands, /*return_pc=*/false,
10558: /*cond=*/const_true_rtx,
10559: /*reverse=*/false,
10560: /*update=*/true);
10561: return \"\";
10562: }
10563: "
10564: [(set_attr "type" "load4")
10565: (set_attr "predicable" "yes")]
10566: )
10567:
10568: ;; Pop with return (as used in epilogue RTL)
10569: ;;
10570: ;; This instruction is generated when the registers are popped at the end of
10571: ;; epilogue. Here, instead of popping the value into LR and then generating
10572: ;; jump to LR, value is popped into PC directly. Hence, the pattern is combined
10573: ;; with (return).
10574: (define_insn "*pop_multiple_with_writeback_and_return"
10575: [(match_parallel 0 "pop_multiple_return"
10576: [(return)
10577: (set (match_operand:SI 1 "s_register_operand" "+rk")
10578: (plus:SI (match_dup 1)
1.5 mrg 10579: (match_operand:SI 2 "const_int_I_operand" "I")))
1.3 mrg 10580: (set (match_operand:SI 3 "s_register_operand" "=rk")
10581: (mem:SI (match_dup 1)))
10582: ])]
10583: "TARGET_32BIT && (reload_in_progress || reload_completed)"
10584: "*
10585: {
10586: arm_output_multireg_pop (operands, /*return_pc=*/true,
10587: /*cond=*/const_true_rtx,
10588: /*reverse=*/false,
10589: /*update=*/true);
10590: return \"\";
10591: }
10592: "
10593: [(set_attr "type" "load4")
10594: (set_attr "predicable" "yes")]
10595: )
10596:
10597: (define_insn "*pop_multiple_with_return"
10598: [(match_parallel 0 "pop_multiple_return"
10599: [(return)
10600: (set (match_operand:SI 2 "s_register_operand" "=rk")
10601: (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
10602: ])]
10603: "TARGET_32BIT && (reload_in_progress || reload_completed)"
10604: "*
10605: {
10606: arm_output_multireg_pop (operands, /*return_pc=*/true,
10607: /*cond=*/const_true_rtx,
10608: /*reverse=*/false,
10609: /*update=*/false);
10610: return \"\";
10611: }
10612: "
10613: [(set_attr "type" "load4")
10614: (set_attr "predicable" "yes")]
10615: )
10616:
10617: ;; Load into PC and return
10618: (define_insn "*ldr_with_return"
10619: [(return)
10620: (set (reg:SI PC_REGNUM)
10621: (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+rk"))))]
10622: "TARGET_32BIT && (reload_in_progress || reload_completed)"
10623: "ldr%?\t%|pc, [%0], #4"
10624: [(set_attr "type" "load1")
10625: (set_attr "predicable" "yes")]
10626: )
10627: ;; Pop for floating point registers (as used in epilogue RTL)
10628: (define_insn "*vfp_pop_multiple_with_writeback"
10629: [(match_parallel 0 "pop_multiple_fp"
10630: [(set (match_operand:SI 1 "s_register_operand" "+rk")
10631: (plus:SI (match_dup 1)
1.5 mrg 10632: (match_operand:SI 2 "const_int_I_operand" "I")))
1.3 mrg 10633: (set (match_operand:DF 3 "vfp_hard_register_operand" "")
10634: (mem:DF (match_dup 1)))])]
10635: "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
1.1 mrg 10636: "*
10637: {
1.3 mrg 10638: int num_regs = XVECLEN (operands[0], 0);
1.1 mrg 10639: char pattern[100];
1.3 mrg 10640: rtx op_list[2];
1.5 mrg 10641: strcpy (pattern, \"vldm\\t\");
1.3 mrg 10642: strcat (pattern, reg_names[REGNO (SET_DEST (XVECEXP (operands[0], 0, 0)))]);
10643: strcat (pattern, \"!, {\");
10644: op_list[0] = XEXP (XVECEXP (operands[0], 0, 1), 0);
10645: strcat (pattern, \"%P0\");
10646: if ((num_regs - 1) > 1)
10647: {
10648: strcat (pattern, \"-%P1\");
10649: op_list [1] = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0);
10650: }
1.1 mrg 10651:
1.3 mrg 10652: strcat (pattern, \"}\");
10653: output_asm_insn (pattern, op_list);
1.1 mrg 10654: return \"\";
1.3 mrg 10655: }
10656: "
10657: [(set_attr "type" "load4")
10658: (set_attr "conds" "unconditional")
10659: (set_attr "predicable" "no")]
1.1 mrg 10660: )
10661:
10662: ;; Special patterns for dealing with the constant pool
10663:
10664: (define_insn "align_4"
10665: [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10666: "TARGET_EITHER"
10667: "*
10668: assemble_align (32);
10669: return \"\";
10670: "
1.5 mrg 10671: [(set_attr "type" "no_insn")]
1.1 mrg 10672: )
10673:
10674: (define_insn "align_8"
10675: [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10676: "TARGET_EITHER"
10677: "*
10678: assemble_align (64);
10679: return \"\";
10680: "
1.5 mrg 10681: [(set_attr "type" "no_insn")]
1.1 mrg 10682: )
10683:
10684: (define_insn "consttable_end"
10685: [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10686: "TARGET_EITHER"
10687: "*
10688: making_const_table = FALSE;
10689: return \"\";
10690: "
1.5 mrg 10691: [(set_attr "type" "no_insn")]
1.1 mrg 10692: )
10693:
10694: (define_insn "consttable_1"
10695: [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
1.3 mrg 10696: "TARGET_EITHER"
1.1 mrg 10697: "*
10698: making_const_table = TRUE;
10699: assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10700: assemble_zeros (3);
10701: return \"\";
10702: "
1.5 mrg 10703: [(set_attr "length" "4")
10704: (set_attr "type" "no_insn")]
1.1 mrg 10705: )
10706:
10707: (define_insn "consttable_2"
10708: [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
1.3 mrg 10709: "TARGET_EITHER"
1.1 mrg 10710: "*
1.3 mrg 10711: {
10712: rtx x = operands[0];
10713: making_const_table = TRUE;
10714: switch (GET_MODE_CLASS (GET_MODE (x)))
10715: {
10716: case MODE_FLOAT:
10717: arm_emit_fp16_const (x);
10718: break;
10719: default:
10720: assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10721: assemble_zeros (2);
10722: break;
10723: }
10724: return \"\";
10725: }"
1.5 mrg 10726: [(set_attr "length" "4")
10727: (set_attr "type" "no_insn")]
1.1 mrg 10728: )
10729:
10730: (define_insn "consttable_4"
10731: [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10732: "TARGET_EITHER"
10733: "*
10734: {
10735: rtx x = operands[0];
10736: making_const_table = TRUE;
10737: switch (GET_MODE_CLASS (GET_MODE (x)))
10738: {
10739: case MODE_FLOAT:
1.7 ! mrg 10740: assemble_real (*CONST_DOUBLE_REAL_VALUE (x), GET_MODE (x),
! 10741: BITS_PER_WORD);
! 10742: break;
1.1 mrg 10743: default:
10744: /* XXX: Sometimes gcc does something really dumb and ends up with
10745: a HIGH in a constant pool entry, usually because it's trying to
10746: load into a VFP register. We know this will always be used in
10747: combination with a LO_SUM which ignores the high bits, so just
10748: strip off the HIGH. */
10749: if (GET_CODE (x) == HIGH)
10750: x = XEXP (x, 0);
10751: assemble_integer (x, 4, BITS_PER_WORD, 1);
10752: mark_symbol_refs_as_used (x);
10753: break;
10754: }
10755: return \"\";
10756: }"
1.5 mrg 10757: [(set_attr "length" "4")
10758: (set_attr "type" "no_insn")]
1.1 mrg 10759: )
10760:
10761: (define_insn "consttable_8"
10762: [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10763: "TARGET_EITHER"
10764: "*
10765: {
10766: making_const_table = TRUE;
10767: switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10768: {
1.7 ! mrg 10769: case MODE_FLOAT:
! 10770: assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
! 10771: GET_MODE (operands[0]), BITS_PER_WORD);
! 10772: break;
1.1 mrg 10773: default:
10774: assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10775: break;
10776: }
10777: return \"\";
10778: }"
1.5 mrg 10779: [(set_attr "length" "8")
10780: (set_attr "type" "no_insn")]
1.1 mrg 10781: )
10782:
10783: (define_insn "consttable_16"
10784: [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
10785: "TARGET_EITHER"
10786: "*
10787: {
10788: making_const_table = TRUE;
10789: switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10790: {
1.7 ! mrg 10791: case MODE_FLOAT:
! 10792: assemble_real (*CONST_DOUBLE_REAL_VALUE (operands[0]),
! 10793: GET_MODE (operands[0]), BITS_PER_WORD);
! 10794: break;
1.1 mrg 10795: default:
10796: assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
10797: break;
10798: }
10799: return \"\";
10800: }"
1.5 mrg 10801: [(set_attr "length" "16")
10802: (set_attr "type" "no_insn")]
1.1 mrg 10803: )
10804:
10805: ;; V5 Instructions,
10806:
10807: (define_insn "clzsi2"
10808: [(set (match_operand:SI 0 "s_register_operand" "=r")
10809: (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10810: "TARGET_32BIT && arm_arch5"
10811: "clz%?\\t%0, %1"
10812: [(set_attr "predicable" "yes")
1.5 mrg 10813: (set_attr "predicable_short_it" "no")
10814: (set_attr "type" "clz")])
1.1 mrg 10815:
10816: (define_insn "rbitsi2"
10817: [(set (match_operand:SI 0 "s_register_operand" "=r")
10818: (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
10819: "TARGET_32BIT && arm_arch_thumb2"
10820: "rbit%?\\t%0, %1"
10821: [(set_attr "predicable" "yes")
1.5 mrg 10822: (set_attr "predicable_short_it" "no")
10823: (set_attr "type" "clz")])
1.1 mrg 10824:
10825: (define_expand "ctzsi2"
10826: [(set (match_operand:SI 0 "s_register_operand" "")
10827: (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10828: "TARGET_32BIT && arm_arch_thumb2"
10829: "
10830: {
10831: rtx tmp = gen_reg_rtx (SImode);
10832: emit_insn (gen_rbitsi2 (tmp, operands[1]));
10833: emit_insn (gen_clzsi2 (operands[0], tmp));
10834: }
10835: DONE;
10836: "
10837: )
10838:
10839: ;; V5E instructions.
10840:
10841: (define_insn "prefetch"
10842: [(prefetch (match_operand:SI 0 "address_operand" "p")
10843: (match_operand:SI 1 "" "")
10844: (match_operand:SI 2 "" ""))]
10845: "TARGET_32BIT && arm_arch5e"
1.3 mrg 10846: "pld\\t%a0"
10847: [(set_attr "type" "load1")]
10848: )
1.1 mrg 10849:
10850: ;; General predication pattern
10851:
10852: (define_cond_exec
10853: [(match_operator 0 "arm_comparison_operator"
10854: [(match_operand 1 "cc_register" "")
10855: (const_int 0)])]
1.5 mrg 10856: "TARGET_32BIT
10857: && (!TARGET_NO_VOLATILE_CE || !volatile_refs_p (PATTERN (insn)))"
1.1 mrg 10858: ""
1.5 mrg 10859: [(set_attr "predicated" "yes")]
1.1 mrg 10860: )
10861:
1.3 mrg 10862: (define_insn "force_register_use"
10863: [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_REGISTER_USE)]
1.1 mrg 10864: ""
1.3 mrg 10865: "%@ %0 needed"
1.5 mrg 10866: [(set_attr "length" "0")
10867: (set_attr "type" "no_insn")]
1.1 mrg 10868: )
10869:
10870:
10871: ;; Patterns for exception handling
10872:
10873: (define_expand "eh_return"
10874: [(use (match_operand 0 "general_operand" ""))]
10875: "TARGET_EITHER"
10876: "
10877: {
10878: if (TARGET_32BIT)
10879: emit_insn (gen_arm_eh_return (operands[0]));
10880: else
10881: emit_insn (gen_thumb_eh_return (operands[0]));
10882: DONE;
10883: }"
10884: )
10885:
10886: ;; We can't expand this before we know where the link register is stored.
10887: (define_insn_and_split "arm_eh_return"
10888: [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10889: VUNSPEC_EH_RETURN)
10890: (clobber (match_scratch:SI 1 "=&r"))]
10891: "TARGET_ARM"
10892: "#"
10893: "&& reload_completed"
10894: [(const_int 0)]
10895: "
10896: {
10897: arm_set_return_address (operands[0], operands[1]);
10898: DONE;
10899: }"
10900: )
10901:
10902:
10903: ;; TLS support
10904:
10905: (define_insn "load_tp_hard"
10906: [(set (match_operand:SI 0 "register_operand" "=r")
10907: (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10908: "TARGET_HARD_TP"
10909: "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
1.5 mrg 10910: [(set_attr "predicable" "yes")
10911: (set_attr "type" "mrs")]
1.1 mrg 10912: )
10913:
10914: ;; Doesn't clobber R1-R3. Must use r0 for the first operand.
10915: (define_insn "load_tp_soft"
10916: [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10917: (clobber (reg:SI LR_REGNUM))
10918: (clobber (reg:SI IP_REGNUM))
10919: (clobber (reg:CC CC_REGNUM))]
10920: "TARGET_SOFT_TP"
10921: "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
1.5 mrg 10922: [(set_attr "conds" "clob")
10923: (set_attr "type" "branch")]
1.1 mrg 10924: )
10925:
1.3 mrg 10926: ;; tls descriptor call
10927: (define_insn "tlscall"
10928: [(set (reg:SI R0_REGNUM)
10929: (unspec:SI [(reg:SI R0_REGNUM)
10930: (match_operand:SI 0 "" "X")
10931: (match_operand 1 "" "")] UNSPEC_TLS))
10932: (clobber (reg:SI R1_REGNUM))
10933: (clobber (reg:SI LR_REGNUM))
10934: (clobber (reg:SI CC_REGNUM))]
10935: "TARGET_GNU2_TLS"
10936: {
10937: targetm.asm_out.internal_label (asm_out_file, "LPIC",
10938: INTVAL (operands[1]));
10939: return "bl\\t%c0(tlscall)";
10940: }
10941: [(set_attr "conds" "clob")
1.5 mrg 10942: (set_attr "length" "4")
10943: (set_attr "type" "branch")]
1.3 mrg 10944: )
10945:
10946: ;; For thread pointer builtin
10947: (define_expand "get_thread_pointersi"
10948: [(match_operand:SI 0 "s_register_operand" "=r")]
10949: ""
10950: "
10951: {
10952: arm_load_tp (operands[0]);
10953: DONE;
10954: }")
10955:
10956: ;;
10957:
10958: ;; We only care about the lower 16 bits of the constant
10959: ;; being inserted into the upper 16 bits of the register.
1.1 mrg 10960: (define_insn "*arm_movtas_ze"
10961: [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
10962: (const_int 16)
10963: (const_int 16))
10964: (match_operand:SI 1 "const_int_operand" ""))]
10965: "arm_arch_thumb2"
1.3 mrg 10966: "movt%?\t%0, %L1"
1.1 mrg 10967: [(set_attr "predicable" "yes")
1.5 mrg 10968: (set_attr "predicable_short_it" "no")
10969: (set_attr "length" "4")
1.7 ! mrg 10970: (set_attr "type" "alu_sreg")]
1.1 mrg 10971: )
10972:
10973: (define_insn "*arm_rev"
1.3 mrg 10974: [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
10975: (bswap:SI (match_operand:SI 1 "s_register_operand" "l,l,r")))]
10976: "arm_arch6"
10977: "@
10978: rev\t%0, %1
10979: rev%?\t%0, %1
10980: rev%?\t%0, %1"
10981: [(set_attr "arch" "t1,t2,32")
1.5 mrg 10982: (set_attr "length" "2,2,4")
10983: (set_attr "predicable" "no,yes,yes")
10984: (set_attr "predicable_short_it" "no")
10985: (set_attr "type" "rev")]
1.1 mrg 10986: )
10987:
10988: (define_expand "arm_legacy_rev"
10989: [(set (match_operand:SI 2 "s_register_operand" "")
10990: (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
10991: (const_int 16))
10992: (match_dup 1)))
10993: (set (match_dup 2)
10994: (lshiftrt:SI (match_dup 2)
10995: (const_int 8)))
10996: (set (match_operand:SI 3 "s_register_operand" "")
10997: (rotatert:SI (match_dup 1)
10998: (const_int 8)))
10999: (set (match_dup 2)
11000: (and:SI (match_dup 2)
11001: (const_int -65281)))
11002: (set (match_operand:SI 0 "s_register_operand" "")
11003: (xor:SI (match_dup 3)
11004: (match_dup 2)))]
11005: "TARGET_32BIT"
11006: ""
11007: )
11008:
11009: ;; Reuse temporaries to keep register pressure down.
11010: (define_expand "thumb_legacy_rev"
11011: [(set (match_operand:SI 2 "s_register_operand" "")
11012: (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11013: (const_int 24)))
11014: (set (match_operand:SI 3 "s_register_operand" "")
11015: (lshiftrt:SI (match_dup 1)
11016: (const_int 24)))
11017: (set (match_dup 3)
11018: (ior:SI (match_dup 3)
11019: (match_dup 2)))
11020: (set (match_operand:SI 4 "s_register_operand" "")
11021: (const_int 16))
11022: (set (match_operand:SI 5 "s_register_operand" "")
11023: (rotatert:SI (match_dup 1)
11024: (match_dup 4)))
11025: (set (match_dup 2)
11026: (ashift:SI (match_dup 5)
11027: (const_int 24)))
11028: (set (match_dup 5)
11029: (lshiftrt:SI (match_dup 5)
11030: (const_int 24)))
11031: (set (match_dup 5)
11032: (ior:SI (match_dup 5)
11033: (match_dup 2)))
11034: (set (match_dup 5)
11035: (rotatert:SI (match_dup 5)
11036: (match_dup 4)))
11037: (set (match_operand:SI 0 "s_register_operand" "")
11038: (ior:SI (match_dup 5)
11039: (match_dup 3)))]
11040: "TARGET_THUMB"
11041: ""
11042: )
11043:
1.7 ! mrg 11044: ;; ARM-specific expansion of signed mod by power of 2
! 11045: ;; using conditional negate.
! 11046: ;; For r0 % n where n is a power of 2 produce:
! 11047: ;; rsbs r1, r0, #0
! 11048: ;; and r0, r0, #(n - 1)
! 11049: ;; and r1, r1, #(n - 1)
! 11050: ;; rsbpl r0, r1, #0
! 11051:
! 11052: (define_expand "modsi3"
! 11053: [(match_operand:SI 0 "register_operand" "")
! 11054: (match_operand:SI 1 "register_operand" "")
! 11055: (match_operand:SI 2 "const_int_operand" "")]
! 11056: "TARGET_32BIT"
! 11057: {
! 11058: HOST_WIDE_INT val = INTVAL (operands[2]);
! 11059:
! 11060: if (val <= 0
! 11061: || exact_log2 (val) <= 0)
! 11062: FAIL;
! 11063:
! 11064: rtx mask = GEN_INT (val - 1);
! 11065:
! 11066: /* In the special case of x0 % 2 we can do the even shorter:
! 11067: cmp r0, #0
! 11068: and r0, r0, #1
! 11069: rsblt r0, r0, #0. */
! 11070:
! 11071: if (val == 2)
! 11072: {
! 11073: rtx cc_reg = arm_gen_compare_reg (LT,
! 11074: operands[1], const0_rtx, NULL_RTX);
! 11075: rtx cond = gen_rtx_LT (SImode, cc_reg, const0_rtx);
! 11076: rtx masked = gen_reg_rtx (SImode);
! 11077:
! 11078: emit_insn (gen_andsi3 (masked, operands[1], mask));
! 11079: emit_move_insn (operands[0],
! 11080: gen_rtx_IF_THEN_ELSE (SImode, cond,
! 11081: gen_rtx_NEG (SImode,
! 11082: masked),
! 11083: masked));
! 11084: DONE;
! 11085: }
! 11086:
! 11087: rtx neg_op = gen_reg_rtx (SImode);
! 11088: rtx_insn *insn = emit_insn (gen_subsi3_compare0 (neg_op, const0_rtx,
! 11089: operands[1]));
! 11090:
! 11091: /* Extract the condition register and mode. */
! 11092: rtx cmp = XVECEXP (PATTERN (insn), 0, 0);
! 11093: rtx cc_reg = SET_DEST (cmp);
! 11094: rtx cond = gen_rtx_GE (SImode, cc_reg, const0_rtx);
! 11095:
! 11096: emit_insn (gen_andsi3 (operands[0], operands[1], mask));
! 11097:
! 11098: rtx masked_neg = gen_reg_rtx (SImode);
! 11099: emit_insn (gen_andsi3 (masked_neg, neg_op, mask));
! 11100:
! 11101: /* We want a conditional negate here, but emitting COND_EXEC rtxes
! 11102: during expand does not always work. Do an IF_THEN_ELSE instead. */
! 11103: emit_move_insn (operands[0],
! 11104: gen_rtx_IF_THEN_ELSE (SImode, cond,
! 11105: gen_rtx_NEG (SImode, masked_neg),
! 11106: operands[0]));
! 11107:
! 11108:
! 11109: DONE;
! 11110: }
! 11111: )
! 11112:
1.1 mrg 11113: (define_expand "bswapsi2"
11114: [(set (match_operand:SI 0 "s_register_operand" "=r")
11115: (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11116: "TARGET_EITHER && (arm_arch6 || !optimize_size)"
11117: "
11118: if (!arm_arch6)
11119: {
11120: rtx op2 = gen_reg_rtx (SImode);
11121: rtx op3 = gen_reg_rtx (SImode);
11122:
11123: if (TARGET_THUMB)
11124: {
11125: rtx op4 = gen_reg_rtx (SImode);
11126: rtx op5 = gen_reg_rtx (SImode);
11127:
11128: emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11129: op2, op3, op4, op5));
11130: }
11131: else
11132: {
11133: emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11134: op2, op3));
11135: }
11136:
11137: DONE;
11138: }
11139: "
11140: )
11141:
1.3 mrg 11142: ;; bswap16 patterns: use revsh and rev16 instructions for the signed
11143: ;; and unsigned variants, respectively. For rev16, expose
11144: ;; byte-swapping in the lower 16 bits only.
11145: (define_insn "*arm_revsh"
11146: [(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
11147: (sign_extend:SI (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r"))))]
11148: "arm_arch6"
11149: "@
11150: revsh\t%0, %1
11151: revsh%?\t%0, %1
11152: revsh%?\t%0, %1"
11153: [(set_attr "arch" "t1,t2,32")
1.5 mrg 11154: (set_attr "length" "2,2,4")
11155: (set_attr "type" "rev")]
1.3 mrg 11156: )
11157:
11158: (define_insn "*arm_rev16"
11159: [(set (match_operand:HI 0 "s_register_operand" "=l,l,r")
11160: (bswap:HI (match_operand:HI 1 "s_register_operand" "l,l,r")))]
11161: "arm_arch6"
11162: "@
11163: rev16\t%0, %1
11164: rev16%?\t%0, %1
11165: rev16%?\t%0, %1"
11166: [(set_attr "arch" "t1,t2,32")
1.5 mrg 11167: (set_attr "length" "2,2,4")
11168: (set_attr "type" "rev")]
11169: )
11170:
11171: ;; There are no canonicalisation rules for the position of the lshiftrt, ashift
11172: ;; operations within an IOR/AND RTX, therefore we have two patterns matching
11173: ;; each valid permutation.
11174:
11175: (define_insn "arm_rev16si2"
11176: [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11177: (ior:SI (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "l,l,r")
11178: (const_int 8))
11179: (match_operand:SI 3 "const_int_operand" "n,n,n"))
11180: (and:SI (lshiftrt:SI (match_dup 1)
11181: (const_int 8))
11182: (match_operand:SI 2 "const_int_operand" "n,n,n"))))]
11183: "arm_arch6
11184: && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11185: && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11186: "rev16\\t%0, %1"
11187: [(set_attr "arch" "t1,t2,32")
11188: (set_attr "length" "2,2,4")
11189: (set_attr "type" "rev")]
11190: )
11191:
11192: (define_insn "arm_rev16si2_alt"
11193: [(set (match_operand:SI 0 "register_operand" "=l,l,r")
11194: (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,l,r")
11195: (const_int 8))
11196: (match_operand:SI 2 "const_int_operand" "n,n,n"))
11197: (and:SI (ashift:SI (match_dup 1)
11198: (const_int 8))
11199: (match_operand:SI 3 "const_int_operand" "n,n,n"))))]
11200: "arm_arch6
11201: && aarch_rev16_shleft_mask_imm_p (operands[3], SImode)
11202: && aarch_rev16_shright_mask_imm_p (operands[2], SImode)"
11203: "rev16\\t%0, %1"
11204: [(set_attr "arch" "t1,t2,32")
11205: (set_attr "length" "2,2,4")
11206: (set_attr "type" "rev")]
1.3 mrg 11207: )
11208:
11209: (define_expand "bswaphi2"
11210: [(set (match_operand:HI 0 "s_register_operand" "=r")
11211: (bswap:HI (match_operand:HI 1 "s_register_operand" "r")))]
11212: "arm_arch6"
11213: ""
11214: )
11215:
11216: ;; Patterns for LDRD/STRD in Thumb2 mode
11217:
11218: (define_insn "*thumb2_ldrd"
11219: [(set (match_operand:SI 0 "s_register_operand" "=r")
11220: (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11221: (match_operand:SI 2 "ldrd_strd_offset_operand" "Do"))))
11222: (set (match_operand:SI 3 "s_register_operand" "=r")
11223: (mem:SI (plus:SI (match_dup 1)
11224: (match_operand:SI 4 "const_int_operand" ""))))]
11225: "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11226: && current_tune->prefer_ldrd_strd
11227: && ((INTVAL (operands[2]) + 4) == INTVAL (operands[4]))
11228: && (operands_ok_ldrd_strd (operands[0], operands[3],
11229: operands[1], INTVAL (operands[2]),
11230: false, true))"
11231: "ldrd%?\t%0, %3, [%1, %2]"
11232: [(set_attr "type" "load2")
1.5 mrg 11233: (set_attr "predicable" "yes")
11234: (set_attr "predicable_short_it" "no")])
1.3 mrg 11235:
11236: (define_insn "*thumb2_ldrd_base"
11237: [(set (match_operand:SI 0 "s_register_operand" "=r")
11238: (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11239: (set (match_operand:SI 2 "s_register_operand" "=r")
11240: (mem:SI (plus:SI (match_dup 1)
11241: (const_int 4))))]
11242: "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11243: && current_tune->prefer_ldrd_strd
11244: && (operands_ok_ldrd_strd (operands[0], operands[2],
11245: operands[1], 0, false, true))"
11246: "ldrd%?\t%0, %2, [%1]"
11247: [(set_attr "type" "load2")
1.5 mrg 11248: (set_attr "predicable" "yes")
11249: (set_attr "predicable_short_it" "no")])
1.3 mrg 11250:
11251: (define_insn "*thumb2_ldrd_base_neg"
11252: [(set (match_operand:SI 0 "s_register_operand" "=r")
11253: (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
11254: (const_int -4))))
11255: (set (match_operand:SI 2 "s_register_operand" "=r")
11256: (mem:SI (match_dup 1)))]
11257: "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11258: && current_tune->prefer_ldrd_strd
11259: && (operands_ok_ldrd_strd (operands[0], operands[2],
11260: operands[1], -4, false, true))"
11261: "ldrd%?\t%0, %2, [%1, #-4]"
11262: [(set_attr "type" "load2")
1.5 mrg 11263: (set_attr "predicable" "yes")
11264: (set_attr "predicable_short_it" "no")])
1.3 mrg 11265:
11266: (define_insn "*thumb2_strd"
11267: [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11268: (match_operand:SI 1 "ldrd_strd_offset_operand" "Do")))
11269: (match_operand:SI 2 "s_register_operand" "r"))
11270: (set (mem:SI (plus:SI (match_dup 0)
11271: (match_operand:SI 3 "const_int_operand" "")))
11272: (match_operand:SI 4 "s_register_operand" "r"))]
11273: "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11274: && current_tune->prefer_ldrd_strd
11275: && ((INTVAL (operands[1]) + 4) == INTVAL (operands[3]))
11276: && (operands_ok_ldrd_strd (operands[2], operands[4],
11277: operands[0], INTVAL (operands[1]),
11278: false, false))"
11279: "strd%?\t%2, %4, [%0, %1]"
11280: [(set_attr "type" "store2")
1.5 mrg 11281: (set_attr "predicable" "yes")
11282: (set_attr "predicable_short_it" "no")])
1.3 mrg 11283:
11284: (define_insn "*thumb2_strd_base"
11285: [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk"))
11286: (match_operand:SI 1 "s_register_operand" "r"))
11287: (set (mem:SI (plus:SI (match_dup 0)
11288: (const_int 4)))
11289: (match_operand:SI 2 "s_register_operand" "r"))]
11290: "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11291: && current_tune->prefer_ldrd_strd
11292: && (operands_ok_ldrd_strd (operands[1], operands[2],
11293: operands[0], 0, false, false))"
11294: "strd%?\t%1, %2, [%0]"
11295: [(set_attr "type" "store2")
1.5 mrg 11296: (set_attr "predicable" "yes")
11297: (set_attr "predicable_short_it" "no")])
1.3 mrg 11298:
11299: (define_insn "*thumb2_strd_base_neg"
11300: [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk")
11301: (const_int -4)))
11302: (match_operand:SI 1 "s_register_operand" "r"))
11303: (set (mem:SI (match_dup 0))
11304: (match_operand:SI 2 "s_register_operand" "r"))]
11305: "TARGET_LDRD && TARGET_THUMB2 && reload_completed
11306: && current_tune->prefer_ldrd_strd
11307: && (operands_ok_ldrd_strd (operands[1], operands[2],
11308: operands[0], -4, false, false))"
11309: "strd%?\t%1, %2, [%0, #-4]"
11310: [(set_attr "type" "store2")
1.5 mrg 11311: (set_attr "predicable" "yes")
11312: (set_attr "predicable_short_it" "no")])
11313:
11314: ;; ARMv8 CRC32 instructions.
11315: (define_insn "<crc_variant>"
11316: [(set (match_operand:SI 0 "s_register_operand" "=r")
11317: (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")
11318: (match_operand:<crc_mode> 2 "s_register_operand" "r")]
11319: CRC))]
11320: "TARGET_CRC32"
11321: "<crc_variant>\\t%0, %1, %2"
11322: [(set_attr "type" "crc")
11323: (set_attr "conds" "unconditional")]
11324: )
1.3 mrg 11325:
1.5 mrg 11326: ;; Load the load/store double peephole optimizations.
11327: (include "ldrdstrd.md")
1.3 mrg 11328:
11329: ;; Load the load/store multiple patterns
11330: (include "ldmstm.md")
11331:
11332: ;; Patterns in ldmstm.md don't cover more than 4 registers. This pattern covers
11333: ;; large lists without explicit writeback generated for APCS_FRAME epilogue.
11334: (define_insn "*load_multiple"
11335: [(match_parallel 0 "load_multiple_operation"
11336: [(set (match_operand:SI 2 "s_register_operand" "=rk")
11337: (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
11338: ])]
11339: "TARGET_32BIT"
11340: "*
11341: {
11342: arm_output_multireg_pop (operands, /*return_pc=*/false,
11343: /*cond=*/const_true_rtx,
11344: /*reverse=*/false,
11345: /*update=*/false);
11346: return \"\";
11347: }
11348: "
11349: [(set_attr "predicable" "yes")]
11350: )
11351:
1.5 mrg 11352: (define_expand "copysignsf3"
11353: [(match_operand:SF 0 "register_operand")
11354: (match_operand:SF 1 "register_operand")
11355: (match_operand:SF 2 "register_operand")]
11356: "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11357: "{
11358: emit_move_insn (operands[0], operands[2]);
11359: emit_insn (gen_insv_t2 (simplify_gen_subreg (SImode, operands[0], SFmode, 0),
11360: GEN_INT (31), GEN_INT (0),
11361: simplify_gen_subreg (SImode, operands[1], SFmode, 0)));
11362: DONE;
11363: }"
11364: )
11365:
11366: (define_expand "copysigndf3"
11367: [(match_operand:DF 0 "register_operand")
11368: (match_operand:DF 1 "register_operand")
11369: (match_operand:DF 2 "register_operand")]
11370: "TARGET_SOFT_FLOAT && arm_arch_thumb2"
11371: "{
11372: rtx op0_low = gen_lowpart (SImode, operands[0]);
11373: rtx op0_high = gen_highpart (SImode, operands[0]);
11374: rtx op1_low = gen_lowpart (SImode, operands[1]);
11375: rtx op1_high = gen_highpart (SImode, operands[1]);
11376: rtx op2_high = gen_highpart (SImode, operands[2]);
11377:
11378: rtx scratch1 = gen_reg_rtx (SImode);
11379: rtx scratch2 = gen_reg_rtx (SImode);
11380: emit_move_insn (scratch1, op2_high);
11381: emit_move_insn (scratch2, op1_high);
11382:
1.7 ! mrg 11383: emit_insn(gen_rtx_SET(scratch1,
1.5 mrg 11384: gen_rtx_LSHIFTRT (SImode, op2_high, GEN_INT(31))));
11385: emit_insn(gen_insv_t2(scratch2, GEN_INT(1), GEN_INT(31), scratch1));
11386: emit_move_insn (op0_low, op1_low);
11387: emit_move_insn (op0_high, scratch2);
11388:
11389: DONE;
11390: }"
11391: )
11392:
1.7 ! mrg 11393: ;; movmisalign patterns for HImode and SImode.
! 11394: (define_expand "movmisalign<mode>"
! 11395: [(match_operand:HSI 0 "general_operand")
! 11396: (match_operand:HSI 1 "general_operand")]
! 11397: "unaligned_access"
! 11398: {
! 11399: /* This pattern is not permitted to fail during expansion: if both arguments
! 11400: are non-registers (e.g. memory := constant), force operand 1 into a
! 11401: register. */
! 11402: rtx (* gen_unaligned_load)(rtx, rtx);
! 11403: rtx tmp_dest = operands[0];
! 11404: if (!s_register_operand (operands[0], <MODE>mode)
! 11405: && !s_register_operand (operands[1], <MODE>mode))
! 11406: operands[1] = force_reg (<MODE>mode, operands[1]);
! 11407:
! 11408: if (<MODE>mode == HImode)
! 11409: {
! 11410: gen_unaligned_load = gen_unaligned_loadhiu;
! 11411: tmp_dest = gen_reg_rtx (SImode);
! 11412: }
! 11413: else
! 11414: gen_unaligned_load = gen_unaligned_loadsi;
! 11415:
! 11416: if (MEM_P (operands[1]))
! 11417: {
! 11418: emit_insn (gen_unaligned_load (tmp_dest, operands[1]));
! 11419: if (<MODE>mode == HImode)
! 11420: emit_move_insn (operands[0], gen_lowpart (HImode, tmp_dest));
! 11421: }
! 11422: else
! 11423: emit_insn (gen_unaligned_store<mode> (operands[0], operands[1]));
! 11424:
! 11425: DONE;
! 11426: })
! 11427:
1.1 mrg 11428: ;; Vector bits common to IWMMXT and Neon
11429: (include "vec-common.md")
11430: ;; Load the Intel Wireless Multimedia Extension patterns
11431: (include "iwmmxt.md")
11432: ;; Load the VFP co-processor patterns
11433: (include "vfp.md")
1.5 mrg 11434: ;; Thumb-1 patterns
11435: (include "thumb1.md")
1.1 mrg 11436: ;; Thumb-2 patterns
11437: (include "thumb2.md")
11438: ;; Neon patterns
11439: (include "neon.md")
1.5 mrg 11440: ;; Crypto patterns
11441: (include "crypto.md")
1.3 mrg 11442: ;; Synchronization Primitives
11443: (include "sync.md")
11444: ;; Fixed-point patterns
11445: (include "arm-fixed.md")
CVSweb <webmaster@jp.NetBSD.org>