OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [config/] [arm/] [arm.md] - Blame information for rev 713

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 709 jeremybenn
;;- Machine description for ARM for GNU compiler
2
;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3
;;  2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4
;;  Free Software Foundation, Inc.
5
;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
6
;;  and Martin Simmons (@harleqn.co.uk).
7
;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8
 
9
;; This file is part of GCC.
10
 
11
;; GCC is free software; you can redistribute it and/or modify it
12
;; under the terms of the GNU General Public License as published
13
;; by the Free Software Foundation; either version 3, or (at your
14
;; option) any later version.
15
 
16
;; GCC is distributed in the hope that it will be useful, but WITHOUT
17
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19
;; License for more details.
20
 
21
;; You should have received a copy of the GNU General Public License
22
;; along with GCC; see the file COPYING3.  If not see
23
;; .
24
 
25
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
 
27
 
28
;;---------------------------------------------------------------------------
29
;; Constants
30
 
31
;; Register numbers
32
(define_constants
33
  [(R0_REGNUM        0)         ; First CORE register
34
   (R1_REGNUM        1)         ; Second CORE register
35
   (IP_REGNUM       12)         ; Scratch register
36
   (SP_REGNUM       13)         ; Stack pointer
37
   (LR_REGNUM       14)         ; Return address register
38
   (PC_REGNUM       15)         ; Program counter
39
   (CC_REGNUM       24)         ; Condition code pseudo register
40
   (LAST_ARM_REGNUM 15)         ;
41
   (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
42
   (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
43
  ]
44
)
45
;; 3rd operand to select_dominance_cc_mode
46
(define_constants
47
  [(DOM_CC_X_AND_Y  0)
48
   (DOM_CC_NX_OR_Y  1)
49
   (DOM_CC_X_OR_Y   2)
50
  ]
51
)
52
;; conditional compare combination
53
(define_constants
54
  [(CMP_CMP 0)
55
   (CMN_CMP 1)
56
   (CMP_CMN 2)
57
   (CMN_CMN 3)
58
   (NUM_OF_COND_CMP 4)
59
  ]
60
)
61
 
62
;; UNSPEC Usage:
63
;; Note: sin and cos are no-longer used.
64
;; Unspec enumerators for Neon are defined in neon.md.
65
 
66
(define_c_enum "unspec" [
67
  UNSPEC_SIN            ; `sin' operation (MODE_FLOAT):
68
                        ;   operand 0 is the result,
69
                        ;   operand 1 the parameter.
70
  UNPSEC_COS            ; `cos' operation (MODE_FLOAT):
71
                        ;   operand 0 is the result,
72
                        ;   operand 1 the parameter.
73
  UNSPEC_PUSH_MULT      ; `push multiple' operation:
74
                        ;   operand 0 is the first register,
75
                        ;   subsequent registers are in parallel (use ...)
76
                        ;   expressions.
77
  UNSPEC_PIC_SYM        ; A symbol that has been treated properly for pic
78
                        ; usage, that is, we will add the pic_register
79
                        ; value to it before trying to dereference it.
80
  UNSPEC_PIC_BASE       ; Add PC and all but the last operand together,
81
                        ; The last operand is the number of a PIC_LABEL
82
                        ; that points at the containing instruction.
83
  UNSPEC_PRLG_STK       ; A special barrier that prevents frame accesses
84
                        ; being scheduled before the stack adjustment insn.
85
  UNSPEC_PROLOGUE_USE   ; As USE insns are not meaningful after reload,
86
                        ; this unspec is used to prevent the deletion of
87
                        ; instructions setting registers for EH handling
88
                        ; and stack frame generation.  Operand 0 is the
89
                        ; register to "use".
90
  UNSPEC_CHECK_ARCH     ; Set CCs to indicate 26-bit or 32-bit mode.
91
  UNSPEC_WSHUFH         ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
92
  UNSPEC_WACC           ; Used by the intrinsic form of the iWMMXt WACC instruction.
93
  UNSPEC_TMOVMSK        ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
94
  UNSPEC_WSAD           ; Used by the intrinsic form of the iWMMXt WSAD instruction.
95
  UNSPEC_WSADZ          ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
96
  UNSPEC_WMACS          ; Used by the intrinsic form of the iWMMXt WMACS instruction.
97
  UNSPEC_WMACU          ; Used by the intrinsic form of the iWMMXt WMACU instruction.
98
  UNSPEC_WMACSZ         ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
99
  UNSPEC_WMACUZ         ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
100
  UNSPEC_CLRDI          ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
101
  UNSPEC_WMADDS         ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
102
  UNSPEC_WMADDU         ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
103
  UNSPEC_TLS            ; A symbol that has been treated properly for TLS usage.
104
  UNSPEC_PIC_LABEL      ; A label used for PIC access that does not appear in the
105
                        ; instruction stream.
106
  UNSPEC_PIC_OFFSET     ; A symbolic 12-bit OFFSET that has been treated
107
                        ; correctly for PIC usage.
108
  UNSPEC_GOTSYM_OFF     ; The offset of the start of the GOT from a
109
                        ; a given symbolic address.
110
  UNSPEC_THUMB1_CASESI  ; A Thumb1 compressed dispatch-table call.
111
  UNSPEC_RBIT           ; rbit operation.
112
  UNSPEC_SYMBOL_OFFSET  ; The offset of the start of the symbol from
113
                        ; another symbolic address.
114
  UNSPEC_MEMORY_BARRIER ; Represent a memory barrier.
115
  UNSPEC_UNALIGNED_LOAD ; Used to represent ldr/ldrh instructions that access
116
                        ; unaligned locations, on architectures which support
117
                        ; that.
118
  UNSPEC_UNALIGNED_STORE ; Same for str/strh.
119
  UNSPEC_PIC_UNIFIED    ; Create a common pic addressing form.
120
])
121
 
122
;; UNSPEC_VOLATILE Usage:
123
 
124
(define_c_enum "unspecv" [
125
  VUNSPEC_BLOCKAGE      ; `blockage' insn to prevent scheduling across an
126
                        ;   insn in the code.
127
  VUNSPEC_EPILOGUE      ; `epilogue' insn, used to represent any part of the
128
                        ;   instruction epilogue sequence that isn't expanded
129
                        ;   into normal RTL.  Used for both normal and sibcall
130
                        ;   epilogues.
131
  VUNSPEC_THUMB1_INTERWORK ; `prologue_thumb1_interwork' insn, used to swap
132
                        ;   modes from arm to thumb.
133
  VUNSPEC_ALIGN         ; `align' insn.  Used at the head of a minipool table
134
                        ;   for inlined constants.
135
  VUNSPEC_POOL_END      ; `end-of-table'.  Used to mark the end of a minipool
136
                        ;   table.
137
  VUNSPEC_POOL_1        ; `pool-entry(1)'.  An entry in the constant pool for
138
                        ;   an 8-bit object.
139
  VUNSPEC_POOL_2        ; `pool-entry(2)'.  An entry in the constant pool for
140
                        ;   a 16-bit object.
141
  VUNSPEC_POOL_4        ; `pool-entry(4)'.  An entry in the constant pool for
142
                        ;   a 32-bit object.
143
  VUNSPEC_POOL_8        ; `pool-entry(8)'.  An entry in the constant pool for
144
                        ;   a 64-bit object.
145
  VUNSPEC_POOL_16       ; `pool-entry(16)'.  An entry in the constant pool for
146
                        ;   a 128-bit object.
147
  VUNSPEC_TMRC          ; Used by the iWMMXt TMRC instruction.
148
  VUNSPEC_TMCR          ; Used by the iWMMXt TMCR instruction.
149
  VUNSPEC_ALIGN8        ; 8-byte alignment version of VUNSPEC_ALIGN
150
  VUNSPEC_WCMP_EQ       ; Used by the iWMMXt WCMPEQ instructions
151
  VUNSPEC_WCMP_GTU      ; Used by the iWMMXt WCMPGTU instructions
152
  VUNSPEC_WCMP_GT       ; Used by the iwMMXT WCMPGT instructions
153
  VUNSPEC_EH_RETURN     ; Use to override the return address for exception
154
                        ; handling.
155
  VUNSPEC_ATOMIC_CAS    ; Represent an atomic compare swap.
156
  VUNSPEC_ATOMIC_XCHG   ; Represent an atomic exchange.
157
  VUNSPEC_ATOMIC_OP     ; Represent an atomic operation.
158
  VUNSPEC_LL            ; Represent a load-register-exclusive.
159
  VUNSPEC_SC            ; Represent a store-register-exclusive.
160
])
161
 
162
;;---------------------------------------------------------------------------
163
;; Attributes
164
 
165
;; Processor type.  This is created automatically from arm-cores.def.
166
(include "arm-tune.md")
167
 
168
; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
169
; generating ARM code.  This is used to control the length of some insn
170
; patterns that share the same RTL in both ARM and Thumb code.
171
(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
172
 
173
; IS_ARCH6 is set to 'yes' when we are generating code form ARMv6.
174
(define_attr "is_arch6" "no,yes" (const (symbol_ref "arm_arch6")))
175
 
176
; IS_THUMB1 is set to 'yes' iff we are generating Thumb-1 code.
177
(define_attr "is_thumb1" "no,yes" (const (symbol_ref "thumb1_code")))
178
 
179
;; Operand number of an input operand that is shifted.  Zero if the
180
;; given instruction does not shift one of its input operands.
181
(define_attr "shift" "" (const_int 0))
182
 
183
; Floating Point Unit.  If we only have floating point emulation, then there
184
; is no point in scheduling the floating point insns.  (Well, for best
185
; performance we should try and group them together).
186
(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
187
  (const (symbol_ref "arm_fpu_attr")))
188
 
189
; LENGTH of an instruction (in bytes)
190
(define_attr "length" ""
191
  (const_int 4))
192
 
193
; The architecture which supports the instruction (or alternative).
194
; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
195
; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode.  "v6"
196
; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
197
; arm_arch6.  This attribute is used to compute attribute "enabled",
198
; use type "any" to enable an alternative in all cases.
199
(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,onlya8,nota8"
200
  (const_string "any"))
201
 
202
(define_attr "arch_enabled" "no,yes"
203
  (cond [(eq_attr "arch" "any")
204
         (const_string "yes")
205
 
206
         (and (eq_attr "arch" "a")
207
              (match_test "TARGET_ARM"))
208
         (const_string "yes")
209
 
210
         (and (eq_attr "arch" "t")
211
              (match_test "TARGET_THUMB"))
212
         (const_string "yes")
213
 
214
         (and (eq_attr "arch" "t1")
215
              (match_test "TARGET_THUMB1"))
216
         (const_string "yes")
217
 
218
         (and (eq_attr "arch" "t2")
219
              (match_test "TARGET_THUMB2"))
220
         (const_string "yes")
221
 
222
         (and (eq_attr "arch" "32")
223
              (match_test "TARGET_32BIT"))
224
         (const_string "yes")
225
 
226
         (and (eq_attr "arch" "v6")
227
              (match_test "TARGET_32BIT && arm_arch6"))
228
         (const_string "yes")
229
 
230
         (and (eq_attr "arch" "nov6")
231
              (match_test "TARGET_32BIT && !arm_arch6"))
232
         (const_string "yes")
233
 
234
         (and (eq_attr "arch" "onlya8")
235
              (eq_attr "tune" "cortexa8"))
236
         (const_string "yes")
237
 
238
         (and (eq_attr "arch" "nota8")
239
              (not (eq_attr "tune" "cortexa8")))
240
         (const_string "yes")]
241
        (const_string "no")))
242
 
243
; Allows an insn to disable certain alternatives for reasons other than
244
; arch support.
245
(define_attr "insn_enabled" "no,yes"
246
  (const_string "yes"))
247
 
248
; Enable all alternatives that are both arch_enabled and insn_enabled.
249
 (define_attr "enabled" "no,yes"
250
   (if_then_else (eq_attr "insn_enabled" "yes")
251
               (if_then_else (eq_attr "arch_enabled" "yes")
252
                             (const_string "yes")
253
                             (const_string "no"))
254
                (const_string "no")))
255
 
256
; POOL_RANGE is how far away from a constant pool entry that this insn
257
; can be placed.  If the distance is zero, then this insn will never
258
; reference the pool.
259
; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
260
; before its address.  It is set to  - (8 + ).
261
(define_attr "arm_pool_range" "" (const_int 0))
262
(define_attr "thumb2_pool_range" "" (const_int 0))
263
(define_attr "arm_neg_pool_range" "" (const_int 0))
264
(define_attr "thumb2_neg_pool_range" "" (const_int 0))
265
 
266
(define_attr "pool_range" ""
267
  (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_pool_range")]
268
        (attr "arm_pool_range")))
269
(define_attr "neg_pool_range" ""
270
  (cond [(eq_attr "is_thumb" "yes") (attr "thumb2_neg_pool_range")]
271
        (attr "arm_neg_pool_range")))
272
 
273
; An assembler sequence may clobber the condition codes without us knowing.
274
; If such an insn references the pool, then we have no way of knowing how,
275
; so use the most conservative value for pool_range.
276
(define_asm_attributes
277
 [(set_attr "conds" "clob")
278
  (set_attr "length" "4")
279
  (set_attr "pool_range" "250")])
280
 
281
;; The instruction used to implement a particular pattern.  This
282
;; information is used by pipeline descriptions to provide accurate
283
;; scheduling information.
284
 
285
(define_attr "insn"
286
        "mov,mvn,smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,smmla,umaal,smlald,smlsld,clz,mrs,msr,xtab,sdiv,udiv,other"
287
        (const_string "other"))
288
 
289
; TYPE attribute is used to detect floating point instructions which, if
290
; running on a co-processor can run in parallel with other, basic instructions
291
; If write-buffer scheduling is enabled then it can also be used in the
292
; scheduling of writes.
293
 
294
; Classification of each insn
295
; Note: vfp.md has different meanings for some of these, and some further
296
; types as well.  See that file for details.
297
; alu           any alu  instruction that doesn't hit memory or fp
298
;               regs or have a shifted source operand
299
; alu_shift     any data instruction that doesn't hit memory or fp
300
;               regs, but has a source operand shifted by a constant
301
; alu_shift_reg any data instruction that doesn't hit memory or fp
302
;               regs, but has a source operand shifted by a register value
303
; mult          a multiply instruction
304
; block         blockage insn, this blocks all functional units
305
; float         a floating point arithmetic operation (subject to expansion)
306
; fdivd         DFmode floating point division
307
; fdivs         SFmode floating point division
308
; fmul          Floating point multiply
309
; ffmul         Fast floating point multiply
310
; farith        Floating point arithmetic (4 cycle)
311
; ffarith       Fast floating point arithmetic (2 cycle)
312
; float_em      a floating point arithmetic operation that is normally emulated
313
;               even on a machine with an fpa.
314
; f_fpa_load    a floating point load from memory. Only for the FPA.
315
; f_fpa_store   a floating point store to memory. Only for the FPA.
316
; f_load[sd]    A single/double load from memory. Used for VFP unit.
317
; f_store[sd]   A single/double store to memory. Used for VFP unit.
318
; f_flag        a transfer of co-processor flags to the CPSR
319
; f_mem_r       a transfer of a floating point register to a real reg via mem
320
; r_mem_f       the reverse of f_mem_r
321
; f_2_r         fast transfer float to arm (no memory needed)
322
; r_2_f         fast transfer arm to float
323
; f_cvt         convert floating<->integral
324
; branch        a branch
325
; call          a subroutine call
326
; load_byte     load byte(s) from memory to arm registers
327
; load1         load 1 word from memory to arm registers
328
; load2         load 2 words from memory to arm registers
329
; load3         load 3 words from memory to arm registers
330
; load4         load 4 words from memory to arm registers
331
; store         store 1 word to memory from arm registers
332
; store2        store 2 words
333
; store3        store 3 words
334
; store4        store 4 (or more) words
335
;  Additions for Cirrus Maverick co-processor:
336
; mav_farith    Floating point arithmetic (4 cycle)
337
; mav_dmult     Double multiplies (7 cycle)
338
;
339
 
340
(define_attr "type"
341
        "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,fmuls,fmuld,fmacs,fmacd,ffmul,farith,ffarith,f_flag,float_em,f_fpa_load,f_fpa_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult,fconsts,fconstd,fadds,faddd,ffariths,ffarithd,fcmps,fcmpd,fcpys"
342
        (if_then_else
343
         (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
344
         (const_string "mult")
345
         (const_string "alu")))
346
 
347
; Is this an (integer side) multiply with a 64-bit result?
348
(define_attr "mul64" "no,yes"
349
             (if_then_else
350
               (eq_attr "insn" "smlalxy,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
351
               (const_string "yes")
352
               (const_string "no")))
353
 
354
; Load scheduling, set from the arm_ld_sched variable
355
; initialized by arm_option_override()
356
(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
357
 
358
;; Classification of NEON instructions for scheduling purposes.
359
;; Do not set this attribute and the "type" attribute together in
360
;; any one instruction pattern.
361
(define_attr "neon_type"
362
   "neon_int_1,\
363
   neon_int_2,\
364
   neon_int_3,\
365
   neon_int_4,\
366
   neon_int_5,\
367
   neon_vqneg_vqabs,\
368
   neon_vmov,\
369
   neon_vaba,\
370
   neon_vsma,\
371
   neon_vaba_qqq,\
372
   neon_mul_ddd_8_16_qdd_16_8_long_32_16_long,\
373
   neon_mul_qqq_8_16_32_ddd_32,\
374
   neon_mul_qdd_64_32_long_qqd_16_ddd_32_scalar_64_32_long_scalar,\
375
   neon_mla_ddd_8_16_qdd_16_8_long_32_16_long,\
376
   neon_mla_qqq_8_16,\
377
   neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long,\
378
   neon_mla_qqq_32_qqd_32_scalar,\
379
   neon_mul_ddd_16_scalar_32_16_long_scalar,\
380
   neon_mul_qqd_32_scalar,\
381
   neon_mla_ddd_16_scalar_qdd_32_16_long_scalar,\
382
   neon_shift_1,\
383
   neon_shift_2,\
384
   neon_shift_3,\
385
   neon_vshl_ddd,\
386
   neon_vqshl_vrshl_vqrshl_qqq,\
387
   neon_vsra_vrsra,\
388
   neon_fp_vadd_ddd_vabs_dd,\
389
   neon_fp_vadd_qqq_vabs_qq,\
390
   neon_fp_vsum,\
391
   neon_fp_vmul_ddd,\
392
   neon_fp_vmul_qqd,\
393
   neon_fp_vmla_ddd,\
394
   neon_fp_vmla_qqq,\
395
   neon_fp_vmla_ddd_scalar,\
396
   neon_fp_vmla_qqq_scalar,\
397
   neon_fp_vrecps_vrsqrts_ddd,\
398
   neon_fp_vrecps_vrsqrts_qqq,\
399
   neon_bp_simple,\
400
   neon_bp_2cycle,\
401
   neon_bp_3cycle,\
402
   neon_ldr,\
403
   neon_str,\
404
   neon_vld1_1_2_regs,\
405
   neon_vld1_3_4_regs,\
406
   neon_vld2_2_regs_vld1_vld2_all_lanes,\
407
   neon_vld2_4_regs,\
408
   neon_vld3_vld4,\
409
   neon_vst1_1_2_regs_vst2_2_regs,\
410
   neon_vst1_3_4_regs,\
411
   neon_vst2_4_regs_vst3_vst4,\
412
   neon_vst3_vst4,\
413
   neon_vld1_vld2_lane,\
414
   neon_vld3_vld4_lane,\
415
   neon_vst1_vst2_lane,\
416
   neon_vst3_vst4_lane,\
417
   neon_vld3_vld4_all_lanes,\
418
   neon_mcr,\
419
   neon_mcr_2_mcrr,\
420
   neon_mrc,\
421
   neon_mrrc,\
422
   neon_ldm_2,\
423
   neon_stm_2,\
424
   none"
425
 (const_string "none"))
426
 
427
; condition codes: this one is used by final_prescan_insn to speed up
428
; conditionalizing instructions.  It saves having to scan the rtl to see if
429
; it uses or alters the condition codes.
430
;
431
; USE means that the condition codes are used by the insn in the process of
432
;   outputting code, this means (at present) that we can't use the insn in
433
;   inlined branches
434
;
435
; SET means that the purpose of the insn is to set the condition codes in a
436
;   well defined manner.
437
;
438
; CLOB means that the condition codes are altered in an undefined manner, if
439
;   they are altered at all
440
;
441
; UNCONDITIONAL means the instruction can not be conditionally executed and
442
;   that the instruction does not use or alter the condition codes.
443
;
444
; NOCOND means that the instruction does not use or alter the condition
445
;   codes but can be converted into a conditionally exectuted instruction.
446
 
447
(define_attr "conds" "use,set,clob,unconditional,nocond"
448
        (if_then_else
449
         (ior (eq_attr "is_thumb1" "yes")
450
              (eq_attr "type" "call"))
451
         (const_string "clob")
452
         (if_then_else (eq_attr "neon_type" "none")
453
          (const_string "nocond")
454
          (const_string "unconditional"))))
455
 
456
; Predicable means that the insn can be conditionally executed based on
457
; an automatically added predicate (additional patterns are generated by
458
; gen...).  We default to 'no' because no Thumb patterns match this rule
459
; and not all ARM patterns do.
460
(define_attr "predicable" "no,yes" (const_string "no"))
461
 
462
; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
463
; have one.  Later ones, such as StrongARM, have write-back caches, so don't
464
; suffer blockages enough to warrant modelling this (and it can adversely
465
; affect the schedule).
466
(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
467
 
468
; WRITE_CONFLICT implies that a read following an unrelated write is likely
469
; to stall the processor.  Used with model_wbuf above.
470
(define_attr "write_conflict" "no,yes"
471
  (if_then_else (eq_attr "type"
472
                 "block,float_em,f_fpa_load,f_fpa_store,f_mem_r,r_mem_f,call,load1")
473
                (const_string "yes")
474
                (const_string "no")))
475
 
476
; Classify the insns into those that take one cycle and those that take more
477
; than one on the main cpu execution unit.
478
(define_attr "core_cycles" "single,multi"
479
  (if_then_else (eq_attr "type"
480
                 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
481
                (const_string "single")
482
                (const_string "multi")))
483
 
484
;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
485
;; distant label.  Only applicable to Thumb code.
486
(define_attr "far_jump" "yes,no" (const_string "no"))
487
 
488
 
489
;; The number of machine instructions this pattern expands to.
490
;; Used for Thumb-2 conditional execution.
491
(define_attr "ce_count" "" (const_int 1))
492
 
493
;;---------------------------------------------------------------------------
494
;; Mode iterators
495
 
496
(include "iterators.md")
497
 
498
;;---------------------------------------------------------------------------
499
;; Predicates
500
 
501
(include "predicates.md")
502
(include "constraints.md")
503
 
504
;;---------------------------------------------------------------------------
505
;; Pipeline descriptions
506
 
507
(define_attr "tune_cortexr4" "yes,no"
508
  (const (if_then_else
509
          (eq_attr "tune" "cortexr4,cortexr4f,cortexr5")
510
          (const_string "yes")
511
          (const_string "no"))))
512
 
513
;; True if the generic scheduling description should be used.
514
 
515
(define_attr "generic_sched" "yes,no"
516
  (const (if_then_else
517
          (ior (eq_attr "tune" "fa526,fa626,fa606te,fa626te,fmp626,fa726te,arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexa15,cortexm4")
518
               (eq_attr "tune_cortexr4" "yes"))
519
          (const_string "no")
520
          (const_string "yes"))))
521
 
522
(define_attr "generic_vfp" "yes,no"
523
  (const (if_then_else
524
          (and (eq_attr "fpu" "vfp")
525
               (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4")
526
               (eq_attr "tune_cortexr4" "no"))
527
          (const_string "yes")
528
          (const_string "no"))))
529
 
530
(include "arm-generic.md")
531
(include "arm926ejs.md")
532
(include "arm1020e.md")
533
(include "arm1026ejs.md")
534
(include "arm1136jfs.md")
535
(include "fa526.md")
536
(include "fa606te.md")
537
(include "fa626te.md")
538
(include "fmp626.md")
539
(include "fa726te.md")
540
(include "cortex-a5.md")
541
(include "cortex-a8.md")
542
(include "cortex-a9.md")
543
(include "cortex-a15.md")
544
(include "cortex-r4.md")
545
(include "cortex-r4f.md")
546
(include "cortex-m4.md")
547
(include "cortex-m4-fpu.md")
548
(include "vfp11.md")
549
 
550
 
551
;;---------------------------------------------------------------------------
552
;; Insn patterns
553
;;
554
;; Addition insns.
555
 
556
;; Note: For DImode insns, there is normally no reason why operands should
557
;; not be in the same register, what we don't want is for something being
558
;; written to partially overlap something that is an input.
559
;; Cirrus 64bit additions should not be split because we have a native
560
;; 64bit addition instructions.
561
 
562
(define_expand "adddi3"
563
 [(parallel
564
   [(set (match_operand:DI           0 "s_register_operand" "")
565
          (plus:DI (match_operand:DI 1 "s_register_operand" "")
566
                   (match_operand:DI 2 "s_register_operand" "")))
567
    (clobber (reg:CC CC_REGNUM))])]
568
  "TARGET_EITHER"
569
  "
570
  if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
571
    {
572
      if (!cirrus_fp_register (operands[0], DImode))
573
        operands[0] = force_reg (DImode, operands[0]);
574
      if (!cirrus_fp_register (operands[1], DImode))
575
        operands[1] = force_reg (DImode, operands[1]);
576
      emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
577
      DONE;
578
    }
579
 
580
  if (TARGET_THUMB1)
581
    {
582
      if (GET_CODE (operands[1]) != REG)
583
        operands[1] = force_reg (DImode, operands[1]);
584
      if (GET_CODE (operands[2]) != REG)
585
        operands[2] = force_reg (DImode, operands[2]);
586
     }
587
  "
588
)
589
 
590
(define_insn "*thumb1_adddi3"
591
  [(set (match_operand:DI          0 "register_operand" "=l")
592
        (plus:DI (match_operand:DI 1 "register_operand" "%0")
593
                 (match_operand:DI 2 "register_operand" "l")))
594
   (clobber (reg:CC CC_REGNUM))
595
  ]
596
  "TARGET_THUMB1"
597
  "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
598
  [(set_attr "length" "4")]
599
)
600
 
601
(define_insn_and_split "*arm_adddi3"
602
  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
603
        (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
604
                 (match_operand:DI 2 "s_register_operand" "r,  0")))
605
   (clobber (reg:CC CC_REGNUM))]
606
  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && !TARGET_NEON"
607
  "#"
608
  "TARGET_32BIT && reload_completed
609
   && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))"
610
  [(parallel [(set (reg:CC_C CC_REGNUM)
611
                   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
612
                                 (match_dup 1)))
613
              (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
614
   (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
615
                               (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
616
  "
617
  {
618
    operands[3] = gen_highpart (SImode, operands[0]);
619
    operands[0] = gen_lowpart (SImode, operands[0]);
620
    operands[4] = gen_highpart (SImode, operands[1]);
621
    operands[1] = gen_lowpart (SImode, operands[1]);
622
    operands[5] = gen_highpart (SImode, operands[2]);
623
    operands[2] = gen_lowpart (SImode, operands[2]);
624
  }"
625
  [(set_attr "conds" "clob")
626
   (set_attr "length" "8")]
627
)
628
 
629
(define_insn_and_split "*adddi_sesidi_di"
630
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
631
        (plus:DI (sign_extend:DI
632
                  (match_operand:SI 2 "s_register_operand" "r,r"))
633
                 (match_operand:DI 1 "s_register_operand" "0,r")))
634
   (clobber (reg:CC CC_REGNUM))]
635
  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
636
  "#"
637
  "TARGET_32BIT && reload_completed"
638
  [(parallel [(set (reg:CC_C CC_REGNUM)
639
                   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
640
                                 (match_dup 1)))
641
              (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
642
   (set (match_dup 3) (plus:SI (plus:SI (ashiftrt:SI (match_dup 2)
643
                                                     (const_int 31))
644
                                        (match_dup 4))
645
                               (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
646
  "
647
  {
648
    operands[3] = gen_highpart (SImode, operands[0]);
649
    operands[0] = gen_lowpart (SImode, operands[0]);
650
    operands[4] = gen_highpart (SImode, operands[1]);
651
    operands[1] = gen_lowpart (SImode, operands[1]);
652
    operands[2] = gen_lowpart (SImode, operands[2]);
653
  }"
654
  [(set_attr "conds" "clob")
655
   (set_attr "length" "8")]
656
)
657
 
658
(define_insn_and_split "*adddi_zesidi_di"
659
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
660
        (plus:DI (zero_extend:DI
661
                  (match_operand:SI 2 "s_register_operand" "r,r"))
662
                 (match_operand:DI 1 "s_register_operand" "0,r")))
663
   (clobber (reg:CC CC_REGNUM))]
664
  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
665
  "#"
666
  "TARGET_32BIT && reload_completed"
667
  [(parallel [(set (reg:CC_C CC_REGNUM)
668
                   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
669
                                 (match_dup 1)))
670
              (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
671
   (set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (const_int 0))
672
                               (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
673
  "
674
  {
675
    operands[3] = gen_highpart (SImode, operands[0]);
676
    operands[0] = gen_lowpart (SImode, operands[0]);
677
    operands[4] = gen_highpart (SImode, operands[1]);
678
    operands[1] = gen_lowpart (SImode, operands[1]);
679
    operands[2] = gen_lowpart (SImode, operands[2]);
680
  }"
681
  [(set_attr "conds" "clob")
682
   (set_attr "length" "8")]
683
)
684
 
685
(define_expand "addsi3"
686
  [(set (match_operand:SI          0 "s_register_operand" "")
687
        (plus:SI (match_operand:SI 1 "s_register_operand" "")
688
                 (match_operand:SI 2 "reg_or_int_operand" "")))]
689
  "TARGET_EITHER"
690
  "
691
  if (TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT)
692
    {
693
      arm_split_constant (PLUS, SImode, NULL_RTX,
694
                          INTVAL (operands[2]), operands[0], operands[1],
695
                          optimize && can_create_pseudo_p ());
696
      DONE;
697
    }
698
  "
699
)
700
 
701
; If there is a scratch available, this will be faster than synthesizing the
702
; addition.
703
(define_peephole2
704
  [(match_scratch:SI 3 "r")
705
   (set (match_operand:SI          0 "arm_general_register_operand" "")
706
        (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
707
                 (match_operand:SI 2 "const_int_operand"  "")))]
708
  "TARGET_32BIT &&
709
   !(const_ok_for_arm (INTVAL (operands[2]))
710
     || const_ok_for_arm (-INTVAL (operands[2])))
711
    && const_ok_for_arm (~INTVAL (operands[2]))"
712
  [(set (match_dup 3) (match_dup 2))
713
   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
714
  ""
715
)
716
 
717
;; The r/r/k alternative is required when reloading the address
718
;;  (plus (reg rN) (reg sp)) into (reg rN).  In this case reload will
719
;; put the duplicated register first, and not try the commutative version.
720
(define_insn_and_split "*arm_addsi3"
721
  [(set (match_operand:SI          0 "s_register_operand" "=r, k,r,r, k, r, k,r, k, r")
722
        (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k, rk,k,rk,k, rk")
723
                 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n")))]
724
  "TARGET_32BIT"
725
  "@
726
   add%?\\t%0, %1, %2
727
   add%?\\t%0, %1, %2
728
   add%?\\t%0, %2, %1
729
   addw%?\\t%0, %1, %2
730
   addw%?\\t%0, %1, %2
731
   sub%?\\t%0, %1, #%n2
732
   sub%?\\t%0, %1, #%n2
733
   subw%?\\t%0, %1, #%n2
734
   subw%?\\t%0, %1, #%n2
735
   #"
736
  "TARGET_32BIT
737
   && GET_CODE (operands[2]) == CONST_INT
738
   && !const_ok_for_op (INTVAL (operands[2]), PLUS)
739
   && (reload_completed || !arm_eliminable_register (operands[1]))"
740
  [(clobber (const_int 0))]
741
  "
742
  arm_split_constant (PLUS, SImode, curr_insn,
743
                      INTVAL (operands[2]), operands[0],
744
                      operands[1], 0);
745
  DONE;
746
  "
747
  [(set_attr "length" "4,4,4,4,4,4,4,4,4,16")
748
   (set_attr "predicable" "yes")
749
   (set_attr "arch" "*,*,*,t2,t2,*,*,t2,t2,*")]
750
)
751
 
752
(define_insn_and_split "*thumb1_addsi3"
753
  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*rk,*hk,l,k,l,l,l")
754
        (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,k,k,0,l,k")
755
                 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*hk,*rk,M,O,Pa,Pb,Pc")))]
756
  "TARGET_THUMB1"
757
  "*
758
   static const char * const asms[] =
759
   {
760
     \"add\\t%0, %0, %2\",
761
     \"sub\\t%0, %0, #%n2\",
762
     \"add\\t%0, %1, %2\",
763
     \"add\\t%0, %0, %2\",
764
     \"add\\t%0, %0, %2\",
765
     \"add\\t%0, %1, %2\",
766
     \"add\\t%0, %1, %2\",
767
     \"#\",
768
     \"#\",
769
     \"#\"
770
   };
771
   if ((which_alternative == 2 || which_alternative == 6)
772
       && GET_CODE (operands[2]) == CONST_INT
773
       && INTVAL (operands[2]) < 0)
774
     return \"sub\\t%0, %1, #%n2\";
775
   return asms[which_alternative];
776
  "
777
  "&& reload_completed && CONST_INT_P (operands[2])
778
   && ((operands[1] != stack_pointer_rtx
779
        && (INTVAL (operands[2]) > 255 || INTVAL (operands[2]) < -255))
780
       || (operands[1] == stack_pointer_rtx
781
           && INTVAL (operands[2]) > 1020))"
782
  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
783
   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
784
  {
785
    HOST_WIDE_INT offset = INTVAL (operands[2]);
786
    if (operands[1] == stack_pointer_rtx)
787
      offset -= 1020;
788
    else
789
      {
790
        if (offset > 255)
791
          offset = 255;
792
        else if (offset < -255)
793
          offset = -255;
794
      }
795
    operands[3] = GEN_INT (offset);
796
    operands[2] = GEN_INT (INTVAL (operands[2]) - offset);
797
  }
798
  [(set_attr "length" "2,2,2,2,2,2,2,4,4,4")]
799
)
800
 
801
;; Reloading and elimination of the frame pointer can
802
;; sometimes cause this optimization to be missed.
803
(define_peephole2
804
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
805
        (match_operand:SI 1 "const_int_operand" ""))
806
   (set (match_dup 0)
807
        (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
808
  "TARGET_THUMB1
809
   && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
810
   && (INTVAL (operands[1]) & 3) == 0"
811
  [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
812
  ""
813
)
814
 
815
(define_insn "addsi3_compare0"
816
  [(set (reg:CC_NOOV CC_REGNUM)
817
        (compare:CC_NOOV
818
         (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
819
                  (match_operand:SI 2 "arm_add_operand"    "rI,L"))
820
         (const_int 0)))
821
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
822
        (plus:SI (match_dup 1) (match_dup 2)))]
823
  "TARGET_ARM"
824
  "@
825
   add%.\\t%0, %1, %2
826
   sub%.\\t%0, %1, #%n2"
827
  [(set_attr "conds" "set")]
828
)
829
 
830
(define_insn "*addsi3_compare0_scratch"
831
  [(set (reg:CC_NOOV CC_REGNUM)
832
        (compare:CC_NOOV
833
         (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
834
                  (match_operand:SI 1 "arm_add_operand"    "rI,L"))
835
         (const_int 0)))]
836
  "TARGET_ARM"
837
  "@
838
   cmn%?\\t%0, %1
839
   cmp%?\\t%0, #%n1"
840
  [(set_attr "conds" "set")
841
   (set_attr "predicable" "yes")]
842
)
843
 
844
(define_insn "*compare_negsi_si"
845
  [(set (reg:CC_Z CC_REGNUM)
846
        (compare:CC_Z
847
         (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
848
         (match_operand:SI 1 "s_register_operand" "r")))]
849
  "TARGET_32BIT"
850
  "cmn%?\\t%1, %0"
851
  [(set_attr "conds" "set")
852
   (set_attr "predicable" "yes")]
853
)
854
 
855
;; This is the canonicalization of addsi3_compare0_for_combiner when the
856
;; addend is a constant.
857
(define_insn "*cmpsi2_addneg"
858
  [(set (reg:CC CC_REGNUM)
859
        (compare:CC
860
         (match_operand:SI 1 "s_register_operand" "r,r")
861
         (match_operand:SI 2 "arm_addimm_operand" "L,I")))
862
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
863
        (plus:SI (match_dup 1)
864
                 (match_operand:SI 3 "arm_addimm_operand" "I,L")))]
865
  "TARGET_32BIT && INTVAL (operands[2]) == -INTVAL (operands[3])"
866
  "@
867
   add%.\\t%0, %1, %3
868
   sub%.\\t%0, %1, #%n3"
869
  [(set_attr "conds" "set")]
870
)
871
 
872
;; Convert the sequence
873
;;  sub  rd, rn, #1
874
;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
875
;;  bne  dest
876
;; into
877
;;  subs rd, rn, #1
878
;;  bcs  dest   ((unsigned)rn >= 1)
879
;; similarly for the beq variant using bcc.
880
;; This is a common looping idiom (while (n--))
881
(define_peephole2
882
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
883
        (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
884
                 (const_int -1)))
885
   (set (match_operand 2 "cc_register" "")
886
        (compare (match_dup 0) (const_int -1)))
887
   (set (pc)
888
        (if_then_else (match_operator 3 "equality_operator"
889
                       [(match_dup 2) (const_int 0)])
890
                      (match_operand 4 "" "")
891
                      (match_operand 5 "" "")))]
892
  "TARGET_32BIT && peep2_reg_dead_p (3, operands[2])"
893
  [(parallel[
894
    (set (match_dup 2)
895
         (compare:CC
896
          (match_dup 1) (const_int 1)))
897
    (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
898
   (set (pc)
899
        (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
900
                      (match_dup 4)
901
                      (match_dup 5)))]
902
  "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
903
   operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
904
                                  ? GEU : LTU),
905
                                 VOIDmode,
906
                                 operands[2], const0_rtx);"
907
)
908
 
909
;; The next four insns work because they compare the result with one of
910
;; the operands, and we know that the use of the condition code is
911
;; either GEU or LTU, so we can use the carry flag from the addition
912
;; instead of doing the compare a second time.
913
(define_insn "*addsi3_compare_op1"
914
  [(set (reg:CC_C CC_REGNUM)
915
        (compare:CC_C
916
         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
917
                  (match_operand:SI 2 "arm_add_operand" "rI,L"))
918
         (match_dup 1)))
919
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
920
        (plus:SI (match_dup 1) (match_dup 2)))]
921
  "TARGET_32BIT"
922
  "@
923
   add%.\\t%0, %1, %2
924
   sub%.\\t%0, %1, #%n2"
925
  [(set_attr "conds" "set")]
926
)
927
 
928
(define_insn "*addsi3_compare_op2"
929
  [(set (reg:CC_C CC_REGNUM)
930
        (compare:CC_C
931
         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
932
                  (match_operand:SI 2 "arm_add_operand" "rI,L"))
933
         (match_dup 2)))
934
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
935
        (plus:SI (match_dup 1) (match_dup 2)))]
936
  "TARGET_32BIT"
937
  "@
938
   add%.\\t%0, %1, %2
939
   sub%.\\t%0, %1, #%n2"
940
  [(set_attr "conds" "set")]
941
)
942
 
943
(define_insn "*compare_addsi2_op0"
944
  [(set (reg:CC_C CC_REGNUM)
945
        (compare:CC_C
946
         (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
947
                  (match_operand:SI 1 "arm_add_operand" "rI,L"))
948
         (match_dup 0)))]
949
  "TARGET_32BIT"
950
  "@
951
   cmn%?\\t%0, %1
952
   cmp%?\\t%0, #%n1"
953
  [(set_attr "conds" "set")
954
   (set_attr "predicable" "yes")]
955
)
956
 
957
(define_insn "*compare_addsi2_op1"
958
  [(set (reg:CC_C CC_REGNUM)
959
        (compare:CC_C
960
         (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
961
                  (match_operand:SI 1 "arm_add_operand" "rI,L"))
962
         (match_dup 1)))]
963
  "TARGET_32BIT"
964
  "@
965
   cmn%?\\t%0, %1
966
   cmp%?\\t%0, #%n1"
967
  [(set_attr "conds" "set")
968
   (set_attr "predicable" "yes")]
969
)
970
 
971
(define_insn "*addsi3_carryin_"
972
  [(set (match_operand:SI 0 "s_register_operand" "=r")
973
        (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
974
                          (match_operand:SI 2 "arm_rhs_operand" "rI"))
975
                 (LTUGEU:SI (reg: CC_REGNUM) (const_int 0))))]
976
  "TARGET_32BIT"
977
  "adc%?\\t%0, %1, %2"
978
  [(set_attr "conds" "use")]
979
)
980
 
981
(define_insn "*addsi3_carryin_alt2_"
982
  [(set (match_operand:SI 0 "s_register_operand" "=r")
983
        (plus:SI (plus:SI (LTUGEU:SI (reg: CC_REGNUM) (const_int 0))
984
                          (match_operand:SI 1 "s_register_operand" "%r"))
985
                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
986
  "TARGET_32BIT"
987
  "adc%?\\t%0, %1, %2"
988
  [(set_attr "conds" "use")]
989
)
990
 
991
(define_insn "*addsi3_carryin_shift_"
992
  [(set (match_operand:SI 0 "s_register_operand" "=r")
993
        (plus:SI (plus:SI
994
                  (match_operator:SI 2 "shift_operator"
995
                    [(match_operand:SI 3 "s_register_operand" "r")
996
                     (match_operand:SI 4 "reg_or_int_operand" "rM")])
997
                  (match_operand:SI 1 "s_register_operand" "r"))
998
                 (LTUGEU:SI (reg: CC_REGNUM) (const_int 0))))]
999
  "TARGET_32BIT"
1000
  "adc%?\\t%0, %1, %3%S2"
1001
  [(set_attr "conds" "use")
1002
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
1003
                      (const_string "alu_shift")
1004
                      (const_string "alu_shift_reg")))]
1005
)
1006
 
1007
(define_insn "*addsi3_carryin_clobercc_"
1008
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1009
        (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%r")
1010
                          (match_operand:SI 2 "arm_rhs_operand" "rI"))
1011
                 (LTUGEU:SI (reg: CC_REGNUM) (const_int 0))))
1012
   (clobber (reg:CC CC_REGNUM))]
1013
   "TARGET_32BIT"
1014
   "adc%.\\t%0, %1, %2"
1015
   [(set_attr "conds" "set")]
1016
)
1017
 
1018
(define_expand "incscc"
1019
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1020
        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1021
                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1022
                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1023
  "TARGET_32BIT"
1024
  ""
1025
)
1026
 
1027
(define_insn "*arm_incscc"
1028
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1029
        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
1030
                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
1031
                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
1032
  "TARGET_ARM"
1033
  "@
1034
  add%d2\\t%0, %1, #1
1035
  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
1036
  [(set_attr "conds" "use")
1037
   (set_attr "length" "4,8")]
1038
)
1039
 
1040
; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
1041
(define_split
1042
  [(set (match_operand:SI 0 "s_register_operand" "")
1043
        (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
1044
                            (match_operand:SI 2 "s_register_operand" ""))
1045
                 (const_int -1)))
1046
   (clobber (match_operand:SI 3 "s_register_operand" ""))]
1047
  "TARGET_32BIT"
1048
  [(set (match_dup 3) (match_dup 1))
1049
   (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
1050
  "
1051
  operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
1052
")
1053
 
1054
(define_expand "addsf3"
1055
  [(set (match_operand:SF          0 "s_register_operand" "")
1056
        (plus:SF (match_operand:SF 1 "s_register_operand" "")
1057
                 (match_operand:SF 2 "arm_float_add_operand" "")))]
1058
  "TARGET_32BIT && TARGET_HARD_FLOAT"
1059
  "
1060
  if (TARGET_MAVERICK
1061
      && !cirrus_fp_register (operands[2], SFmode))
1062
    operands[2] = force_reg (SFmode, operands[2]);
1063
")
1064
 
1065
(define_expand "adddf3"
1066
  [(set (match_operand:DF          0 "s_register_operand" "")
1067
        (plus:DF (match_operand:DF 1 "s_register_operand" "")
1068
                 (match_operand:DF 2 "arm_float_add_operand" "")))]
1069
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1070
  "
1071
  if (TARGET_MAVERICK
1072
      && !cirrus_fp_register (operands[2], DFmode))
1073
    operands[2] = force_reg (DFmode, operands[2]);
1074
")
1075
 
1076
(define_expand "subdi3"
1077
 [(parallel
1078
   [(set (match_operand:DI            0 "s_register_operand" "")
1079
          (minus:DI (match_operand:DI 1 "s_register_operand" "")
1080
                    (match_operand:DI 2 "s_register_operand" "")))
1081
    (clobber (reg:CC CC_REGNUM))])]
1082
  "TARGET_EITHER"
1083
  "
1084
  if (TARGET_HARD_FLOAT && TARGET_MAVERICK
1085
      && TARGET_32BIT
1086
      && cirrus_fp_register (operands[0], DImode)
1087
      && cirrus_fp_register (operands[1], DImode))
1088
    {
1089
      emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
1090
      DONE;
1091
    }
1092
 
1093
  if (TARGET_THUMB1)
1094
    {
1095
      if (GET_CODE (operands[1]) != REG)
1096
        operands[1] = force_reg (DImode, operands[1]);
1097
      if (GET_CODE (operands[2]) != REG)
1098
        operands[2] = force_reg (DImode, operands[2]);
1099
     }
1100
  "
1101
)
1102
 
1103
(define_insn "*arm_subdi3"
1104
  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
1105
        (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
1106
                  (match_operand:DI 2 "s_register_operand" "r,0,0")))
1107
   (clobber (reg:CC CC_REGNUM))]
1108
  "TARGET_32BIT && !TARGET_NEON"
1109
  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
1110
  [(set_attr "conds" "clob")
1111
   (set_attr "length" "8")]
1112
)
1113
 
1114
(define_insn "*thumb_subdi3"
1115
  [(set (match_operand:DI           0 "register_operand" "=l")
1116
        (minus:DI (match_operand:DI 1 "register_operand"  "0")
1117
                  (match_operand:DI 2 "register_operand"  "l")))
1118
   (clobber (reg:CC CC_REGNUM))]
1119
  "TARGET_THUMB1"
1120
  "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
1121
  [(set_attr "length" "4")]
1122
)
1123
 
1124
(define_insn "*subdi_di_zesidi"
1125
  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
1126
        (minus:DI (match_operand:DI 1 "s_register_operand"  "0,r")
1127
                  (zero_extend:DI
1128
                   (match_operand:SI 2 "s_register_operand"  "r,r"))))
1129
   (clobber (reg:CC CC_REGNUM))]
1130
  "TARGET_32BIT"
1131
  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
1132
  [(set_attr "conds" "clob")
1133
   (set_attr "length" "8")]
1134
)
1135
 
1136
(define_insn "*subdi_di_sesidi"
1137
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1138
        (minus:DI (match_operand:DI  1 "s_register_operand"  "0,r")
1139
                  (sign_extend:DI
1140
                   (match_operand:SI 2 "s_register_operand"  "r,r"))))
1141
   (clobber (reg:CC CC_REGNUM))]
1142
  "TARGET_32BIT"
1143
  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
1144
  [(set_attr "conds" "clob")
1145
   (set_attr "length" "8")]
1146
)
1147
 
1148
(define_insn "*subdi_zesidi_di"
1149
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1150
        (minus:DI (zero_extend:DI
1151
                   (match_operand:SI 2 "s_register_operand"  "r,r"))
1152
                  (match_operand:DI  1 "s_register_operand" "0,r")))
1153
   (clobber (reg:CC CC_REGNUM))]
1154
  "TARGET_ARM"
1155
  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
1156
  [(set_attr "conds" "clob")
1157
   (set_attr "length" "8")]
1158
)
1159
 
1160
(define_insn "*subdi_sesidi_di"
1161
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
1162
        (minus:DI (sign_extend:DI
1163
                   (match_operand:SI 2 "s_register_operand"   "r,r"))
1164
                  (match_operand:DI  1 "s_register_operand"  "0,r")))
1165
   (clobber (reg:CC CC_REGNUM))]
1166
  "TARGET_ARM"
1167
  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
1168
  [(set_attr "conds" "clob")
1169
   (set_attr "length" "8")]
1170
)
1171
 
1172
(define_insn "*subdi_zesidi_zesidi"
1173
  [(set (match_operand:DI            0 "s_register_operand" "=r")
1174
        (minus:DI (zero_extend:DI
1175
                   (match_operand:SI 1 "s_register_operand"  "r"))
1176
                  (zero_extend:DI
1177
                   (match_operand:SI 2 "s_register_operand"  "r"))))
1178
   (clobber (reg:CC CC_REGNUM))]
1179
  "TARGET_32BIT"
1180
  "subs\\t%Q0, %1, %2\;sbc\\t%R0, %1, %1"
1181
  [(set_attr "conds" "clob")
1182
   (set_attr "length" "8")]
1183
)
1184
 
1185
(define_expand "subsi3"
1186
  [(set (match_operand:SI           0 "s_register_operand" "")
1187
        (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
1188
                  (match_operand:SI 2 "s_register_operand" "")))]
1189
  "TARGET_EITHER"
1190
  "
1191
  if (GET_CODE (operands[1]) == CONST_INT)
1192
    {
1193
      if (TARGET_32BIT)
1194
        {
1195
          arm_split_constant (MINUS, SImode, NULL_RTX,
1196
                              INTVAL (operands[1]), operands[0],
1197
                              operands[2], optimize && can_create_pseudo_p ());
1198
          DONE;
1199
        }
1200
      else /* TARGET_THUMB1 */
1201
        operands[1] = force_reg (SImode, operands[1]);
1202
    }
1203
  "
1204
)
1205
 
1206
(define_insn "thumb1_subsi3_insn"
1207
  [(set (match_operand:SI           0 "register_operand" "=l")
1208
        (minus:SI (match_operand:SI 1 "register_operand" "l")
1209
                  (match_operand:SI 2 "reg_or_int_operand" "lPd")))]
1210
  "TARGET_THUMB1"
1211
  "sub\\t%0, %1, %2"
1212
  [(set_attr "length" "2")
1213
   (set_attr "conds" "set")])
1214
 
1215
; ??? Check Thumb-2 split length
1216
(define_insn_and_split "*arm_subsi3_insn"
1217
  [(set (match_operand:SI           0 "s_register_operand" "=r,r,rk,r")
1218
        (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n")
1219
                  (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r")))]
1220
  "TARGET_32BIT"
1221
  "@
1222
   rsb%?\\t%0, %2, %1
1223
   sub%?\\t%0, %1, %2
1224
   sub%?\\t%0, %1, %2
1225
   #"
1226
  "&& (GET_CODE (operands[1]) == CONST_INT
1227
       && !const_ok_for_arm (INTVAL (operands[1])))"
1228
  [(clobber (const_int 0))]
1229
  "
1230
  arm_split_constant (MINUS, SImode, curr_insn,
1231
                      INTVAL (operands[1]), operands[0], operands[2], 0);
1232
  DONE;
1233
  "
1234
  [(set_attr "length" "4,4,4,16")
1235
   (set_attr "predicable" "yes")]
1236
)
1237
 
1238
(define_peephole2
1239
  [(match_scratch:SI 3 "r")
1240
   (set (match_operand:SI 0 "arm_general_register_operand" "")
1241
        (minus:SI (match_operand:SI 1 "const_int_operand" "")
1242
                  (match_operand:SI 2 "arm_general_register_operand" "")))]
1243
  "TARGET_32BIT
1244
   && !const_ok_for_arm (INTVAL (operands[1]))
1245
   && const_ok_for_arm (~INTVAL (operands[1]))"
1246
  [(set (match_dup 3) (match_dup 1))
1247
   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1248
  ""
1249
)
1250
 
1251
(define_insn "*subsi3_compare0"
1252
  [(set (reg:CC_NOOV CC_REGNUM)
1253
        (compare:CC_NOOV
1254
         (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1255
                   (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1256
         (const_int 0)))
1257
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
1258
        (minus:SI (match_dup 1) (match_dup 2)))]
1259
  "TARGET_32BIT"
1260
  "@
1261
   sub%.\\t%0, %1, %2
1262
   rsb%.\\t%0, %2, %1"
1263
  [(set_attr "conds" "set")]
1264
)
1265
 
1266
(define_insn "*subsi3_compare"
1267
  [(set (reg:CC CC_REGNUM)
1268
        (compare:CC (match_operand:SI 1 "arm_rhs_operand" "r,I")
1269
                    (match_operand:SI 2 "arm_rhs_operand" "rI,r")))
1270
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
1271
        (minus:SI (match_dup 1) (match_dup 2)))]
1272
  "TARGET_32BIT"
1273
  "@
1274
   sub%.\\t%0, %1, %2
1275
   rsb%.\\t%0, %2, %1"
1276
  [(set_attr "conds" "set")]
1277
)
1278
 
1279
(define_expand "decscc"
1280
  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1281
        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1282
                  (match_operator:SI 2 "arm_comparison_operator"
1283
                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
1284
  "TARGET_32BIT"
1285
  ""
1286
)
1287
 
1288
(define_insn "*arm_decscc"
1289
  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1290
        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1291
                  (match_operator:SI 2 "arm_comparison_operator"
1292
                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
1293
  "TARGET_ARM"
1294
  "@
1295
   sub%d2\\t%0, %1, #1
1296
   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1297
  [(set_attr "conds" "use")
1298
   (set_attr "length" "*,8")]
1299
)
1300
 
1301
(define_expand "subsf3"
1302
  [(set (match_operand:SF           0 "s_register_operand" "")
1303
        (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1304
                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1305
  "TARGET_32BIT && TARGET_HARD_FLOAT"
1306
  "
1307
  if (TARGET_MAVERICK)
1308
    {
1309
      if (!cirrus_fp_register (operands[1], SFmode))
1310
        operands[1] = force_reg (SFmode, operands[1]);
1311
      if (!cirrus_fp_register (operands[2], SFmode))
1312
        operands[2] = force_reg (SFmode, operands[2]);
1313
    }
1314
")
1315
 
1316
(define_expand "subdf3"
1317
  [(set (match_operand:DF           0 "s_register_operand" "")
1318
        (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1319
                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1320
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1321
  "
1322
  if (TARGET_MAVERICK)
1323
    {
1324
       if (!cirrus_fp_register (operands[1], DFmode))
1325
         operands[1] = force_reg (DFmode, operands[1]);
1326
       if (!cirrus_fp_register (operands[2], DFmode))
1327
         operands[2] = force_reg (DFmode, operands[2]);
1328
    }
1329
")
1330
 
1331
 
1332
;; Multiplication insns
1333
 
1334
(define_expand "mulsi3"
1335
  [(set (match_operand:SI          0 "s_register_operand" "")
1336
        (mult:SI (match_operand:SI 2 "s_register_operand" "")
1337
                 (match_operand:SI 1 "s_register_operand" "")))]
1338
  "TARGET_EITHER"
1339
  ""
1340
)
1341
 
1342
;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1343
(define_insn "*arm_mulsi3"
1344
  [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1345
        (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1346
                 (match_operand:SI 1 "s_register_operand" "%0,r")))]
1347
  "TARGET_32BIT && !arm_arch6"
1348
  "mul%?\\t%0, %2, %1"
1349
  [(set_attr "insn" "mul")
1350
   (set_attr "predicable" "yes")]
1351
)
1352
 
1353
(define_insn "*arm_mulsi3_v6"
1354
  [(set (match_operand:SI          0 "s_register_operand" "=r")
1355
        (mult:SI (match_operand:SI 1 "s_register_operand" "r")
1356
                 (match_operand:SI 2 "s_register_operand" "r")))]
1357
  "TARGET_32BIT && arm_arch6"
1358
  "mul%?\\t%0, %1, %2"
1359
  [(set_attr "insn" "mul")
1360
   (set_attr "predicable" "yes")]
1361
)
1362
 
1363
; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1364
; 1 and 2; are the same, because reload will make operand 0 match
1365
; operand 1 without realizing that this conflicts with operand 2.  We fix
1366
; this by adding another alternative to match this case, and then `reload'
1367
; it ourselves.  This alternative must come first.
1368
(define_insn "*thumb_mulsi3"
1369
  [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1370
        (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1371
                 (match_operand:SI 2 "register_operand" "l,l,l")))]
1372
  "TARGET_THUMB1 && !arm_arch6"
1373
  "*
1374
  if (which_alternative < 2)
1375
    return \"mov\\t%0, %1\;mul\\t%0, %2\";
1376
  else
1377
    return \"mul\\t%0, %2\";
1378
  "
1379
  [(set_attr "length" "4,4,2")
1380
   (set_attr "insn" "mul")]
1381
)
1382
 
1383
(define_insn "*thumb_mulsi3_v6"
1384
  [(set (match_operand:SI          0 "register_operand" "=l,l,l")
1385
        (mult:SI (match_operand:SI 1 "register_operand" "0,l,0")
1386
                 (match_operand:SI 2 "register_operand" "l,0,0")))]
1387
  "TARGET_THUMB1 && arm_arch6"
1388
  "@
1389
   mul\\t%0, %2
1390
   mul\\t%0, %1
1391
   mul\\t%0, %1"
1392
  [(set_attr "length" "2")
1393
   (set_attr "insn" "mul")]
1394
)
1395
 
1396
(define_insn "*mulsi3_compare0"
1397
  [(set (reg:CC_NOOV CC_REGNUM)
1398
        (compare:CC_NOOV (mult:SI
1399
                          (match_operand:SI 2 "s_register_operand" "r,r")
1400
                          (match_operand:SI 1 "s_register_operand" "%0,r"))
1401
                         (const_int 0)))
1402
   (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1403
        (mult:SI (match_dup 2) (match_dup 1)))]
1404
  "TARGET_ARM && !arm_arch6"
1405
  "mul%.\\t%0, %2, %1"
1406
  [(set_attr "conds" "set")
1407
   (set_attr "insn" "muls")]
1408
)
1409
 
1410
(define_insn "*mulsi3_compare0_v6"
1411
  [(set (reg:CC_NOOV CC_REGNUM)
1412
        (compare:CC_NOOV (mult:SI
1413
                          (match_operand:SI 2 "s_register_operand" "r")
1414
                          (match_operand:SI 1 "s_register_operand" "r"))
1415
                         (const_int 0)))
1416
   (set (match_operand:SI 0 "s_register_operand" "=r")
1417
        (mult:SI (match_dup 2) (match_dup 1)))]
1418
  "TARGET_ARM && arm_arch6 && optimize_size"
1419
  "mul%.\\t%0, %2, %1"
1420
  [(set_attr "conds" "set")
1421
   (set_attr "insn" "muls")]
1422
)
1423
 
1424
(define_insn "*mulsi_compare0_scratch"
1425
  [(set (reg:CC_NOOV CC_REGNUM)
1426
        (compare:CC_NOOV (mult:SI
1427
                          (match_operand:SI 2 "s_register_operand" "r,r")
1428
                          (match_operand:SI 1 "s_register_operand" "%0,r"))
1429
                         (const_int 0)))
1430
   (clobber (match_scratch:SI 0 "=&r,&r"))]
1431
  "TARGET_ARM && !arm_arch6"
1432
  "mul%.\\t%0, %2, %1"
1433
  [(set_attr "conds" "set")
1434
   (set_attr "insn" "muls")]
1435
)
1436
 
1437
(define_insn "*mulsi_compare0_scratch_v6"
1438
  [(set (reg:CC_NOOV CC_REGNUM)
1439
        (compare:CC_NOOV (mult:SI
1440
                          (match_operand:SI 2 "s_register_operand" "r")
1441
                          (match_operand:SI 1 "s_register_operand" "r"))
1442
                         (const_int 0)))
1443
   (clobber (match_scratch:SI 0 "=r"))]
1444
  "TARGET_ARM && arm_arch6 && optimize_size"
1445
  "mul%.\\t%0, %2, %1"
1446
  [(set_attr "conds" "set")
1447
   (set_attr "insn" "muls")]
1448
)
1449
 
1450
;; Unnamed templates to match MLA instruction.
1451
 
1452
(define_insn "*mulsi3addsi"
1453
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1454
        (plus:SI
1455
          (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1456
                   (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1457
          (match_operand:SI 3 "s_register_operand" "r,r,0,0")))]
1458
  "TARGET_32BIT && !arm_arch6"
1459
  "mla%?\\t%0, %2, %1, %3"
1460
  [(set_attr "insn" "mla")
1461
   (set_attr "predicable" "yes")]
1462
)
1463
 
1464
(define_insn "*mulsi3addsi_v6"
1465
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1466
        (plus:SI
1467
          (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1468
                   (match_operand:SI 1 "s_register_operand" "r"))
1469
          (match_operand:SI 3 "s_register_operand" "r")))]
1470
  "TARGET_32BIT && arm_arch6"
1471
  "mla%?\\t%0, %2, %1, %3"
1472
  [(set_attr "insn" "mla")
1473
   (set_attr "predicable" "yes")]
1474
)
1475
 
1476
(define_insn "*mulsi3addsi_compare0"
1477
  [(set (reg:CC_NOOV CC_REGNUM)
1478
        (compare:CC_NOOV
1479
         (plus:SI (mult:SI
1480
                   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1481
                   (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1482
                  (match_operand:SI 3 "s_register_operand" "r,r,0,0"))
1483
         (const_int 0)))
1484
   (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1485
        (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1486
                 (match_dup 3)))]
1487
  "TARGET_ARM && arm_arch6"
1488
  "mla%.\\t%0, %2, %1, %3"
1489
  [(set_attr "conds" "set")
1490
   (set_attr "insn" "mlas")]
1491
)
1492
 
1493
(define_insn "*mulsi3addsi_compare0_v6"
1494
  [(set (reg:CC_NOOV CC_REGNUM)
1495
        (compare:CC_NOOV
1496
         (plus:SI (mult:SI
1497
                   (match_operand:SI 2 "s_register_operand" "r")
1498
                   (match_operand:SI 1 "s_register_operand" "r"))
1499
                  (match_operand:SI 3 "s_register_operand" "r"))
1500
         (const_int 0)))
1501
   (set (match_operand:SI 0 "s_register_operand" "=r")
1502
        (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1503
                 (match_dup 3)))]
1504
  "TARGET_ARM && arm_arch6 && optimize_size"
1505
  "mla%.\\t%0, %2, %1, %3"
1506
  [(set_attr "conds" "set")
1507
   (set_attr "insn" "mlas")]
1508
)
1509
 
1510
(define_insn "*mulsi3addsi_compare0_scratch"
1511
  [(set (reg:CC_NOOV CC_REGNUM)
1512
        (compare:CC_NOOV
1513
         (plus:SI (mult:SI
1514
                   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1515
                   (match_operand:SI 1 "s_register_operand" "%0,r,0,r"))
1516
                  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1517
         (const_int 0)))
1518
   (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1519
  "TARGET_ARM && !arm_arch6"
1520
  "mla%.\\t%0, %2, %1, %3"
1521
  [(set_attr "conds" "set")
1522
   (set_attr "insn" "mlas")]
1523
)
1524
 
1525
(define_insn "*mulsi3addsi_compare0_scratch_v6"
1526
  [(set (reg:CC_NOOV CC_REGNUM)
1527
        (compare:CC_NOOV
1528
         (plus:SI (mult:SI
1529
                   (match_operand:SI 2 "s_register_operand" "r")
1530
                   (match_operand:SI 1 "s_register_operand" "r"))
1531
                  (match_operand:SI 3 "s_register_operand" "r"))
1532
         (const_int 0)))
1533
   (clobber (match_scratch:SI 0 "=r"))]
1534
  "TARGET_ARM && arm_arch6 && optimize_size"
1535
  "mla%.\\t%0, %2, %1, %3"
1536
  [(set_attr "conds" "set")
1537
   (set_attr "insn" "mlas")]
1538
)
1539
 
1540
(define_insn "*mulsi3subsi"
1541
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1542
        (minus:SI
1543
          (match_operand:SI 3 "s_register_operand" "r")
1544
          (mult:SI (match_operand:SI 2 "s_register_operand" "r")
1545
                   (match_operand:SI 1 "s_register_operand" "r"))))]
1546
  "TARGET_32BIT && arm_arch_thumb2"
1547
  "mls%?\\t%0, %2, %1, %3"
1548
  [(set_attr "insn" "mla")
1549
   (set_attr "predicable" "yes")]
1550
)
1551
 
1552
(define_expand "maddsidi4"
1553
  [(set (match_operand:DI 0 "s_register_operand" "")
1554
        (plus:DI
1555
         (mult:DI
1556
          (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1557
          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1558
         (match_operand:DI 3 "s_register_operand" "")))]
1559
  "TARGET_32BIT && arm_arch3m"
1560
  "")
1561
 
1562
(define_insn "*mulsidi3adddi"
1563
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1564
        (plus:DI
1565
         (mult:DI
1566
          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1567
          (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1568
         (match_operand:DI 1 "s_register_operand" "0")))]
1569
  "TARGET_32BIT && arm_arch3m && !arm_arch6"
1570
  "smlal%?\\t%Q0, %R0, %3, %2"
1571
  [(set_attr "insn" "smlal")
1572
   (set_attr "predicable" "yes")]
1573
)
1574
 
1575
(define_insn "*mulsidi3adddi_v6"
1576
  [(set (match_operand:DI 0 "s_register_operand" "=r")
1577
        (plus:DI
1578
         (mult:DI
1579
          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1580
          (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1581
         (match_operand:DI 1 "s_register_operand" "0")))]
1582
  "TARGET_32BIT && arm_arch6"
1583
  "smlal%?\\t%Q0, %R0, %3, %2"
1584
  [(set_attr "insn" "smlal")
1585
   (set_attr "predicable" "yes")]
1586
)
1587
 
1588
;; 32x32->64 widening multiply.
1589
;; As with mulsi3, the only difference between the v3-5 and v6+
1590
;; versions of these patterns is the requirement that the output not
1591
;; overlap the inputs, but that still means we have to have a named
1592
;; expander and two different starred insns.
1593
 
1594
(define_expand "mulsidi3"
1595
  [(set (match_operand:DI 0 "s_register_operand" "")
1596
        (mult:DI
1597
         (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1598
         (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1599
  "TARGET_32BIT && arm_arch3m"
1600
  ""
1601
)
1602
 
1603
(define_insn "*mulsidi3_nov6"
1604
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1605
        (mult:DI
1606
         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1607
         (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1608
  "TARGET_32BIT && arm_arch3m && !arm_arch6"
1609
  "smull%?\\t%Q0, %R0, %1, %2"
1610
  [(set_attr "insn" "smull")
1611
   (set_attr "predicable" "yes")]
1612
)
1613
 
1614
(define_insn "*mulsidi3_v6"
1615
  [(set (match_operand:DI 0 "s_register_operand" "=r")
1616
        (mult:DI
1617
         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1618
         (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1619
  "TARGET_32BIT && arm_arch6"
1620
  "smull%?\\t%Q0, %R0, %1, %2"
1621
  [(set_attr "insn" "smull")
1622
   (set_attr "predicable" "yes")]
1623
)
1624
 
1625
(define_expand "umulsidi3"
1626
  [(set (match_operand:DI 0 "s_register_operand" "")
1627
        (mult:DI
1628
         (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1629
         (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))))]
1630
  "TARGET_32BIT && arm_arch3m"
1631
  ""
1632
)
1633
 
1634
(define_insn "*umulsidi3_nov6"
1635
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1636
        (mult:DI
1637
         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1638
         (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1639
  "TARGET_32BIT && arm_arch3m && !arm_arch6"
1640
  "umull%?\\t%Q0, %R0, %1, %2"
1641
  [(set_attr "insn" "umull")
1642
   (set_attr "predicable" "yes")]
1643
)
1644
 
1645
(define_insn "*umulsidi3_v6"
1646
  [(set (match_operand:DI 0 "s_register_operand" "=r")
1647
        (mult:DI
1648
         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1649
         (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1650
  "TARGET_32BIT && arm_arch6"
1651
  "umull%?\\t%Q0, %R0, %1, %2"
1652
  [(set_attr "insn" "umull")
1653
   (set_attr "predicable" "yes")]
1654
)
1655
 
1656
(define_expand "umaddsidi4"
1657
  [(set (match_operand:DI 0 "s_register_operand" "")
1658
        (plus:DI
1659
         (mult:DI
1660
          (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1661
          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1662
         (match_operand:DI 3 "s_register_operand" "")))]
1663
  "TARGET_32BIT && arm_arch3m"
1664
  "")
1665
 
1666
(define_insn "*umulsidi3adddi"
1667
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1668
        (plus:DI
1669
         (mult:DI
1670
          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1671
          (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1672
         (match_operand:DI 1 "s_register_operand" "0")))]
1673
  "TARGET_32BIT && arm_arch3m && !arm_arch6"
1674
  "umlal%?\\t%Q0, %R0, %3, %2"
1675
  [(set_attr "insn" "umlal")
1676
   (set_attr "predicable" "yes")]
1677
)
1678
 
1679
(define_insn "*umulsidi3adddi_v6"
1680
  [(set (match_operand:DI 0 "s_register_operand" "=r")
1681
        (plus:DI
1682
         (mult:DI
1683
          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
1684
          (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1685
         (match_operand:DI 1 "s_register_operand" "0")))]
1686
  "TARGET_32BIT && arm_arch6"
1687
  "umlal%?\\t%Q0, %R0, %3, %2"
1688
  [(set_attr "insn" "umlal")
1689
   (set_attr "predicable" "yes")]
1690
)
1691
 
1692
(define_expand "smulsi3_highpart"
1693
  [(parallel
1694
    [(set (match_operand:SI 0 "s_register_operand" "")
1695
          (truncate:SI
1696
           (lshiftrt:DI
1697
            (mult:DI
1698
             (sign_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1699
             (sign_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1700
            (const_int 32))))
1701
     (clobber (match_scratch:SI 3 ""))])]
1702
  "TARGET_32BIT && arm_arch3m"
1703
  ""
1704
)
1705
 
1706
(define_insn "*smulsi3_highpart_nov6"
1707
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1708
        (truncate:SI
1709
         (lshiftrt:DI
1710
          (mult:DI
1711
           (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1712
           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1713
          (const_int 32))))
1714
   (clobber (match_scratch:SI 3 "=&r,&r"))]
1715
  "TARGET_32BIT && arm_arch3m && !arm_arch6"
1716
  "smull%?\\t%3, %0, %2, %1"
1717
  [(set_attr "insn" "smull")
1718
   (set_attr "predicable" "yes")]
1719
)
1720
 
1721
(define_insn "*smulsi3_highpart_v6"
1722
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1723
        (truncate:SI
1724
         (lshiftrt:DI
1725
          (mult:DI
1726
           (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1727
           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1728
          (const_int 32))))
1729
   (clobber (match_scratch:SI 3 "=r"))]
1730
  "TARGET_32BIT && arm_arch6"
1731
  "smull%?\\t%3, %0, %2, %1"
1732
  [(set_attr "insn" "smull")
1733
   (set_attr "predicable" "yes")]
1734
)
1735
 
1736
(define_expand "umulsi3_highpart"
1737
  [(parallel
1738
    [(set (match_operand:SI 0 "s_register_operand" "")
1739
          (truncate:SI
1740
           (lshiftrt:DI
1741
            (mult:DI
1742
             (zero_extend:DI (match_operand:SI 1 "s_register_operand" ""))
1743
              (zero_extend:DI (match_operand:SI 2 "s_register_operand" "")))
1744
            (const_int 32))))
1745
     (clobber (match_scratch:SI 3 ""))])]
1746
  "TARGET_32BIT && arm_arch3m"
1747
  ""
1748
)
1749
 
1750
(define_insn "*umulsi3_highpart_nov6"
1751
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1752
        (truncate:SI
1753
         (lshiftrt:DI
1754
          (mult:DI
1755
           (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%0,r"))
1756
           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1757
          (const_int 32))))
1758
   (clobber (match_scratch:SI 3 "=&r,&r"))]
1759
  "TARGET_32BIT && arm_arch3m && !arm_arch6"
1760
  "umull%?\\t%3, %0, %2, %1"
1761
  [(set_attr "insn" "umull")
1762
   (set_attr "predicable" "yes")]
1763
)
1764
 
1765
(define_insn "*umulsi3_highpart_v6"
1766
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1767
        (truncate:SI
1768
         (lshiftrt:DI
1769
          (mult:DI
1770
           (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
1771
           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r")))
1772
          (const_int 32))))
1773
   (clobber (match_scratch:SI 3 "=r"))]
1774
  "TARGET_32BIT && arm_arch6"
1775
  "umull%?\\t%3, %0, %2, %1"
1776
  [(set_attr "insn" "umull")
1777
   (set_attr "predicable" "yes")]
1778
)
1779
 
1780
(define_insn "mulhisi3"
1781
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1782
        (mult:SI (sign_extend:SI
1783
                  (match_operand:HI 1 "s_register_operand" "%r"))
1784
                 (sign_extend:SI
1785
                  (match_operand:HI 2 "s_register_operand" "r"))))]
1786
  "TARGET_DSP_MULTIPLY"
1787
  "smulbb%?\\t%0, %1, %2"
1788
  [(set_attr "insn" "smulxy")
1789
   (set_attr "predicable" "yes")]
1790
)
1791
 
1792
(define_insn "*mulhisi3tb"
1793
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1794
        (mult:SI (ashiftrt:SI
1795
                  (match_operand:SI 1 "s_register_operand" "r")
1796
                  (const_int 16))
1797
                 (sign_extend:SI
1798
                  (match_operand:HI 2 "s_register_operand" "r"))))]
1799
  "TARGET_DSP_MULTIPLY"
1800
  "smultb%?\\t%0, %1, %2"
1801
  [(set_attr "insn" "smulxy")
1802
   (set_attr "predicable" "yes")]
1803
)
1804
 
1805
(define_insn "*mulhisi3bt"
1806
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1807
        (mult:SI (sign_extend:SI
1808
                  (match_operand:HI 1 "s_register_operand" "r"))
1809
                 (ashiftrt:SI
1810
                  (match_operand:SI 2 "s_register_operand" "r")
1811
                  (const_int 16))))]
1812
  "TARGET_DSP_MULTIPLY"
1813
  "smulbt%?\\t%0, %1, %2"
1814
  [(set_attr "insn" "smulxy")
1815
   (set_attr "predicable" "yes")]
1816
)
1817
 
1818
(define_insn "*mulhisi3tt"
1819
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1820
        (mult:SI (ashiftrt:SI
1821
                  (match_operand:SI 1 "s_register_operand" "r")
1822
                  (const_int 16))
1823
                 (ashiftrt:SI
1824
                  (match_operand:SI 2 "s_register_operand" "r")
1825
                  (const_int 16))))]
1826
  "TARGET_DSP_MULTIPLY"
1827
  "smultt%?\\t%0, %1, %2"
1828
  [(set_attr "insn" "smulxy")
1829
   (set_attr "predicable" "yes")]
1830
)
1831
 
1832
(define_insn "maddhisi4"
1833
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1834
        (plus:SI (mult:SI (sign_extend:SI
1835
                           (match_operand:HI 1 "s_register_operand" "r"))
1836
                          (sign_extend:SI
1837
                           (match_operand:HI 2 "s_register_operand" "r")))
1838
                 (match_operand:SI 3 "s_register_operand" "r")))]
1839
  "TARGET_DSP_MULTIPLY"
1840
  "smlabb%?\\t%0, %1, %2, %3"
1841
  [(set_attr "insn" "smlaxy")
1842
   (set_attr "predicable" "yes")]
1843
)
1844
 
1845
;; Note: there is no maddhisi4ibt because this one is canonical form
1846
(define_insn "*maddhisi4tb"
1847
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1848
        (plus:SI (mult:SI (ashiftrt:SI
1849
                           (match_operand:SI 1 "s_register_operand" "r")
1850
                           (const_int 16))
1851
                          (sign_extend:SI
1852
                           (match_operand:HI 2 "s_register_operand" "r")))
1853
                 (match_operand:SI 3 "s_register_operand" "r")))]
1854
  "TARGET_DSP_MULTIPLY"
1855
  "smlatb%?\\t%0, %1, %2, %3"
1856
  [(set_attr "insn" "smlaxy")
1857
   (set_attr "predicable" "yes")]
1858
)
1859
 
1860
(define_insn "*maddhisi4tt"
1861
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1862
        (plus:SI (mult:SI (ashiftrt:SI
1863
                           (match_operand:SI 1 "s_register_operand" "r")
1864
                           (const_int 16))
1865
                          (ashiftrt:SI
1866
                           (match_operand:SI 2 "s_register_operand" "r")
1867
                           (const_int 16)))
1868
                 (match_operand:SI 3 "s_register_operand" "r")))]
1869
  "TARGET_DSP_MULTIPLY"
1870
  "smlatt%?\\t%0, %1, %2, %3"
1871
  [(set_attr "insn" "smlaxy")
1872
   (set_attr "predicable" "yes")]
1873
)
1874
 
1875
(define_insn "maddhidi4"
1876
  [(set (match_operand:DI 0 "s_register_operand" "=r")
1877
        (plus:DI
1878
          (mult:DI (sign_extend:DI
1879
                    (match_operand:HI 1 "s_register_operand" "r"))
1880
                   (sign_extend:DI
1881
                    (match_operand:HI 2 "s_register_operand" "r")))
1882
          (match_operand:DI 3 "s_register_operand" "0")))]
1883
  "TARGET_DSP_MULTIPLY"
1884
  "smlalbb%?\\t%Q0, %R0, %1, %2"
1885
  [(set_attr "insn" "smlalxy")
1886
   (set_attr "predicable" "yes")])
1887
 
1888
;; Note: there is no maddhidi4ibt because this one is canonical form
1889
(define_insn "*maddhidi4tb"
1890
  [(set (match_operand:DI 0 "s_register_operand" "=r")
1891
        (plus:DI
1892
          (mult:DI (sign_extend:DI
1893
                    (ashiftrt:SI
1894
                     (match_operand:SI 1 "s_register_operand" "r")
1895
                     (const_int 16)))
1896
                   (sign_extend:DI
1897
                    (match_operand:HI 2 "s_register_operand" "r")))
1898
          (match_operand:DI 3 "s_register_operand" "0")))]
1899
  "TARGET_DSP_MULTIPLY"
1900
  "smlaltb%?\\t%Q0, %R0, %1, %2"
1901
  [(set_attr "insn" "smlalxy")
1902
   (set_attr "predicable" "yes")])
1903
 
1904
(define_insn "*maddhidi4tt"
1905
  [(set (match_operand:DI 0 "s_register_operand" "=r")
1906
        (plus:DI
1907
          (mult:DI (sign_extend:DI
1908
                    (ashiftrt:SI
1909
                     (match_operand:SI 1 "s_register_operand" "r")
1910
                     (const_int 16)))
1911
                   (sign_extend:DI
1912
                    (ashiftrt:SI
1913
                     (match_operand:SI 2 "s_register_operand" "r")
1914
                     (const_int 16))))
1915
          (match_operand:DI 3 "s_register_operand" "0")))]
1916
  "TARGET_DSP_MULTIPLY"
1917
  "smlaltt%?\\t%Q0, %R0, %1, %2"
1918
  [(set_attr "insn" "smlalxy")
1919
   (set_attr "predicable" "yes")])
1920
 
1921
(define_expand "mulsf3"
1922
  [(set (match_operand:SF          0 "s_register_operand" "")
1923
        (mult:SF (match_operand:SF 1 "s_register_operand" "")
1924
                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1925
  "TARGET_32BIT && TARGET_HARD_FLOAT"
1926
  "
1927
  if (TARGET_MAVERICK
1928
      && !cirrus_fp_register (operands[2], SFmode))
1929
    operands[2] = force_reg (SFmode, operands[2]);
1930
")
1931
 
1932
(define_expand "muldf3"
1933
  [(set (match_operand:DF          0 "s_register_operand" "")
1934
        (mult:DF (match_operand:DF 1 "s_register_operand" "")
1935
                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1936
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
1937
  "
1938
  if (TARGET_MAVERICK
1939
      && !cirrus_fp_register (operands[2], DFmode))
1940
    operands[2] = force_reg (DFmode, operands[2]);
1941
")
1942
 
1943
;; Division insns
1944
 
1945
(define_expand "divsf3"
1946
  [(set (match_operand:SF 0 "s_register_operand" "")
1947
        (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1948
                (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1949
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1950
  "")
1951
 
1952
(define_expand "divdf3"
1953
  [(set (match_operand:DF 0 "s_register_operand" "")
1954
        (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1955
                (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1956
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
1957
  "")
1958
 
1959
;; Modulo insns
1960
 
1961
(define_expand "modsf3"
1962
  [(set (match_operand:SF 0 "s_register_operand" "")
1963
        (mod:SF (match_operand:SF 1 "s_register_operand" "")
1964
                (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1965
  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1966
  "")
1967
 
1968
(define_expand "moddf3"
1969
  [(set (match_operand:DF 0 "s_register_operand" "")
1970
        (mod:DF (match_operand:DF 1 "s_register_operand" "")
1971
                (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1972
  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
1973
  "")
1974
 
1975
;; Boolean and,ior,xor insns
1976
 
1977
;; Split up double word logical operations
1978
 
1979
;; Split up simple DImode logical operations.  Simply perform the logical
1980
;; operation on the upper and lower halves of the registers.
1981
(define_split
1982
  [(set (match_operand:DI 0 "s_register_operand" "")
1983
        (match_operator:DI 6 "logical_binary_operator"
1984
          [(match_operand:DI 1 "s_register_operand" "")
1985
           (match_operand:DI 2 "s_register_operand" "")]))]
1986
  "TARGET_32BIT && reload_completed
1987
   && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
1988
   && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1989
  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1990
   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1991
  "
1992
  {
1993
    operands[3] = gen_highpart (SImode, operands[0]);
1994
    operands[0] = gen_lowpart (SImode, operands[0]);
1995
    operands[4] = gen_highpart (SImode, operands[1]);
1996
    operands[1] = gen_lowpart (SImode, operands[1]);
1997
    operands[5] = gen_highpart (SImode, operands[2]);
1998
    operands[2] = gen_lowpart (SImode, operands[2]);
1999
  }"
2000
)
2001
 
2002
(define_split
2003
  [(set (match_operand:DI 0 "s_register_operand" "")
2004
        (match_operator:DI 6 "logical_binary_operator"
2005
          [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2006
           (match_operand:DI 1 "s_register_operand" "")]))]
2007
  "TARGET_32BIT && reload_completed"
2008
  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
2009
   (set (match_dup 3) (match_op_dup:SI 6
2010
                        [(ashiftrt:SI (match_dup 2) (const_int 31))
2011
                         (match_dup 4)]))]
2012
  "
2013
  {
2014
    operands[3] = gen_highpart (SImode, operands[0]);
2015
    operands[0] = gen_lowpart (SImode, operands[0]);
2016
    operands[4] = gen_highpart (SImode, operands[1]);
2017
    operands[1] = gen_lowpart (SImode, operands[1]);
2018
    operands[5] = gen_highpart (SImode, operands[2]);
2019
    operands[2] = gen_lowpart (SImode, operands[2]);
2020
  }"
2021
)
2022
 
2023
;; The zero extend of operand 2 means we can just copy the high part of
2024
;; operand1 into operand0.
2025
(define_split
2026
  [(set (match_operand:DI 0 "s_register_operand" "")
2027
        (ior:DI
2028
          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2029
          (match_operand:DI 1 "s_register_operand" "")))]
2030
  "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2031
  [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
2032
   (set (match_dup 3) (match_dup 4))]
2033
  "
2034
  {
2035
    operands[4] = gen_highpart (SImode, operands[1]);
2036
    operands[3] = gen_highpart (SImode, operands[0]);
2037
    operands[0] = gen_lowpart (SImode, operands[0]);
2038
    operands[1] = gen_lowpart (SImode, operands[1]);
2039
  }"
2040
)
2041
 
2042
;; The zero extend of operand 2 means we can just copy the high part of
2043
;; operand1 into operand0.
2044
(define_split
2045
  [(set (match_operand:DI 0 "s_register_operand" "")
2046
        (xor:DI
2047
          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
2048
          (match_operand:DI 1 "s_register_operand" "")))]
2049
  "TARGET_32BIT && operands[0] != operands[1] && reload_completed"
2050
  [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
2051
   (set (match_dup 3) (match_dup 4))]
2052
  "
2053
  {
2054
    operands[4] = gen_highpart (SImode, operands[1]);
2055
    operands[3] = gen_highpart (SImode, operands[0]);
2056
    operands[0] = gen_lowpart (SImode, operands[0]);
2057
    operands[1] = gen_lowpart (SImode, operands[1]);
2058
  }"
2059
)
2060
 
2061
(define_expand "anddi3"
2062
  [(set (match_operand:DI         0 "s_register_operand" "")
2063
        (and:DI (match_operand:DI 1 "s_register_operand" "")
2064
                (match_operand:DI 2 "neon_inv_logic_op2" "")))]
2065
  "TARGET_32BIT"
2066
  ""
2067
)
2068
 
2069
(define_insn "*anddi3_insn"
2070
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2071
        (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2072
                (match_operand:DI 2 "s_register_operand"   "r,r")))]
2073
  "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2074
  "#"
2075
  [(set_attr "length" "8")]
2076
)
2077
 
2078
(define_insn_and_split "*anddi_zesidi_di"
2079
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2080
        (and:DI (zero_extend:DI
2081
                 (match_operand:SI 2 "s_register_operand" "r,r"))
2082
                (match_operand:DI 1 "s_register_operand" "0,r")))]
2083
  "TARGET_32BIT"
2084
  "#"
2085
  "TARGET_32BIT && reload_completed"
2086
  ; The zero extend of operand 2 clears the high word of the output
2087
  ; operand.
2088
  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
2089
   (set (match_dup 3) (const_int 0))]
2090
  "
2091
  {
2092
    operands[3] = gen_highpart (SImode, operands[0]);
2093
    operands[0] = gen_lowpart (SImode, operands[0]);
2094
    operands[1] = gen_lowpart (SImode, operands[1]);
2095
  }"
2096
  [(set_attr "length" "8")]
2097
)
2098
 
2099
(define_insn "*anddi_sesdi_di"
2100
  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
2101
        (and:DI (sign_extend:DI
2102
                 (match_operand:SI 2 "s_register_operand" "r,r"))
2103
                (match_operand:DI  1 "s_register_operand" "0,r")))]
2104
  "TARGET_32BIT"
2105
  "#"
2106
  [(set_attr "length" "8")]
2107
)
2108
 
2109
(define_expand "andsi3"
2110
  [(set (match_operand:SI         0 "s_register_operand" "")
2111
        (and:SI (match_operand:SI 1 "s_register_operand" "")
2112
                (match_operand:SI 2 "reg_or_int_operand" "")))]
2113
  "TARGET_EITHER"
2114
  "
2115
  if (TARGET_32BIT)
2116
    {
2117
      if (GET_CODE (operands[2]) == CONST_INT)
2118
        {
2119
          if (INTVAL (operands[2]) == 255 && arm_arch6)
2120
            {
2121
              operands[1] = convert_to_mode (QImode, operands[1], 1);
2122
              emit_insn (gen_thumb2_zero_extendqisi2_v6 (operands[0],
2123
                                                         operands[1]));
2124
            }
2125
          else
2126
            arm_split_constant (AND, SImode, NULL_RTX,
2127
                                INTVAL (operands[2]), operands[0],
2128
                                operands[1],
2129
                                optimize && can_create_pseudo_p ());
2130
 
2131
          DONE;
2132
        }
2133
    }
2134
  else /* TARGET_THUMB1 */
2135
    {
2136
      if (GET_CODE (operands[2]) != CONST_INT)
2137
        {
2138
          rtx tmp = force_reg (SImode, operands[2]);
2139
          if (rtx_equal_p (operands[0], operands[1]))
2140
            operands[2] = tmp;
2141
          else
2142
            {
2143
              operands[2] = operands[1];
2144
              operands[1] = tmp;
2145
            }
2146
        }
2147
      else
2148
        {
2149
          int i;
2150
 
2151
          if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
2152
            {
2153
              operands[2] = force_reg (SImode,
2154
                                       GEN_INT (~INTVAL (operands[2])));
2155
 
2156
              emit_insn (gen_thumb1_bicsi3 (operands[0], operands[2], operands[1]));
2157
 
2158
              DONE;
2159
            }
2160
 
2161
          for (i = 9; i <= 31; i++)
2162
            {
2163
              if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
2164
                {
2165
                  emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
2166
                                        const0_rtx));
2167
                  DONE;
2168
                }
2169
              else if ((((HOST_WIDE_INT) 1) << i) - 1
2170
                       == ~INTVAL (operands[2]))
2171
                {
2172
                  rtx shift = GEN_INT (i);
2173
                  rtx reg = gen_reg_rtx (SImode);
2174
 
2175
                  emit_insn (gen_lshrsi3 (reg, operands[1], shift));
2176
                  emit_insn (gen_ashlsi3 (operands[0], reg, shift));
2177
 
2178
                  DONE;
2179
                }
2180
            }
2181
 
2182
          operands[2] = force_reg (SImode, operands[2]);
2183
        }
2184
    }
2185
  "
2186
)
2187
 
2188
; ??? Check split length for Thumb-2
2189
(define_insn_and_split "*arm_andsi3_insn"
2190
  [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
2191
        (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
2192
                (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2193
  "TARGET_32BIT"
2194
  "@
2195
   and%?\\t%0, %1, %2
2196
   bic%?\\t%0, %1, #%B2
2197
   #"
2198
  "TARGET_32BIT
2199
   && GET_CODE (operands[2]) == CONST_INT
2200
   && !(const_ok_for_arm (INTVAL (operands[2]))
2201
        || const_ok_for_arm (~INTVAL (operands[2])))"
2202
  [(clobber (const_int 0))]
2203
  "
2204
  arm_split_constant  (AND, SImode, curr_insn,
2205
                       INTVAL (operands[2]), operands[0], operands[1], 0);
2206
  DONE;
2207
  "
2208
  [(set_attr "length" "4,4,16")
2209
   (set_attr "predicable" "yes")]
2210
)
2211
 
2212
(define_insn "*thumb1_andsi3_insn"
2213
  [(set (match_operand:SI         0 "register_operand" "=l")
2214
        (and:SI (match_operand:SI 1 "register_operand" "%0")
2215
                (match_operand:SI 2 "register_operand" "l")))]
2216
  "TARGET_THUMB1"
2217
  "and\\t%0, %2"
2218
  [(set_attr "length" "2")
2219
   (set_attr "conds" "set")])
2220
 
2221
(define_insn "*andsi3_compare0"
2222
  [(set (reg:CC_NOOV CC_REGNUM)
2223
        (compare:CC_NOOV
2224
         (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
2225
                 (match_operand:SI 2 "arm_not_operand" "rI,K"))
2226
         (const_int 0)))
2227
   (set (match_operand:SI          0 "s_register_operand" "=r,r")
2228
        (and:SI (match_dup 1) (match_dup 2)))]
2229
  "TARGET_32BIT"
2230
  "@
2231
   and%.\\t%0, %1, %2
2232
   bic%.\\t%0, %1, #%B2"
2233
  [(set_attr "conds" "set")]
2234
)
2235
 
2236
(define_insn "*andsi3_compare0_scratch"
2237
  [(set (reg:CC_NOOV CC_REGNUM)
2238
        (compare:CC_NOOV
2239
         (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
2240
                 (match_operand:SI 1 "arm_not_operand" "rI,K"))
2241
         (const_int 0)))
2242
   (clobber (match_scratch:SI 2 "=X,r"))]
2243
  "TARGET_32BIT"
2244
  "@
2245
   tst%?\\t%0, %1
2246
   bic%.\\t%2, %0, #%B1"
2247
  [(set_attr "conds" "set")]
2248
)
2249
 
2250
(define_insn "*zeroextractsi_compare0_scratch"
2251
  [(set (reg:CC_NOOV CC_REGNUM)
2252
        (compare:CC_NOOV (zero_extract:SI
2253
                          (match_operand:SI 0 "s_register_operand" "r")
2254
                          (match_operand 1 "const_int_operand" "n")
2255
                          (match_operand 2 "const_int_operand" "n"))
2256
                         (const_int 0)))]
2257
  "TARGET_32BIT
2258
  && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
2259
      && INTVAL (operands[1]) > 0
2260
      && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
2261
      && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
2262
  "*
2263
  operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
2264
                         << INTVAL (operands[2]));
2265
  output_asm_insn (\"tst%?\\t%0, %1\", operands);
2266
  return \"\";
2267
  "
2268
  [(set_attr "conds" "set")
2269
   (set_attr "predicable" "yes")]
2270
)
2271
 
2272
(define_insn_and_split "*ne_zeroextractsi"
2273
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2274
        (ne:SI (zero_extract:SI
2275
                (match_operand:SI 1 "s_register_operand" "r")
2276
                (match_operand:SI 2 "const_int_operand" "n")
2277
                (match_operand:SI 3 "const_int_operand" "n"))
2278
               (const_int 0)))
2279
   (clobber (reg:CC CC_REGNUM))]
2280
  "TARGET_32BIT
2281
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2282
       && INTVAL (operands[2]) > 0
2283
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2284
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2285
  "#"
2286
  "TARGET_32BIT
2287
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2288
       && INTVAL (operands[2]) > 0
2289
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2290
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
2291
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2292
                   (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2293
                                    (const_int 0)))
2294
              (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2295
   (set (match_dup 0)
2296
        (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2297
                         (match_dup 0) (const_int 1)))]
2298
  "
2299
  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2300
                         << INTVAL (operands[3]));
2301
  "
2302
  [(set_attr "conds" "clob")
2303
   (set (attr "length")
2304
        (if_then_else (eq_attr "is_thumb" "yes")
2305
                      (const_int 12)
2306
                      (const_int 8)))]
2307
)
2308
 
2309
(define_insn_and_split "*ne_zeroextractsi_shifted"
2310
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2311
        (ne:SI (zero_extract:SI
2312
                (match_operand:SI 1 "s_register_operand" "r")
2313
                (match_operand:SI 2 "const_int_operand" "n")
2314
                (const_int 0))
2315
               (const_int 0)))
2316
   (clobber (reg:CC CC_REGNUM))]
2317
  "TARGET_ARM"
2318
  "#"
2319
  "TARGET_ARM"
2320
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2321
                   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2322
                                    (const_int 0)))
2323
              (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2324
   (set (match_dup 0)
2325
        (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2326
                         (match_dup 0) (const_int 1)))]
2327
  "
2328
  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2329
  "
2330
  [(set_attr "conds" "clob")
2331
   (set_attr "length" "8")]
2332
)
2333
 
2334
(define_insn_and_split "*ite_ne_zeroextractsi"
2335
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2336
        (if_then_else:SI (ne (zero_extract:SI
2337
                              (match_operand:SI 1 "s_register_operand" "r")
2338
                              (match_operand:SI 2 "const_int_operand" "n")
2339
                              (match_operand:SI 3 "const_int_operand" "n"))
2340
                             (const_int 0))
2341
                         (match_operand:SI 4 "arm_not_operand" "rIK")
2342
                         (const_int 0)))
2343
   (clobber (reg:CC CC_REGNUM))]
2344
  "TARGET_ARM
2345
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2346
       && INTVAL (operands[2]) > 0
2347
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2348
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2349
   && !reg_overlap_mentioned_p (operands[0], operands[4])"
2350
  "#"
2351
  "TARGET_ARM
2352
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
2353
       && INTVAL (operands[2]) > 0
2354
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
2355
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
2356
   && !reg_overlap_mentioned_p (operands[0], operands[4])"
2357
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2358
                   (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
2359
                                    (const_int 0)))
2360
              (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
2361
   (set (match_dup 0)
2362
        (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2363
                         (match_dup 0) (match_dup 4)))]
2364
  "
2365
  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
2366
                         << INTVAL (operands[3]));
2367
  "
2368
  [(set_attr "conds" "clob")
2369
   (set_attr "length" "8")]
2370
)
2371
 
2372
(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
2373
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2374
        (if_then_else:SI (ne (zero_extract:SI
2375
                              (match_operand:SI 1 "s_register_operand" "r")
2376
                              (match_operand:SI 2 "const_int_operand" "n")
2377
                              (const_int 0))
2378
                             (const_int 0))
2379
                         (match_operand:SI 3 "arm_not_operand" "rIK")
2380
                         (const_int 0)))
2381
   (clobber (reg:CC CC_REGNUM))]
2382
  "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2383
  "#"
2384
  "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
2385
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
2386
                   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
2387
                                    (const_int 0)))
2388
              (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
2389
   (set (match_dup 0)
2390
        (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
2391
                         (match_dup 0) (match_dup 3)))]
2392
  "
2393
  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
2394
  "
2395
  [(set_attr "conds" "clob")
2396
   (set_attr "length" "8")]
2397
)
2398
 
2399
(define_split
2400
  [(set (match_operand:SI 0 "s_register_operand" "")
2401
        (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
2402
                         (match_operand:SI 2 "const_int_operand" "")
2403
                         (match_operand:SI 3 "const_int_operand" "")))
2404
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
2405
  "TARGET_THUMB1"
2406
  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
2407
   (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
2408
  "{
2409
     HOST_WIDE_INT temp = INTVAL (operands[2]);
2410
 
2411
     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2412
     operands[3] = GEN_INT (32 - temp);
2413
   }"
2414
)
2415
 
2416
;; ??? Use Thumb-2 has bitfield insert/extract instructions.
2417
(define_split
2418
  [(set (match_operand:SI 0 "s_register_operand" "")
2419
        (match_operator:SI 1 "shiftable_operator"
2420
         [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2421
                           (match_operand:SI 3 "const_int_operand" "")
2422
                           (match_operand:SI 4 "const_int_operand" ""))
2423
          (match_operand:SI 5 "s_register_operand" "")]))
2424
   (clobber (match_operand:SI 6 "s_register_operand" ""))]
2425
  "TARGET_ARM"
2426
  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2427
   (set (match_dup 0)
2428
        (match_op_dup 1
2429
         [(lshiftrt:SI (match_dup 6) (match_dup 4))
2430
          (match_dup 5)]))]
2431
  "{
2432
     HOST_WIDE_INT temp = INTVAL (operands[3]);
2433
 
2434
     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2435
     operands[4] = GEN_INT (32 - temp);
2436
   }"
2437
)
2438
 
2439
(define_split
2440
  [(set (match_operand:SI 0 "s_register_operand" "")
2441
        (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
2442
                         (match_operand:SI 2 "const_int_operand" "")
2443
                         (match_operand:SI 3 "const_int_operand" "")))]
2444
  "TARGET_THUMB1"
2445
  [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
2446
   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
2447
  "{
2448
     HOST_WIDE_INT temp = INTVAL (operands[2]);
2449
 
2450
     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
2451
     operands[3] = GEN_INT (32 - temp);
2452
   }"
2453
)
2454
 
2455
(define_split
2456
  [(set (match_operand:SI 0 "s_register_operand" "")
2457
        (match_operator:SI 1 "shiftable_operator"
2458
         [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2459
                           (match_operand:SI 3 "const_int_operand" "")
2460
                           (match_operand:SI 4 "const_int_operand" ""))
2461
          (match_operand:SI 5 "s_register_operand" "")]))
2462
   (clobber (match_operand:SI 6 "s_register_operand" ""))]
2463
  "TARGET_ARM"
2464
  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
2465
   (set (match_dup 0)
2466
        (match_op_dup 1
2467
         [(ashiftrt:SI (match_dup 6) (match_dup 4))
2468
          (match_dup 5)]))]
2469
  "{
2470
     HOST_WIDE_INT temp = INTVAL (operands[3]);
2471
 
2472
     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
2473
     operands[4] = GEN_INT (32 - temp);
2474
   }"
2475
)
2476
 
2477
;;; ??? This pattern is bogus.  If operand3 has bits outside the range
2478
;;; represented by the bitfield, then this will produce incorrect results.
2479
;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
2480
;;; which have a real bit-field insert instruction, the truncation happens
2481
;;; in the bit-field insert instruction itself.  Since arm does not have a
2482
;;; bit-field insert instruction, we would have to emit code here to truncate
2483
;;; the value before we insert.  This loses some of the advantage of having
2484
;;; this insv pattern, so this pattern needs to be reevalutated.
2485
 
2486
(define_expand "insv"
2487
  [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
2488
                      (match_operand 1 "general_operand" "")
2489
                      (match_operand 2 "general_operand" ""))
2490
        (match_operand 3 "reg_or_int_operand" ""))]
2491
  "TARGET_ARM || arm_arch_thumb2"
2492
  "
2493
  {
2494
    int start_bit = INTVAL (operands[2]);
2495
    int width = INTVAL (operands[1]);
2496
    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
2497
    rtx target, subtarget;
2498
 
2499
    if (arm_arch_thumb2)
2500
      {
2501
        if (unaligned_access && MEM_P (operands[0])
2502
            && s_register_operand (operands[3], GET_MODE (operands[3]))
2503
            && (width == 16 || width == 32) && (start_bit % BITS_PER_UNIT) == 0)
2504
          {
2505
            rtx base_addr;
2506
 
2507
            if (BYTES_BIG_ENDIAN)
2508
              start_bit = GET_MODE_BITSIZE (GET_MODE (operands[3])) - width
2509
                          - start_bit;
2510
 
2511
            if (width == 32)
2512
              {
2513
                base_addr = adjust_address (operands[0], SImode,
2514
                                            start_bit / BITS_PER_UNIT);
2515
                emit_insn (gen_unaligned_storesi (base_addr, operands[3]));
2516
              }
2517
            else
2518
              {
2519
                rtx tmp = gen_reg_rtx (HImode);
2520
 
2521
                base_addr = adjust_address (operands[0], HImode,
2522
                                            start_bit / BITS_PER_UNIT);
2523
                emit_move_insn (tmp, gen_lowpart (HImode, operands[3]));
2524
                emit_insn (gen_unaligned_storehi (base_addr, tmp));
2525
              }
2526
            DONE;
2527
          }
2528
        else if (s_register_operand (operands[0], GET_MODE (operands[0])))
2529
          {
2530
            bool use_bfi = TRUE;
2531
 
2532
            if (GET_CODE (operands[3]) == CONST_INT)
2533
              {
2534
                HOST_WIDE_INT val = INTVAL (operands[3]) & mask;
2535
 
2536
                if (val == 0)
2537
                  {
2538
                    emit_insn (gen_insv_zero (operands[0], operands[1],
2539
                                              operands[2]));
2540
                    DONE;
2541
                  }
2542
 
2543
                /* See if the set can be done with a single orr instruction.  */
2544
                if (val == mask && const_ok_for_arm (val << start_bit))
2545
                  use_bfi = FALSE;
2546
              }
2547
 
2548
            if (use_bfi)
2549
              {
2550
                if (GET_CODE (operands[3]) != REG)
2551
                  operands[3] = force_reg (SImode, operands[3]);
2552
 
2553
                emit_insn (gen_insv_t2 (operands[0], operands[1], operands[2],
2554
                                        operands[3]));
2555
                DONE;
2556
              }
2557
          }
2558
        else
2559
          FAIL;
2560
      }
2561
 
2562
    if (!s_register_operand (operands[0], GET_MODE (operands[0])))
2563
      FAIL;
2564
 
2565
    target = copy_rtx (operands[0]);
2566
    /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
2567
       subreg as the final target.  */
2568
    if (GET_CODE (target) == SUBREG)
2569
      {
2570
        subtarget = gen_reg_rtx (SImode);
2571
        if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
2572
            < GET_MODE_SIZE (SImode))
2573
          target = SUBREG_REG (target);
2574
      }
2575
    else
2576
      subtarget = target;
2577
 
2578
    if (GET_CODE (operands[3]) == CONST_INT)
2579
      {
2580
        /* Since we are inserting a known constant, we may be able to
2581
           reduce the number of bits that we have to clear so that
2582
           the mask becomes simple.  */
2583
        /* ??? This code does not check to see if the new mask is actually
2584
           simpler.  It may not be.  */
2585
        rtx op1 = gen_reg_rtx (SImode);
2586
        /* ??? Truncate operand3 to fit in the bitfield.  See comment before
2587
           start of this pattern.  */
2588
        HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
2589
        HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
2590
 
2591
        emit_insn (gen_andsi3 (op1, operands[0],
2592
                               gen_int_mode (~mask2, SImode)));
2593
        emit_insn (gen_iorsi3 (subtarget, op1,
2594
                               gen_int_mode (op3_value << start_bit, SImode)));
2595
      }
2596
    else if (start_bit == 0
2597
             && !(const_ok_for_arm (mask)
2598
                  || const_ok_for_arm (~mask)))
2599
      {
2600
        /* A Trick, since we are setting the bottom bits in the word,
2601
           we can shift operand[3] up, operand[0] down, OR them together
2602
           and rotate the result back again.  This takes 3 insns, and
2603
           the third might be mergeable into another op.  */
2604
        /* The shift up copes with the possibility that operand[3] is
2605
           wider than the bitfield.  */
2606
        rtx op0 = gen_reg_rtx (SImode);
2607
        rtx op1 = gen_reg_rtx (SImode);
2608
 
2609
        emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2610
        emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
2611
        emit_insn (gen_iorsi3  (op1, op1, op0));
2612
        emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
2613
      }
2614
    else if ((width + start_bit == 32)
2615
             && !(const_ok_for_arm (mask)
2616
                  || const_ok_for_arm (~mask)))
2617
      {
2618
        /* Similar trick, but slightly less efficient.  */
2619
 
2620
        rtx op0 = gen_reg_rtx (SImode);
2621
        rtx op1 = gen_reg_rtx (SImode);
2622
 
2623
        emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
2624
        emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
2625
        emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
2626
        emit_insn (gen_iorsi3 (subtarget, op1, op0));
2627
      }
2628
    else
2629
      {
2630
        rtx op0 = gen_int_mode (mask, SImode);
2631
        rtx op1 = gen_reg_rtx (SImode);
2632
        rtx op2 = gen_reg_rtx (SImode);
2633
 
2634
        if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
2635
          {
2636
            rtx tmp = gen_reg_rtx (SImode);
2637
 
2638
            emit_insn (gen_movsi (tmp, op0));
2639
            op0 = tmp;
2640
          }
2641
 
2642
        /* Mask out any bits in operand[3] that are not needed.  */
2643
           emit_insn (gen_andsi3 (op1, operands[3], op0));
2644
 
2645
        if (GET_CODE (op0) == CONST_INT
2646
            && (const_ok_for_arm (mask << start_bit)
2647
                || const_ok_for_arm (~(mask << start_bit))))
2648
          {
2649
            op0 = gen_int_mode (~(mask << start_bit), SImode);
2650
            emit_insn (gen_andsi3 (op2, operands[0], op0));
2651
          }
2652
        else
2653
          {
2654
            if (GET_CODE (op0) == CONST_INT)
2655
              {
2656
                rtx tmp = gen_reg_rtx (SImode);
2657
 
2658
                emit_insn (gen_movsi (tmp, op0));
2659
                op0 = tmp;
2660
              }
2661
 
2662
            if (start_bit != 0)
2663
              emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
2664
 
2665
            emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
2666
          }
2667
 
2668
        if (start_bit != 0)
2669
          emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
2670
 
2671
        emit_insn (gen_iorsi3 (subtarget, op1, op2));
2672
      }
2673
 
2674
    if (subtarget != target)
2675
      {
2676
        /* If TARGET is still a SUBREG, then it must be wider than a word,
2677
           so we must be careful only to set the subword we were asked to.  */
2678
        if (GET_CODE (target) == SUBREG)
2679
          emit_move_insn (target, subtarget);
2680
        else
2681
          emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
2682
      }
2683
 
2684
    DONE;
2685
  }"
2686
)
2687
 
2688
(define_insn "insv_zero"
2689
  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2690
                         (match_operand:SI 1 "const_int_operand" "M")
2691
                         (match_operand:SI 2 "const_int_operand" "M"))
2692
        (const_int 0))]
2693
  "arm_arch_thumb2"
2694
  "bfc%?\t%0, %2, %1"
2695
  [(set_attr "length" "4")
2696
   (set_attr "predicable" "yes")]
2697
)
2698
 
2699
(define_insn "insv_t2"
2700
  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
2701
                         (match_operand:SI 1 "const_int_operand" "M")
2702
                         (match_operand:SI 2 "const_int_operand" "M"))
2703
        (match_operand:SI 3 "s_register_operand" "r"))]
2704
  "arm_arch_thumb2"
2705
  "bfi%?\t%0, %3, %2, %1"
2706
  [(set_attr "length" "4")
2707
   (set_attr "predicable" "yes")]
2708
)
2709
 
2710
; constants for op 2 will never be given to these patterns.
2711
(define_insn_and_split "*anddi_notdi_di"
2712
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2713
        (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "0,r"))
2714
                (match_operand:DI 2 "s_register_operand" "r,0")))]
2715
  "TARGET_32BIT"
2716
  "#"
2717
  "TARGET_32BIT && reload_completed
2718
   && ! (TARGET_NEON && IS_VFP_REGNUM (REGNO (operands[0])))
2719
   && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2720
  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2721
   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2722
  "
2723
  {
2724
    operands[3] = gen_highpart (SImode, operands[0]);
2725
    operands[0] = gen_lowpart (SImode, operands[0]);
2726
    operands[4] = gen_highpart (SImode, operands[1]);
2727
    operands[1] = gen_lowpart (SImode, operands[1]);
2728
    operands[5] = gen_highpart (SImode, operands[2]);
2729
    operands[2] = gen_lowpart (SImode, operands[2]);
2730
  }"
2731
  [(set_attr "length" "8")
2732
   (set_attr "predicable" "yes")]
2733
)
2734
 
2735
(define_insn_and_split "*anddi_notzesidi_di"
2736
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2737
        (and:DI (not:DI (zero_extend:DI
2738
                         (match_operand:SI 2 "s_register_operand" "r,r")))
2739
                (match_operand:DI 1 "s_register_operand" "0,?r")))]
2740
  "TARGET_32BIT"
2741
  "@
2742
   bic%?\\t%Q0, %Q1, %2
2743
   #"
2744
  ; (not (zero_extend ...)) allows us to just copy the high word from
2745
  ; operand1 to operand0.
2746
  "TARGET_32BIT
2747
   && reload_completed
2748
   && operands[0] != operands[1]"
2749
  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2750
   (set (match_dup 3) (match_dup 4))]
2751
  "
2752
  {
2753
    operands[3] = gen_highpart (SImode, operands[0]);
2754
    operands[0] = gen_lowpart (SImode, operands[0]);
2755
    operands[4] = gen_highpart (SImode, operands[1]);
2756
    operands[1] = gen_lowpart (SImode, operands[1]);
2757
  }"
2758
  [(set_attr "length" "4,8")
2759
   (set_attr "predicable" "yes")]
2760
)
2761
 
2762
(define_insn_and_split "*anddi_notsesidi_di"
2763
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2764
        (and:DI (not:DI (sign_extend:DI
2765
                         (match_operand:SI 2 "s_register_operand" "r,r")))
2766
                (match_operand:DI 1 "s_register_operand" "0,r")))]
2767
  "TARGET_32BIT"
2768
  "#"
2769
  "TARGET_32BIT && reload_completed"
2770
  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2771
   (set (match_dup 3) (and:SI (not:SI
2772
                                (ashiftrt:SI (match_dup 2) (const_int 31)))
2773
                               (match_dup 4)))]
2774
  "
2775
  {
2776
    operands[3] = gen_highpart (SImode, operands[0]);
2777
    operands[0] = gen_lowpart (SImode, operands[0]);
2778
    operands[4] = gen_highpart (SImode, operands[1]);
2779
    operands[1] = gen_lowpart (SImode, operands[1]);
2780
  }"
2781
  [(set_attr "length" "8")
2782
   (set_attr "predicable" "yes")]
2783
)
2784
 
2785
(define_insn "andsi_notsi_si"
2786
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2787
        (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2788
                (match_operand:SI 1 "s_register_operand" "r")))]
2789
  "TARGET_32BIT"
2790
  "bic%?\\t%0, %1, %2"
2791
  [(set_attr "predicable" "yes")]
2792
)
2793
 
2794
(define_insn "thumb1_bicsi3"
2795
  [(set (match_operand:SI                 0 "register_operand" "=l")
2796
        (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2797
                (match_operand:SI         2 "register_operand" "0")))]
2798
  "TARGET_THUMB1"
2799
  "bic\\t%0, %1"
2800
  [(set_attr "length" "2")
2801
   (set_attr "conds" "set")])
2802
 
2803
(define_insn "andsi_not_shiftsi_si"
2804
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2805
        (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2806
                         [(match_operand:SI 2 "s_register_operand" "r")
2807
                          (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2808
                (match_operand:SI 1 "s_register_operand" "r")))]
2809
  "TARGET_ARM"
2810
  "bic%?\\t%0, %1, %2%S4"
2811
  [(set_attr "predicable" "yes")
2812
   (set_attr "shift" "2")
2813
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2814
                      (const_string "alu_shift")
2815
                      (const_string "alu_shift_reg")))]
2816
)
2817
 
2818
(define_insn "*andsi_notsi_si_compare0"
2819
  [(set (reg:CC_NOOV CC_REGNUM)
2820
        (compare:CC_NOOV
2821
         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2822
                 (match_operand:SI 1 "s_register_operand" "r"))
2823
         (const_int 0)))
2824
   (set (match_operand:SI 0 "s_register_operand" "=r")
2825
        (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2826
  "TARGET_32BIT"
2827
  "bic%.\\t%0, %1, %2"
2828
  [(set_attr "conds" "set")]
2829
)
2830
 
2831
(define_insn "*andsi_notsi_si_compare0_scratch"
2832
  [(set (reg:CC_NOOV CC_REGNUM)
2833
        (compare:CC_NOOV
2834
         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2835
                 (match_operand:SI 1 "s_register_operand" "r"))
2836
         (const_int 0)))
2837
   (clobber (match_scratch:SI 0 "=r"))]
2838
  "TARGET_32BIT"
2839
  "bic%.\\t%0, %1, %2"
2840
  [(set_attr "conds" "set")]
2841
)
2842
 
2843
(define_expand "iordi3"
2844
  [(set (match_operand:DI         0 "s_register_operand" "")
2845
        (ior:DI (match_operand:DI 1 "s_register_operand" "")
2846
                (match_operand:DI 2 "neon_logic_op2" "")))]
2847
  "TARGET_32BIT"
2848
  ""
2849
)
2850
 
2851
(define_insn "*iordi3_insn"
2852
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2853
        (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2854
                (match_operand:DI 2 "s_register_operand"   "r,r")))]
2855
  "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2856
  "#"
2857
  [(set_attr "length" "8")
2858
   (set_attr "predicable" "yes")]
2859
)
2860
 
2861
(define_insn "*iordi_zesidi_di"
2862
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2863
        (ior:DI (zero_extend:DI
2864
                 (match_operand:SI 2 "s_register_operand" "r,r"))
2865
                (match_operand:DI 1 "s_register_operand" "0,?r")))]
2866
  "TARGET_32BIT"
2867
  "@
2868
   orr%?\\t%Q0, %Q1, %2
2869
   #"
2870
  [(set_attr "length" "4,8")
2871
   (set_attr "predicable" "yes")]
2872
)
2873
 
2874
(define_insn "*iordi_sesidi_di"
2875
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2876
        (ior:DI (sign_extend:DI
2877
                 (match_operand:SI 2 "s_register_operand" "r,r"))
2878
                (match_operand:DI 1 "s_register_operand" "0,r")))]
2879
  "TARGET_32BIT"
2880
  "#"
2881
  [(set_attr "length" "8")
2882
   (set_attr "predicable" "yes")]
2883
)
2884
 
2885
(define_expand "iorsi3"
2886
  [(set (match_operand:SI         0 "s_register_operand" "")
2887
        (ior:SI (match_operand:SI 1 "s_register_operand" "")
2888
                (match_operand:SI 2 "reg_or_int_operand" "")))]
2889
  "TARGET_EITHER"
2890
  "
2891
  if (GET_CODE (operands[2]) == CONST_INT)
2892
    {
2893
      if (TARGET_32BIT)
2894
        {
2895
          arm_split_constant (IOR, SImode, NULL_RTX,
2896
                              INTVAL (operands[2]), operands[0], operands[1],
2897
                              optimize && can_create_pseudo_p ());
2898
          DONE;
2899
        }
2900
      else /* TARGET_THUMB1 */
2901
        {
2902
          rtx tmp = force_reg (SImode, operands[2]);
2903
          if (rtx_equal_p (operands[0], operands[1]))
2904
            operands[2] = tmp;
2905
          else
2906
            {
2907
              operands[2] = operands[1];
2908
              operands[1] = tmp;
2909
            }
2910
        }
2911
    }
2912
  "
2913
)
2914
 
2915
(define_insn_and_split "*iorsi3_insn"
2916
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2917
        (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
2918
                (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
2919
  "TARGET_32BIT"
2920
  "@
2921
   orr%?\\t%0, %1, %2
2922
   orn%?\\t%0, %1, #%B2
2923
   #"
2924
  "TARGET_32BIT
2925
   && GET_CODE (operands[2]) == CONST_INT
2926
   && !(const_ok_for_arm (INTVAL (operands[2]))
2927
        || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))"
2928
  [(clobber (const_int 0))]
2929
{
2930
  arm_split_constant (IOR, SImode, curr_insn,
2931
                      INTVAL (operands[2]), operands[0], operands[1], 0);
2932
  DONE;
2933
}
2934
  [(set_attr "length" "4,4,16")
2935
   (set_attr "arch" "32,t2,32")
2936
   (set_attr "predicable" "yes")])
2937
 
2938
(define_insn "*thumb1_iorsi3_insn"
2939
  [(set (match_operand:SI         0 "register_operand" "=l")
2940
        (ior:SI (match_operand:SI 1 "register_operand" "%0")
2941
                (match_operand:SI 2 "register_operand" "l")))]
2942
  "TARGET_THUMB1"
2943
  "orr\\t%0, %2"
2944
  [(set_attr "length" "2")
2945
   (set_attr "conds" "set")])
2946
 
2947
(define_peephole2
2948
  [(match_scratch:SI 3 "r")
2949
   (set (match_operand:SI 0 "arm_general_register_operand" "")
2950
        (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2951
                (match_operand:SI 2 "const_int_operand" "")))]
2952
  "TARGET_ARM
2953
   && !const_ok_for_arm (INTVAL (operands[2]))
2954
   && const_ok_for_arm (~INTVAL (operands[2]))"
2955
  [(set (match_dup 3) (match_dup 2))
2956
   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2957
  ""
2958
)
2959
 
2960
(define_insn "*iorsi3_compare0"
2961
  [(set (reg:CC_NOOV CC_REGNUM)
2962
        (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2963
                                 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2964
                         (const_int 0)))
2965
   (set (match_operand:SI 0 "s_register_operand" "=r")
2966
        (ior:SI (match_dup 1) (match_dup 2)))]
2967
  "TARGET_32BIT"
2968
  "orr%.\\t%0, %1, %2"
2969
  [(set_attr "conds" "set")]
2970
)
2971
 
2972
(define_insn "*iorsi3_compare0_scratch"
2973
  [(set (reg:CC_NOOV CC_REGNUM)
2974
        (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2975
                                 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2976
                         (const_int 0)))
2977
   (clobber (match_scratch:SI 0 "=r"))]
2978
  "TARGET_32BIT"
2979
  "orr%.\\t%0, %1, %2"
2980
  [(set_attr "conds" "set")]
2981
)
2982
 
2983
(define_expand "xordi3"
2984
  [(set (match_operand:DI         0 "s_register_operand" "")
2985
        (xor:DI (match_operand:DI 1 "s_register_operand" "")
2986
                (match_operand:DI 2 "s_register_operand" "")))]
2987
  "TARGET_32BIT"
2988
  ""
2989
)
2990
 
2991
(define_insn "*xordi3_insn"
2992
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2993
        (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2994
                (match_operand:DI 2 "s_register_operand"   "r,r")))]
2995
  "TARGET_32BIT && !TARGET_IWMMXT && !TARGET_NEON"
2996
  "#"
2997
  [(set_attr "length" "8")
2998
   (set_attr "predicable" "yes")]
2999
)
3000
 
3001
(define_insn "*xordi_zesidi_di"
3002
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3003
        (xor:DI (zero_extend:DI
3004
                 (match_operand:SI 2 "s_register_operand" "r,r"))
3005
                (match_operand:DI 1 "s_register_operand" "0,?r")))]
3006
  "TARGET_32BIT"
3007
  "@
3008
   eor%?\\t%Q0, %Q1, %2
3009
   #"
3010
  [(set_attr "length" "4,8")
3011
   (set_attr "predicable" "yes")]
3012
)
3013
 
3014
(define_insn "*xordi_sesidi_di"
3015
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3016
        (xor:DI (sign_extend:DI
3017
                 (match_operand:SI 2 "s_register_operand" "r,r"))
3018
                (match_operand:DI 1 "s_register_operand" "0,r")))]
3019
  "TARGET_32BIT"
3020
  "#"
3021
  [(set_attr "length" "8")
3022
   (set_attr "predicable" "yes")]
3023
)
3024
 
3025
(define_expand "xorsi3"
3026
  [(set (match_operand:SI         0 "s_register_operand" "")
3027
        (xor:SI (match_operand:SI 1 "s_register_operand" "")
3028
                (match_operand:SI 2 "reg_or_int_operand" "")))]
3029
  "TARGET_EITHER"
3030
  "if (GET_CODE (operands[2]) == CONST_INT)
3031
    {
3032
      if (TARGET_32BIT)
3033
        {
3034
          arm_split_constant (XOR, SImode, NULL_RTX,
3035
                              INTVAL (operands[2]), operands[0], operands[1],
3036
                              optimize && can_create_pseudo_p ());
3037
          DONE;
3038
        }
3039
      else /* TARGET_THUMB1 */
3040
        {
3041
          rtx tmp = force_reg (SImode, operands[2]);
3042
          if (rtx_equal_p (operands[0], operands[1]))
3043
            operands[2] = tmp;
3044
          else
3045
            {
3046
              operands[2] = operands[1];
3047
              operands[1] = tmp;
3048
            }
3049
        }
3050
    }"
3051
)
3052
 
3053
(define_insn_and_split "*arm_xorsi3"
3054
  [(set (match_operand:SI         0 "s_register_operand" "=r,r")
3055
        (xor:SI (match_operand:SI 1 "s_register_operand" "%r,r")
3056
                (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
3057
  "TARGET_32BIT"
3058
  "@
3059
   eor%?\\t%0, %1, %2
3060
   #"
3061
  "TARGET_32BIT
3062
   && GET_CODE (operands[2]) == CONST_INT
3063
   && !const_ok_for_arm (INTVAL (operands[2]))"
3064
  [(clobber (const_int 0))]
3065
{
3066
  arm_split_constant (XOR, SImode, curr_insn,
3067
                      INTVAL (operands[2]), operands[0], operands[1], 0);
3068
  DONE;
3069
}
3070
  [(set_attr "length" "4,16")
3071
   (set_attr "predicable" "yes")]
3072
)
3073
 
3074
(define_insn "*thumb1_xorsi3_insn"
3075
  [(set (match_operand:SI         0 "register_operand" "=l")
3076
        (xor:SI (match_operand:SI 1 "register_operand" "%0")
3077
                (match_operand:SI 2 "register_operand" "l")))]
3078
  "TARGET_THUMB1"
3079
  "eor\\t%0, %2"
3080
  [(set_attr "length" "2")
3081
   (set_attr "conds" "set")])
3082
 
3083
(define_insn "*xorsi3_compare0"
3084
  [(set (reg:CC_NOOV CC_REGNUM)
3085
        (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
3086
                                 (match_operand:SI 2 "arm_rhs_operand" "rI"))
3087
                         (const_int 0)))
3088
   (set (match_operand:SI 0 "s_register_operand" "=r")
3089
        (xor:SI (match_dup 1) (match_dup 2)))]
3090
  "TARGET_32BIT"
3091
  "eor%.\\t%0, %1, %2"
3092
  [(set_attr "conds" "set")]
3093
)
3094
 
3095
(define_insn "*xorsi3_compare0_scratch"
3096
  [(set (reg:CC_NOOV CC_REGNUM)
3097
        (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
3098
                                 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3099
                         (const_int 0)))]
3100
  "TARGET_32BIT"
3101
  "teq%?\\t%0, %1"
3102
  [(set_attr "conds" "set")]
3103
)
3104
 
3105
; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
3106
; (NOT D) we can sometimes merge the final NOT into one of the following
3107
; insns.
3108
 
3109
(define_split
3110
  [(set (match_operand:SI 0 "s_register_operand" "")
3111
        (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
3112
                        (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
3113
                (match_operand:SI 3 "arm_rhs_operand" "")))
3114
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
3115
  "TARGET_32BIT"
3116
  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
3117
                              (not:SI (match_dup 3))))
3118
   (set (match_dup 0) (not:SI (match_dup 4)))]
3119
  ""
3120
)
3121
 
3122
(define_insn "*andsi_iorsi3_notsi"
3123
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
3124
        (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "%0,r,r")
3125
                        (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
3126
                (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
3127
  "TARGET_32BIT"
3128
  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
3129
  [(set_attr "length" "8")
3130
   (set_attr "ce_count" "2")
3131
   (set_attr "predicable" "yes")]
3132
)
3133
 
3134
; ??? Are these four splitters still beneficial when the Thumb-2 bitfield
3135
; insns are available?
3136
(define_split
3137
  [(set (match_operand:SI 0 "s_register_operand" "")
3138
        (match_operator:SI 1 "logical_binary_operator"
3139
         [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3140
                           (match_operand:SI 3 "const_int_operand" "")
3141
                           (match_operand:SI 4 "const_int_operand" ""))
3142
          (match_operator:SI 9 "logical_binary_operator"
3143
           [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3144
                         (match_operand:SI 6 "const_int_operand" ""))
3145
            (match_operand:SI 7 "s_register_operand" "")])]))
3146
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
3147
  "TARGET_32BIT
3148
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
3149
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3150
  [(set (match_dup 8)
3151
        (match_op_dup 1
3152
         [(ashift:SI (match_dup 2) (match_dup 4))
3153
          (match_dup 5)]))
3154
   (set (match_dup 0)
3155
        (match_op_dup 1
3156
         [(lshiftrt:SI (match_dup 8) (match_dup 6))
3157
          (match_dup 7)]))]
3158
  "
3159
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3160
")
3161
 
3162
(define_split
3163
  [(set (match_operand:SI 0 "s_register_operand" "")
3164
        (match_operator:SI 1 "logical_binary_operator"
3165
         [(match_operator:SI 9 "logical_binary_operator"
3166
           [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3167
                         (match_operand:SI 6 "const_int_operand" ""))
3168
            (match_operand:SI 7 "s_register_operand" "")])
3169
          (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
3170
                           (match_operand:SI 3 "const_int_operand" "")
3171
                           (match_operand:SI 4 "const_int_operand" ""))]))
3172
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
3173
  "TARGET_32BIT
3174
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
3175
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3176
  [(set (match_dup 8)
3177
        (match_op_dup 1
3178
         [(ashift:SI (match_dup 2) (match_dup 4))
3179
          (match_dup 5)]))
3180
   (set (match_dup 0)
3181
        (match_op_dup 1
3182
         [(lshiftrt:SI (match_dup 8) (match_dup 6))
3183
          (match_dup 7)]))]
3184
  "
3185
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3186
")
3187
 
3188
(define_split
3189
  [(set (match_operand:SI 0 "s_register_operand" "")
3190
        (match_operator:SI 1 "logical_binary_operator"
3191
         [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3192
                           (match_operand:SI 3 "const_int_operand" "")
3193
                           (match_operand:SI 4 "const_int_operand" ""))
3194
          (match_operator:SI 9 "logical_binary_operator"
3195
           [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3196
                         (match_operand:SI 6 "const_int_operand" ""))
3197
            (match_operand:SI 7 "s_register_operand" "")])]))
3198
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
3199
  "TARGET_32BIT
3200
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
3201
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3202
  [(set (match_dup 8)
3203
        (match_op_dup 1
3204
         [(ashift:SI (match_dup 2) (match_dup 4))
3205
          (match_dup 5)]))
3206
   (set (match_dup 0)
3207
        (match_op_dup 1
3208
         [(ashiftrt:SI (match_dup 8) (match_dup 6))
3209
          (match_dup 7)]))]
3210
  "
3211
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3212
")
3213
 
3214
(define_split
3215
  [(set (match_operand:SI 0 "s_register_operand" "")
3216
        (match_operator:SI 1 "logical_binary_operator"
3217
         [(match_operator:SI 9 "logical_binary_operator"
3218
           [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
3219
                         (match_operand:SI 6 "const_int_operand" ""))
3220
            (match_operand:SI 7 "s_register_operand" "")])
3221
          (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
3222
                           (match_operand:SI 3 "const_int_operand" "")
3223
                           (match_operand:SI 4 "const_int_operand" ""))]))
3224
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
3225
  "TARGET_32BIT
3226
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
3227
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
3228
  [(set (match_dup 8)
3229
        (match_op_dup 1
3230
         [(ashift:SI (match_dup 2) (match_dup 4))
3231
          (match_dup 5)]))
3232
   (set (match_dup 0)
3233
        (match_op_dup 1
3234
         [(ashiftrt:SI (match_dup 8) (match_dup 6))
3235
          (match_dup 7)]))]
3236
  "
3237
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
3238
")
3239
 
3240
 
3241
;; Minimum and maximum insns
3242
 
3243
(define_expand "smaxsi3"
3244
  [(parallel [
3245
    (set (match_operand:SI 0 "s_register_operand" "")
3246
         (smax:SI (match_operand:SI 1 "s_register_operand" "")
3247
                  (match_operand:SI 2 "arm_rhs_operand" "")))
3248
    (clobber (reg:CC CC_REGNUM))])]
3249
  "TARGET_32BIT"
3250
  "
3251
  if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
3252
    {
3253
      /* No need for a clobber of the condition code register here.  */
3254
      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3255
                              gen_rtx_SMAX (SImode, operands[1],
3256
                                            operands[2])));
3257
      DONE;
3258
    }
3259
")
3260
 
3261
(define_insn "*smax_0"
3262
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3263
        (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3264
                 (const_int 0)))]
3265
  "TARGET_32BIT"
3266
  "bic%?\\t%0, %1, %1, asr #31"
3267
  [(set_attr "predicable" "yes")]
3268
)
3269
 
3270
(define_insn "*smax_m1"
3271
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3272
        (smax:SI (match_operand:SI 1 "s_register_operand" "r")
3273
                 (const_int -1)))]
3274
  "TARGET_32BIT"
3275
  "orr%?\\t%0, %1, %1, asr #31"
3276
  [(set_attr "predicable" "yes")]
3277
)
3278
 
3279
(define_insn "*arm_smax_insn"
3280
  [(set (match_operand:SI          0 "s_register_operand" "=r,r")
3281
        (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
3282
                 (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
3283
   (clobber (reg:CC CC_REGNUM))]
3284
  "TARGET_ARM"
3285
  "@
3286
   cmp\\t%1, %2\;movlt\\t%0, %2
3287
   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
3288
  [(set_attr "conds" "clob")
3289
   (set_attr "length" "8,12")]
3290
)
3291
 
3292
(define_expand "sminsi3"
3293
  [(parallel [
3294
    (set (match_operand:SI 0 "s_register_operand" "")
3295
         (smin:SI (match_operand:SI 1 "s_register_operand" "")
3296
                  (match_operand:SI 2 "arm_rhs_operand" "")))
3297
    (clobber (reg:CC CC_REGNUM))])]
3298
  "TARGET_32BIT"
3299
  "
3300
  if (operands[2] == const0_rtx)
3301
    {
3302
      /* No need for a clobber of the condition code register here.  */
3303
      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3304
                              gen_rtx_SMIN (SImode, operands[1],
3305
                                            operands[2])));
3306
      DONE;
3307
    }
3308
")
3309
 
3310
(define_insn "*smin_0"
3311
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3312
        (smin:SI (match_operand:SI 1 "s_register_operand" "r")
3313
                 (const_int 0)))]
3314
  "TARGET_32BIT"
3315
  "and%?\\t%0, %1, %1, asr #31"
3316
  [(set_attr "predicable" "yes")]
3317
)
3318
 
3319
(define_insn "*arm_smin_insn"
3320
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3321
        (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
3322
                 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
3323
   (clobber (reg:CC CC_REGNUM))]
3324
  "TARGET_ARM"
3325
  "@
3326
   cmp\\t%1, %2\;movge\\t%0, %2
3327
   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
3328
  [(set_attr "conds" "clob")
3329
   (set_attr "length" "8,12")]
3330
)
3331
 
3332
(define_expand "umaxsi3"
3333
  [(parallel [
3334
    (set (match_operand:SI 0 "s_register_operand" "")
3335
         (umax:SI (match_operand:SI 1 "s_register_operand" "")
3336
                  (match_operand:SI 2 "arm_rhs_operand" "")))
3337
    (clobber (reg:CC CC_REGNUM))])]
3338
  "TARGET_32BIT"
3339
  ""
3340
)
3341
 
3342
(define_insn "*arm_umaxsi3"
3343
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3344
        (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3345
                 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3346
   (clobber (reg:CC CC_REGNUM))]
3347
  "TARGET_ARM"
3348
  "@
3349
   cmp\\t%1, %2\;movcc\\t%0, %2
3350
   cmp\\t%1, %2\;movcs\\t%0, %1
3351
   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
3352
  [(set_attr "conds" "clob")
3353
   (set_attr "length" "8,8,12")]
3354
)
3355
 
3356
(define_expand "uminsi3"
3357
  [(parallel [
3358
    (set (match_operand:SI 0 "s_register_operand" "")
3359
         (umin:SI (match_operand:SI 1 "s_register_operand" "")
3360
                  (match_operand:SI 2 "arm_rhs_operand" "")))
3361
    (clobber (reg:CC CC_REGNUM))])]
3362
  "TARGET_32BIT"
3363
  ""
3364
)
3365
 
3366
(define_insn "*arm_uminsi3"
3367
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
3368
        (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
3369
                 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
3370
   (clobber (reg:CC CC_REGNUM))]
3371
  "TARGET_ARM"
3372
  "@
3373
   cmp\\t%1, %2\;movcs\\t%0, %2
3374
   cmp\\t%1, %2\;movcc\\t%0, %1
3375
   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
3376
  [(set_attr "conds" "clob")
3377
   (set_attr "length" "8,8,12")]
3378
)
3379
 
3380
(define_insn "*store_minmaxsi"
3381
  [(set (match_operand:SI 0 "memory_operand" "=m")
3382
        (match_operator:SI 3 "minmax_operator"
3383
         [(match_operand:SI 1 "s_register_operand" "r")
3384
          (match_operand:SI 2 "s_register_operand" "r")]))
3385
   (clobber (reg:CC CC_REGNUM))]
3386
  "TARGET_32BIT"
3387
  "*
3388
  operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
3389
                                operands[1], operands[2]);
3390
  output_asm_insn (\"cmp\\t%1, %2\", operands);
3391
  if (TARGET_THUMB2)
3392
    output_asm_insn (\"ite\t%d3\", operands);
3393
  output_asm_insn (\"str%d3\\t%1, %0\", operands);
3394
  output_asm_insn (\"str%D3\\t%2, %0\", operands);
3395
  return \"\";
3396
  "
3397
  [(set_attr "conds" "clob")
3398
   (set (attr "length")
3399
        (if_then_else (eq_attr "is_thumb" "yes")
3400
                      (const_int 14)
3401
                      (const_int 12)))
3402
   (set_attr "type" "store1")]
3403
)
3404
 
3405
; Reject the frame pointer in operand[1], since reloading this after
3406
; it has been eliminated can cause carnage.
3407
(define_insn "*minmax_arithsi"
3408
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3409
        (match_operator:SI 4 "shiftable_operator"
3410
         [(match_operator:SI 5 "minmax_operator"
3411
           [(match_operand:SI 2 "s_register_operand" "r,r")
3412
            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
3413
          (match_operand:SI 1 "s_register_operand" "0,?r")]))
3414
   (clobber (reg:CC CC_REGNUM))]
3415
  "TARGET_32BIT && !arm_eliminable_register (operands[1])"
3416
  "*
3417
  {
3418
    enum rtx_code code = GET_CODE (operands[4]);
3419
    bool need_else;
3420
 
3421
    if (which_alternative != 0 || operands[3] != const0_rtx
3422
        || (code != PLUS && code != IOR && code != XOR))
3423
      need_else = true;
3424
    else
3425
      need_else = false;
3426
 
3427
    operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
3428
                                  operands[2], operands[3]);
3429
    output_asm_insn (\"cmp\\t%2, %3\", operands);
3430
    if (TARGET_THUMB2)
3431
      {
3432
        if (need_else)
3433
          output_asm_insn (\"ite\\t%d5\", operands);
3434
        else
3435
          output_asm_insn (\"it\\t%d5\", operands);
3436
      }
3437
    output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
3438
    if (need_else)
3439
      output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
3440
    return \"\";
3441
  }"
3442
  [(set_attr "conds" "clob")
3443
   (set (attr "length")
3444
        (if_then_else (eq_attr "is_thumb" "yes")
3445
                      (const_int 14)
3446
                      (const_int 12)))]
3447
)
3448
 
3449
 
3450
;; Shift and rotation insns
3451
 
3452
(define_expand "ashldi3"
3453
  [(set (match_operand:DI            0 "s_register_operand" "")
3454
        (ashift:DI (match_operand:DI 1 "s_register_operand" "")
3455
                   (match_operand:SI 2 "reg_or_int_operand" "")))]
3456
  "TARGET_32BIT"
3457
  "
3458
  if (GET_CODE (operands[2]) == CONST_INT)
3459
    {
3460
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3461
        {
3462
          emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
3463
          DONE;
3464
        }
3465
        /* Ideally we shouldn't fail here if we could know that operands[1]
3466
           ends up already living in an iwmmxt register. Otherwise it's
3467
           cheaper to have the alternate code being generated than moving
3468
           values to iwmmxt regs and back.  */
3469
        FAIL;
3470
    }
3471
  else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
3472
    FAIL;
3473
  "
3474
)
3475
 
3476
(define_insn "arm_ashldi3_1bit"
3477
  [(set (match_operand:DI            0 "s_register_operand" "=r,&r")
3478
        (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
3479
                   (const_int 1)))
3480
   (clobber (reg:CC CC_REGNUM))]
3481
  "TARGET_32BIT"
3482
  "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
3483
  [(set_attr "conds" "clob")
3484
   (set_attr "length" "8")]
3485
)
3486
 
3487
(define_expand "ashlsi3"
3488
  [(set (match_operand:SI            0 "s_register_operand" "")
3489
        (ashift:SI (match_operand:SI 1 "s_register_operand" "")
3490
                   (match_operand:SI 2 "arm_rhs_operand" "")))]
3491
  "TARGET_EITHER"
3492
  "
3493
  if (GET_CODE (operands[2]) == CONST_INT
3494
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3495
    {
3496
      emit_insn (gen_movsi (operands[0], const0_rtx));
3497
      DONE;
3498
    }
3499
  "
3500
)
3501
 
3502
(define_insn "*thumb1_ashlsi3"
3503
  [(set (match_operand:SI            0 "register_operand" "=l,l")
3504
        (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
3505
                   (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3506
  "TARGET_THUMB1"
3507
  "lsl\\t%0, %1, %2"
3508
  [(set_attr "length" "2")
3509
   (set_attr "conds" "set")])
3510
 
3511
(define_expand "ashrdi3"
3512
  [(set (match_operand:DI              0 "s_register_operand" "")
3513
        (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3514
                     (match_operand:SI 2 "reg_or_int_operand" "")))]
3515
  "TARGET_32BIT"
3516
  "
3517
  if (GET_CODE (operands[2]) == CONST_INT)
3518
    {
3519
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3520
        {
3521
          emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
3522
          DONE;
3523
        }
3524
        /* Ideally we shouldn't fail here if we could know that operands[1]
3525
           ends up already living in an iwmmxt register. Otherwise it's
3526
           cheaper to have the alternate code being generated than moving
3527
           values to iwmmxt regs and back.  */
3528
        FAIL;
3529
    }
3530
  else if (!TARGET_REALLY_IWMMXT)
3531
    FAIL;
3532
  "
3533
)
3534
 
3535
(define_insn "arm_ashrdi3_1bit"
3536
  [(set (match_operand:DI              0 "s_register_operand" "=r,&r")
3537
        (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3538
                     (const_int 1)))
3539
   (clobber (reg:CC CC_REGNUM))]
3540
  "TARGET_32BIT"
3541
  "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
3542
  [(set_attr "conds" "clob")
3543
   (set_attr "insn" "mov")
3544
   (set_attr "length" "8")]
3545
)
3546
 
3547
(define_expand "ashrsi3"
3548
  [(set (match_operand:SI              0 "s_register_operand" "")
3549
        (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3550
                     (match_operand:SI 2 "arm_rhs_operand" "")))]
3551
  "TARGET_EITHER"
3552
  "
3553
  if (GET_CODE (operands[2]) == CONST_INT
3554
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3555
    operands[2] = GEN_INT (31);
3556
  "
3557
)
3558
 
3559
(define_insn "*thumb1_ashrsi3"
3560
  [(set (match_operand:SI              0 "register_operand" "=l,l")
3561
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3562
                     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3563
  "TARGET_THUMB1"
3564
  "asr\\t%0, %1, %2"
3565
  [(set_attr "length" "2")
3566
   (set_attr "conds" "set")])
3567
 
3568
(define_expand "lshrdi3"
3569
  [(set (match_operand:DI              0 "s_register_operand" "")
3570
        (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
3571
                     (match_operand:SI 2 "reg_or_int_operand" "")))]
3572
  "TARGET_32BIT"
3573
  "
3574
  if (GET_CODE (operands[2]) == CONST_INT)
3575
    {
3576
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
3577
        {
3578
          emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
3579
          DONE;
3580
        }
3581
        /* Ideally we shouldn't fail here if we could know that operands[1]
3582
           ends up already living in an iwmmxt register. Otherwise it's
3583
           cheaper to have the alternate code being generated than moving
3584
           values to iwmmxt regs and back.  */
3585
        FAIL;
3586
    }
3587
  else if (!TARGET_REALLY_IWMMXT)
3588
    FAIL;
3589
  "
3590
)
3591
 
3592
(define_insn "arm_lshrdi3_1bit"
3593
  [(set (match_operand:DI              0 "s_register_operand" "=r,&r")
3594
        (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
3595
                     (const_int 1)))
3596
   (clobber (reg:CC CC_REGNUM))]
3597
  "TARGET_32BIT"
3598
  "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
3599
  [(set_attr "conds" "clob")
3600
   (set_attr "insn" "mov")
3601
   (set_attr "length" "8")]
3602
)
3603
 
3604
(define_expand "lshrsi3"
3605
  [(set (match_operand:SI              0 "s_register_operand" "")
3606
        (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
3607
                     (match_operand:SI 2 "arm_rhs_operand" "")))]
3608
  "TARGET_EITHER"
3609
  "
3610
  if (GET_CODE (operands[2]) == CONST_INT
3611
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3612
    {
3613
      emit_insn (gen_movsi (operands[0], const0_rtx));
3614
      DONE;
3615
    }
3616
  "
3617
)
3618
 
3619
(define_insn "*thumb1_lshrsi3"
3620
  [(set (match_operand:SI              0 "register_operand" "=l,l")
3621
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
3622
                     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
3623
  "TARGET_THUMB1"
3624
  "lsr\\t%0, %1, %2"
3625
  [(set_attr "length" "2")
3626
   (set_attr "conds" "set")])
3627
 
3628
(define_expand "rotlsi3"
3629
  [(set (match_operand:SI              0 "s_register_operand" "")
3630
        (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3631
                     (match_operand:SI 2 "reg_or_int_operand" "")))]
3632
  "TARGET_32BIT"
3633
  "
3634
  if (GET_CODE (operands[2]) == CONST_INT)
3635
    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
3636
  else
3637
    {
3638
      rtx reg = gen_reg_rtx (SImode);
3639
      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
3640
      operands[2] = reg;
3641
    }
3642
  "
3643
)
3644
 
3645
(define_expand "rotrsi3"
3646
  [(set (match_operand:SI              0 "s_register_operand" "")
3647
        (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
3648
                     (match_operand:SI 2 "arm_rhs_operand" "")))]
3649
  "TARGET_EITHER"
3650
  "
3651
  if (TARGET_32BIT)
3652
    {
3653
      if (GET_CODE (operands[2]) == CONST_INT
3654
          && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
3655
        operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
3656
    }
3657
  else /* TARGET_THUMB1 */
3658
    {
3659
      if (GET_CODE (operands [2]) == CONST_INT)
3660
        operands [2] = force_reg (SImode, operands[2]);
3661
    }
3662
  "
3663
)
3664
 
3665
(define_insn "*thumb1_rotrsi3"
3666
  [(set (match_operand:SI              0 "register_operand" "=l")
3667
        (rotatert:SI (match_operand:SI 1 "register_operand" "0")
3668
                     (match_operand:SI 2 "register_operand" "l")))]
3669
  "TARGET_THUMB1"
3670
  "ror\\t%0, %0, %2"
3671
  [(set_attr "length" "2")]
3672
)
3673
 
3674
(define_insn "*arm_shiftsi3"
3675
  [(set (match_operand:SI   0 "s_register_operand" "=r")
3676
        (match_operator:SI  3 "shift_operator"
3677
         [(match_operand:SI 1 "s_register_operand"  "r")
3678
          (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
3679
  "TARGET_32BIT"
3680
  "* return arm_output_shift(operands, 0);"
3681
  [(set_attr "predicable" "yes")
3682
   (set_attr "shift" "1")
3683
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3684
                      (const_string "alu_shift")
3685
                      (const_string "alu_shift_reg")))]
3686
)
3687
 
3688
(define_insn "*shiftsi3_compare0"
3689
  [(set (reg:CC_NOOV CC_REGNUM)
3690
        (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3691
                          [(match_operand:SI 1 "s_register_operand" "r")
3692
                           (match_operand:SI 2 "arm_rhs_operand" "rM")])
3693
                         (const_int 0)))
3694
   (set (match_operand:SI 0 "s_register_operand" "=r")
3695
        (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
3696
  "TARGET_32BIT"
3697
  "* return arm_output_shift(operands, 1);"
3698
  [(set_attr "conds" "set")
3699
   (set_attr "shift" "1")
3700
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
3701
                      (const_string "alu_shift")
3702
                      (const_string "alu_shift_reg")))]
3703
)
3704
 
3705
(define_insn "*shiftsi3_compare0_scratch"
3706
  [(set (reg:CC_NOOV CC_REGNUM)
3707
        (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
3708
                          [(match_operand:SI 1 "s_register_operand" "r")
3709
                           (match_operand:SI 2 "arm_rhs_operand" "rM")])
3710
                         (const_int 0)))
3711
   (clobber (match_scratch:SI 0 "=r"))]
3712
  "TARGET_32BIT"
3713
  "* return arm_output_shift(operands, 1);"
3714
  [(set_attr "conds" "set")
3715
   (set_attr "shift" "1")]
3716
)
3717
 
3718
(define_insn "*not_shiftsi"
3719
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3720
        (not:SI (match_operator:SI 3 "shift_operator"
3721
                 [(match_operand:SI 1 "s_register_operand" "r,r")
3722
                  (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
3723
  "TARGET_32BIT"
3724
  "mvn%?\\t%0, %1%S3"
3725
  [(set_attr "predicable" "yes")
3726
   (set_attr "shift" "1")
3727
   (set_attr "insn" "mvn")
3728
   (set_attr "arch" "32,a")
3729
   (set_attr "type" "alu_shift,alu_shift_reg")])
3730
 
3731
(define_insn "*not_shiftsi_compare0"
3732
  [(set (reg:CC_NOOV CC_REGNUM)
3733
        (compare:CC_NOOV
3734
         (not:SI (match_operator:SI 3 "shift_operator"
3735
                  [(match_operand:SI 1 "s_register_operand" "r,r")
3736
                   (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3737
         (const_int 0)))
3738
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
3739
        (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
3740
  "TARGET_32BIT"
3741
  "mvn%.\\t%0, %1%S3"
3742
  [(set_attr "conds" "set")
3743
   (set_attr "shift" "1")
3744
   (set_attr "insn" "mvn")
3745
   (set_attr "arch" "32,a")
3746
   (set_attr "type" "alu_shift,alu_shift_reg")])
3747
 
3748
(define_insn "*not_shiftsi_compare0_scratch"
3749
  [(set (reg:CC_NOOV CC_REGNUM)
3750
        (compare:CC_NOOV
3751
         (not:SI (match_operator:SI 3 "shift_operator"
3752
                  [(match_operand:SI 1 "s_register_operand" "r,r")
3753
                   (match_operand:SI 2 "shift_amount_operand" "M,rM")]))
3754
         (const_int 0)))
3755
   (clobber (match_scratch:SI 0 "=r,r"))]
3756
  "TARGET_32BIT"
3757
  "mvn%.\\t%0, %1%S3"
3758
  [(set_attr "conds" "set")
3759
   (set_attr "shift" "1")
3760
   (set_attr "insn" "mvn")
3761
   (set_attr "arch" "32,a")
3762
   (set_attr "type" "alu_shift,alu_shift_reg")])
3763
 
3764
;; We don't really have extzv, but defining this using shifts helps
3765
;; to reduce register pressure later on.
3766
 
3767
(define_expand "extzv"
3768
  [(set (match_operand 0 "s_register_operand" "")
3769
        (zero_extract (match_operand 1 "nonimmediate_operand" "")
3770
                      (match_operand 2 "const_int_operand" "")
3771
                      (match_operand 3 "const_int_operand" "")))]
3772
  "TARGET_THUMB1 || arm_arch_thumb2"
3773
  "
3774
  {
3775
    HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
3776
    HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
3777
 
3778
    if (arm_arch_thumb2)
3779
      {
3780
        HOST_WIDE_INT width = INTVAL (operands[2]);
3781
        HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3782
 
3783
        if (unaligned_access && MEM_P (operands[1])
3784
            && (width == 16 || width == 32) && (bitpos % BITS_PER_UNIT) == 0)
3785
          {
3786
            rtx base_addr;
3787
 
3788
            if (BYTES_BIG_ENDIAN)
3789
              bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width
3790
                       - bitpos;
3791
 
3792
            if (width == 32)
3793
              {
3794
                base_addr = adjust_address (operands[1], SImode,
3795
                                            bitpos / BITS_PER_UNIT);
3796
                emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3797
              }
3798
            else
3799
              {
3800
                rtx dest = operands[0];
3801
                rtx tmp = gen_reg_rtx (SImode);
3802
 
3803
                /* We may get a paradoxical subreg here.  Strip it off.  */
3804
                if (GET_CODE (dest) == SUBREG
3805
                    && GET_MODE (dest) == SImode
3806
                    && GET_MODE (SUBREG_REG (dest)) == HImode)
3807
                  dest = SUBREG_REG (dest);
3808
 
3809
                if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3810
                  FAIL;
3811
 
3812
                base_addr = adjust_address (operands[1], HImode,
3813
                                            bitpos / BITS_PER_UNIT);
3814
                emit_insn (gen_unaligned_loadhiu (tmp, base_addr));
3815
                emit_move_insn (gen_lowpart (SImode, dest), tmp);
3816
              }
3817
            DONE;
3818
          }
3819
        else if (s_register_operand (operands[1], GET_MODE (operands[1])))
3820
          {
3821
            emit_insn (gen_extzv_t2 (operands[0], operands[1], operands[2],
3822
                                     operands[3]));
3823
            DONE;
3824
          }
3825
        else
3826
          FAIL;
3827
      }
3828
 
3829
    if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3830
      FAIL;
3831
 
3832
    operands[3] = GEN_INT (rshift);
3833
 
3834
    if (lshift == 0)
3835
      {
3836
        emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
3837
        DONE;
3838
      }
3839
 
3840
    emit_insn (gen_extzv_t1 (operands[0], operands[1], GEN_INT (lshift),
3841
                             operands[3], gen_reg_rtx (SImode)));
3842
    DONE;
3843
  }"
3844
)
3845
 
3846
;; Helper for extzv, for the Thumb-1 register-shifts case.
3847
 
3848
(define_expand "extzv_t1"
3849
  [(set (match_operand:SI 4 "s_register_operand" "")
3850
        (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
3851
                   (match_operand:SI 2 "const_int_operand" "")))
3852
   (set (match_operand:SI 0 "s_register_operand" "")
3853
        (lshiftrt:SI (match_dup 4)
3854
                     (match_operand:SI 3 "const_int_operand" "")))]
3855
  "TARGET_THUMB1"
3856
  "")
3857
 
3858
(define_expand "extv"
3859
  [(set (match_operand 0 "s_register_operand" "")
3860
        (sign_extract (match_operand 1 "nonimmediate_operand" "")
3861
                      (match_operand 2 "const_int_operand" "")
3862
                      (match_operand 3 "const_int_operand" "")))]
3863
  "arm_arch_thumb2"
3864
{
3865
  HOST_WIDE_INT width = INTVAL (operands[2]);
3866
  HOST_WIDE_INT bitpos = INTVAL (operands[3]);
3867
 
3868
  if (unaligned_access && MEM_P (operands[1]) && (width == 16 || width == 32)
3869
      && (bitpos % BITS_PER_UNIT)  == 0)
3870
    {
3871
      rtx base_addr;
3872
 
3873
      if (BYTES_BIG_ENDIAN)
3874
        bitpos = GET_MODE_BITSIZE (GET_MODE (operands[0])) - width - bitpos;
3875
 
3876
      if (width == 32)
3877
        {
3878
          base_addr = adjust_address (operands[1], SImode,
3879
                                      bitpos / BITS_PER_UNIT);
3880
          emit_insn (gen_unaligned_loadsi (operands[0], base_addr));
3881
        }
3882
      else
3883
        {
3884
          rtx dest = operands[0];
3885
          rtx tmp = gen_reg_rtx (SImode);
3886
 
3887
          /* We may get a paradoxical subreg here.  Strip it off.  */
3888
          if (GET_CODE (dest) == SUBREG
3889
              && GET_MODE (dest) == SImode
3890
              && GET_MODE (SUBREG_REG (dest)) == HImode)
3891
            dest = SUBREG_REG (dest);
3892
 
3893
          if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
3894
            FAIL;
3895
 
3896
          base_addr = adjust_address (operands[1], HImode,
3897
                                      bitpos / BITS_PER_UNIT);
3898
          emit_insn (gen_unaligned_loadhis (tmp, base_addr));
3899
          emit_move_insn (gen_lowpart (SImode, dest), tmp);
3900
        }
3901
 
3902
      DONE;
3903
    }
3904
  else if (!s_register_operand (operands[1], GET_MODE (operands[1])))
3905
    FAIL;
3906
  else if (GET_MODE (operands[0]) == SImode
3907
           && GET_MODE (operands[1]) == SImode)
3908
    {
3909
      emit_insn (gen_extv_regsi (operands[0], operands[1], operands[2],
3910
                                 operands[3]));
3911
      DONE;
3912
    }
3913
 
3914
  FAIL;
3915
})
3916
 
3917
; Helper to expand register forms of extv with the proper modes.
3918
 
3919
(define_expand "extv_regsi"
3920
  [(set (match_operand:SI 0 "s_register_operand" "")
3921
        (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
3922
                         (match_operand 2 "const_int_operand" "")
3923
                         (match_operand 3 "const_int_operand" "")))]
3924
  ""
3925
{
3926
})
3927
 
3928
; ARMv6+ unaligned load/store instructions (used for packed structure accesses).
3929
 
3930
(define_insn "unaligned_loadsi"
3931
  [(set (match_operand:SI 0 "s_register_operand" "=l,r")
3932
        (unspec:SI [(match_operand:SI 1 "memory_operand" "Uw,m")]
3933
                   UNSPEC_UNALIGNED_LOAD))]
3934
  "unaligned_access && TARGET_32BIT"
3935
  "ldr%?\t%0, %1\t@ unaligned"
3936
  [(set_attr "arch" "t2,any")
3937
   (set_attr "length" "2,4")
3938
   (set_attr "predicable" "yes")
3939
   (set_attr "type" "load1")])
3940
 
3941
(define_insn "unaligned_loadhis"
3942
  [(set (match_operand:SI 0 "s_register_operand" "=l,r")
3943
        (sign_extend:SI
3944
          (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
3945
                     UNSPEC_UNALIGNED_LOAD)))]
3946
  "unaligned_access && TARGET_32BIT"
3947
  "ldr%(sh%)\t%0, %1\t@ unaligned"
3948
  [(set_attr "arch" "t2,any")
3949
   (set_attr "length" "2,4")
3950
   (set_attr "predicable" "yes")
3951
   (set_attr "type" "load_byte")])
3952
 
3953
(define_insn "unaligned_loadhiu"
3954
  [(set (match_operand:SI 0 "s_register_operand" "=l,r")
3955
        (zero_extend:SI
3956
          (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")]
3957
                     UNSPEC_UNALIGNED_LOAD)))]
3958
  "unaligned_access && TARGET_32BIT"
3959
  "ldr%(h%)\t%0, %1\t@ unaligned"
3960
  [(set_attr "arch" "t2,any")
3961
   (set_attr "length" "2,4")
3962
   (set_attr "predicable" "yes")
3963
   (set_attr "type" "load_byte")])
3964
 
3965
(define_insn "unaligned_storesi"
3966
  [(set (match_operand:SI 0 "memory_operand" "=Uw,m")
3967
        (unspec:SI [(match_operand:SI 1 "s_register_operand" "l,r")]
3968
                   UNSPEC_UNALIGNED_STORE))]
3969
  "unaligned_access && TARGET_32BIT"
3970
  "str%?\t%1, %0\t@ unaligned"
3971
  [(set_attr "arch" "t2,any")
3972
   (set_attr "length" "2,4")
3973
   (set_attr "predicable" "yes")
3974
   (set_attr "type" "store1")])
3975
 
3976
(define_insn "unaligned_storehi"
3977
  [(set (match_operand:HI 0 "memory_operand" "=Uw,m")
3978
        (unspec:HI [(match_operand:HI 1 "s_register_operand" "l,r")]
3979
                   UNSPEC_UNALIGNED_STORE))]
3980
  "unaligned_access && TARGET_32BIT"
3981
  "str%(h%)\t%1, %0\t@ unaligned"
3982
  [(set_attr "arch" "t2,any")
3983
   (set_attr "length" "2,4")
3984
   (set_attr "predicable" "yes")
3985
   (set_attr "type" "store1")])
3986
 
3987
(define_insn "*extv_reg"
3988
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3989
        (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
3990
                         (match_operand:SI 2 "const_int_operand" "M")
3991
                         (match_operand:SI 3 "const_int_operand" "M")))]
3992
  "arm_arch_thumb2"
3993
  "sbfx%?\t%0, %1, %3, %2"
3994
  [(set_attr "length" "4")
3995
   (set_attr "predicable" "yes")]
3996
)
3997
 
3998
(define_insn "extzv_t2"
3999
  [(set (match_operand:SI 0 "s_register_operand" "=r")
4000
        (zero_extract:SI (match_operand:SI 1 "s_register_operand" "r")
4001
                         (match_operand:SI 2 "const_int_operand" "M")
4002
                         (match_operand:SI 3 "const_int_operand" "M")))]
4003
  "arm_arch_thumb2"
4004
  "ubfx%?\t%0, %1, %3, %2"
4005
  [(set_attr "length" "4")
4006
   (set_attr "predicable" "yes")]
4007
)
4008
 
4009
 
4010
;; Division instructions
4011
(define_insn "divsi3"
4012
  [(set (match_operand:SI         0 "s_register_operand" "=r")
4013
        (div:SI (match_operand:SI 1 "s_register_operand"  "r")
4014
                (match_operand:SI 2 "s_register_operand"  "r")))]
4015
  "TARGET_IDIV"
4016
  "sdiv%?\t%0, %1, %2"
4017
  [(set_attr "predicable" "yes")
4018
   (set_attr "insn" "sdiv")]
4019
)
4020
 
4021
(define_insn "udivsi3"
4022
  [(set (match_operand:SI          0 "s_register_operand" "=r")
4023
        (udiv:SI (match_operand:SI 1 "s_register_operand"  "r")
4024
                 (match_operand:SI 2 "s_register_operand"  "r")))]
4025
  "TARGET_IDIV"
4026
  "udiv%?\t%0, %1, %2"
4027
  [(set_attr "predicable" "yes")
4028
   (set_attr "insn" "udiv")]
4029
)
4030
 
4031
 
4032
;; Unary arithmetic insns
4033
 
4034
(define_expand "negdi2"
4035
 [(parallel
4036
   [(set (match_operand:DI 0 "s_register_operand" "")
4037
         (neg:DI (match_operand:DI 1 "s_register_operand" "")))
4038
    (clobber (reg:CC CC_REGNUM))])]
4039
  "TARGET_EITHER"
4040
  ""
4041
)
4042
 
4043
;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
4044
;; The first alternative allows the common case of a *full* overlap.
4045
(define_insn "*arm_negdi2"
4046
  [(set (match_operand:DI         0 "s_register_operand" "=r,&r")
4047
        (neg:DI (match_operand:DI 1 "s_register_operand"  "0,r")))
4048
   (clobber (reg:CC CC_REGNUM))]
4049
  "TARGET_ARM"
4050
  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
4051
  [(set_attr "conds" "clob")
4052
   (set_attr "length" "8")]
4053
)
4054
 
4055
(define_insn "*thumb1_negdi2"
4056
  [(set (match_operand:DI 0 "register_operand" "=&l")
4057
        (neg:DI (match_operand:DI 1 "register_operand" "l")))
4058
   (clobber (reg:CC CC_REGNUM))]
4059
  "TARGET_THUMB1"
4060
  "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
4061
  [(set_attr "length" "6")]
4062
)
4063
 
4064
(define_expand "negsi2"
4065
  [(set (match_operand:SI         0 "s_register_operand" "")
4066
        (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
4067
  "TARGET_EITHER"
4068
  ""
4069
)
4070
 
4071
(define_insn "*arm_negsi2"
4072
  [(set (match_operand:SI         0 "s_register_operand" "=r")
4073
        (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
4074
  "TARGET_32BIT"
4075
  "rsb%?\\t%0, %1, #0"
4076
  [(set_attr "predicable" "yes")]
4077
)
4078
 
4079
(define_insn "*thumb1_negsi2"
4080
  [(set (match_operand:SI         0 "register_operand" "=l")
4081
        (neg:SI (match_operand:SI 1 "register_operand" "l")))]
4082
  "TARGET_THUMB1"
4083
  "neg\\t%0, %1"
4084
  [(set_attr "length" "2")]
4085
)
4086
 
4087
(define_expand "negsf2"
4088
  [(set (match_operand:SF         0 "s_register_operand" "")
4089
        (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
4090
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
4091
  ""
4092
)
4093
 
4094
(define_expand "negdf2"
4095
  [(set (match_operand:DF         0 "s_register_operand" "")
4096
        (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
4097
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
4098
  "")
4099
 
4100
;; abssi2 doesn't really clobber the condition codes if a different register
4101
;; is being set.  To keep things simple, assume during rtl manipulations that
4102
;; it does, but tell the final scan operator the truth.  Similarly for
4103
;; (neg (abs...))
4104
 
4105
(define_expand "abssi2"
4106
  [(parallel
4107
    [(set (match_operand:SI         0 "s_register_operand" "")
4108
          (abs:SI (match_operand:SI 1 "s_register_operand" "")))
4109
     (clobber (match_dup 2))])]
4110
  "TARGET_EITHER"
4111
  "
4112
  if (TARGET_THUMB1)
4113
    operands[2] = gen_rtx_SCRATCH (SImode);
4114
  else
4115
    operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
4116
")
4117
 
4118
(define_insn "*arm_abssi2"
4119
  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4120
        (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
4121
   (clobber (reg:CC CC_REGNUM))]
4122
  "TARGET_ARM"
4123
  "@
4124
   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
4125
   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
4126
  [(set_attr "conds" "clob,*")
4127
   (set_attr "shift" "1")
4128
   ;; predicable can't be set based on the variant, so left as no
4129
   (set_attr "length" "8")]
4130
)
4131
 
4132
(define_insn_and_split "*thumb1_abssi2"
4133
  [(set (match_operand:SI 0 "s_register_operand" "=l")
4134
        (abs:SI (match_operand:SI 1 "s_register_operand" "l")))
4135
   (clobber (match_scratch:SI 2 "=&l"))]
4136
  "TARGET_THUMB1"
4137
  "#"
4138
  "TARGET_THUMB1 && reload_completed"
4139
  [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4140
   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
4141
   (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4142
  ""
4143
  [(set_attr "length" "6")]
4144
)
4145
 
4146
(define_insn "*arm_neg_abssi2"
4147
  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
4148
        (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
4149
   (clobber (reg:CC CC_REGNUM))]
4150
  "TARGET_ARM"
4151
  "@
4152
   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
4153
   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
4154
  [(set_attr "conds" "clob,*")
4155
   (set_attr "shift" "1")
4156
   ;; predicable can't be set based on the variant, so left as no
4157
   (set_attr "length" "8")]
4158
)
4159
 
4160
(define_insn_and_split "*thumb1_neg_abssi2"
4161
  [(set (match_operand:SI 0 "s_register_operand" "=l")
4162
        (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "l"))))
4163
   (clobber (match_scratch:SI 2 "=&l"))]
4164
  "TARGET_THUMB1"
4165
  "#"
4166
  "TARGET_THUMB1 && reload_completed"
4167
  [(set (match_dup 2) (ashiftrt:SI (match_dup 1) (const_int 31)))
4168
   (set (match_dup 0) (minus:SI (match_dup 2) (match_dup 1)))
4169
   (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 2)))]
4170
  ""
4171
  [(set_attr "length" "6")]
4172
)
4173
 
4174
(define_expand "abssf2"
4175
  [(set (match_operand:SF         0 "s_register_operand" "")
4176
        (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
4177
  "TARGET_32BIT && TARGET_HARD_FLOAT"
4178
  "")
4179
 
4180
(define_expand "absdf2"
4181
  [(set (match_operand:DF         0 "s_register_operand" "")
4182
        (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
4183
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4184
  "")
4185
 
4186
(define_expand "sqrtsf2"
4187
  [(set (match_operand:SF 0 "s_register_operand" "")
4188
        (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
4189
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
4190
  "")
4191
 
4192
(define_expand "sqrtdf2"
4193
  [(set (match_operand:DF 0 "s_register_operand" "")
4194
        (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
4195
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
4196
  "")
4197
 
4198
(define_insn_and_split "one_cmpldi2"
4199
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
4200
        (not:DI (match_operand:DI 1 "s_register_operand" "0,r")))]
4201
  "TARGET_32BIT"
4202
  "#"
4203
  "TARGET_32BIT && reload_completed"
4204
  [(set (match_dup 0) (not:SI (match_dup 1)))
4205
   (set (match_dup 2) (not:SI (match_dup 3)))]
4206
  "
4207
  {
4208
    operands[2] = gen_highpart (SImode, operands[0]);
4209
    operands[0] = gen_lowpart (SImode, operands[0]);
4210
    operands[3] = gen_highpart (SImode, operands[1]);
4211
    operands[1] = gen_lowpart (SImode, operands[1]);
4212
  }"
4213
  [(set_attr "length" "8")
4214
   (set_attr "predicable" "yes")]
4215
)
4216
 
4217
(define_expand "one_cmplsi2"
4218
  [(set (match_operand:SI         0 "s_register_operand" "")
4219
        (not:SI (match_operand:SI 1 "s_register_operand" "")))]
4220
  "TARGET_EITHER"
4221
  ""
4222
)
4223
 
4224
(define_insn "*arm_one_cmplsi2"
4225
  [(set (match_operand:SI         0 "s_register_operand" "=r")
4226
        (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
4227
  "TARGET_32BIT"
4228
  "mvn%?\\t%0, %1"
4229
  [(set_attr "predicable" "yes")
4230
   (set_attr "insn" "mvn")]
4231
)
4232
 
4233
(define_insn "*thumb1_one_cmplsi2"
4234
  [(set (match_operand:SI         0 "register_operand" "=l")
4235
        (not:SI (match_operand:SI 1 "register_operand"  "l")))]
4236
  "TARGET_THUMB1"
4237
  "mvn\\t%0, %1"
4238
  [(set_attr "length" "2")
4239
   (set_attr "insn" "mvn")]
4240
)
4241
 
4242
(define_insn "*notsi_compare0"
4243
  [(set (reg:CC_NOOV CC_REGNUM)
4244
        (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4245
                         (const_int 0)))
4246
   (set (match_operand:SI 0 "s_register_operand" "=r")
4247
        (not:SI (match_dup 1)))]
4248
  "TARGET_32BIT"
4249
  "mvn%.\\t%0, %1"
4250
  [(set_attr "conds" "set")
4251
   (set_attr "insn" "mvn")]
4252
)
4253
 
4254
(define_insn "*notsi_compare0_scratch"
4255
  [(set (reg:CC_NOOV CC_REGNUM)
4256
        (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
4257
                         (const_int 0)))
4258
   (clobber (match_scratch:SI 0 "=r"))]
4259
  "TARGET_32BIT"
4260
  "mvn%.\\t%0, %1"
4261
  [(set_attr "conds" "set")
4262
   (set_attr "insn" "mvn")]
4263
)
4264
 
4265
;; Fixed <--> Floating conversion insns
4266
 
4267
(define_expand "floatsihf2"
4268
  [(set (match_operand:HF           0 "general_operand" "")
4269
        (float:HF (match_operand:SI 1 "general_operand" "")))]
4270
  "TARGET_EITHER"
4271
  "
4272
  {
4273
    rtx op1 = gen_reg_rtx (SFmode);
4274
    expand_float (op1, operands[1], 0);
4275
    op1 = convert_to_mode (HFmode, op1, 0);
4276
    emit_move_insn (operands[0], op1);
4277
    DONE;
4278
  }"
4279
)
4280
 
4281
(define_expand "floatdihf2"
4282
  [(set (match_operand:HF           0 "general_operand" "")
4283
        (float:HF (match_operand:DI 1 "general_operand" "")))]
4284
  "TARGET_EITHER"
4285
  "
4286
  {
4287
    rtx op1 = gen_reg_rtx (SFmode);
4288
    expand_float (op1, operands[1], 0);
4289
    op1 = convert_to_mode (HFmode, op1, 0);
4290
    emit_move_insn (operands[0], op1);
4291
    DONE;
4292
  }"
4293
)
4294
 
4295
(define_expand "floatsisf2"
4296
  [(set (match_operand:SF           0 "s_register_operand" "")
4297
        (float:SF (match_operand:SI 1 "s_register_operand" "")))]
4298
  "TARGET_32BIT && TARGET_HARD_FLOAT"
4299
  "
4300
  if (TARGET_MAVERICK)
4301
    {
4302
      emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
4303
      DONE;
4304
    }
4305
")
4306
 
4307
(define_expand "floatsidf2"
4308
  [(set (match_operand:DF           0 "s_register_operand" "")
4309
        (float:DF (match_operand:SI 1 "s_register_operand" "")))]
4310
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4311
  "
4312
  if (TARGET_MAVERICK)
4313
    {
4314
      emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
4315
      DONE;
4316
    }
4317
")
4318
 
4319
(define_expand "fix_trunchfsi2"
4320
  [(set (match_operand:SI         0 "general_operand" "")
4321
        (fix:SI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
4322
  "TARGET_EITHER"
4323
  "
4324
  {
4325
    rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4326
    expand_fix (operands[0], op1, 0);
4327
    DONE;
4328
  }"
4329
)
4330
 
4331
(define_expand "fix_trunchfdi2"
4332
  [(set (match_operand:DI         0 "general_operand" "")
4333
        (fix:DI (fix:HF (match_operand:HF 1 "general_operand"  ""))))]
4334
  "TARGET_EITHER"
4335
  "
4336
  {
4337
    rtx op1 = convert_to_mode (SFmode, operands[1], 0);
4338
    expand_fix (operands[0], op1, 0);
4339
    DONE;
4340
  }"
4341
)
4342
 
4343
(define_expand "fix_truncsfsi2"
4344
  [(set (match_operand:SI         0 "s_register_operand" "")
4345
        (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
4346
  "TARGET_32BIT && TARGET_HARD_FLOAT"
4347
  "
4348
  if (TARGET_MAVERICK)
4349
    {
4350
      if (!cirrus_fp_register (operands[0], SImode))
4351
        operands[0] = force_reg (SImode, operands[0]);
4352
      if (!cirrus_fp_register (operands[1], SFmode))
4353
        operands[1] = force_reg (SFmode, operands[0]);
4354
      emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
4355
      DONE;
4356
    }
4357
")
4358
 
4359
(define_expand "fix_truncdfsi2"
4360
  [(set (match_operand:SI         0 "s_register_operand" "")
4361
        (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
4362
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4363
  "
4364
  if (TARGET_MAVERICK)
4365
    {
4366
      if (!cirrus_fp_register (operands[1], DFmode))
4367
        operands[1] = force_reg (DFmode, operands[0]);
4368
      emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
4369
      DONE;
4370
    }
4371
")
4372
 
4373
;; Truncation insns
4374
 
4375
(define_expand "truncdfsf2"
4376
  [(set (match_operand:SF  0 "s_register_operand" "")
4377
        (float_truncate:SF
4378
         (match_operand:DF 1 "s_register_operand" "")))]
4379
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
4380
  ""
4381
)
4382
 
4383
/* DFmode -> HFmode conversions have to go through SFmode.  */
4384
(define_expand "truncdfhf2"
4385
  [(set (match_operand:HF  0 "general_operand" "")
4386
        (float_truncate:HF
4387
         (match_operand:DF 1 "general_operand" "")))]
4388
  "TARGET_EITHER"
4389
  "
4390
  {
4391
    rtx op1;
4392
    op1 = convert_to_mode (SFmode, operands[1], 0);
4393
    op1 = convert_to_mode (HFmode, op1, 0);
4394
    emit_move_insn (operands[0], op1);
4395
    DONE;
4396
  }"
4397
)
4398
 
4399
;; Zero and sign extension instructions.
4400
 
4401
(define_insn "zero_extenddi2"
4402
  [(set (match_operand:DI 0 "s_register_operand" "=r")
4403
        (zero_extend:DI (match_operand:QHSI 1 ""
4404
                                            "")))]
4405
  "TARGET_32BIT "
4406
  "#"
4407
  [(set_attr "length" "8")
4408
   (set_attr "ce_count" "2")
4409
   (set_attr "predicable" "yes")]
4410
)
4411
 
4412
(define_insn "extenddi2"
4413
  [(set (match_operand:DI 0 "s_register_operand" "=r")
4414
        (sign_extend:DI (match_operand:QHSI 1 ""
4415
                                            "")))]
4416
  "TARGET_32BIT "
4417
  "#"
4418
  [(set_attr "length" "8")
4419
   (set_attr "ce_count" "2")
4420
   (set_attr "shift" "1")
4421
   (set_attr "predicable" "yes")]
4422
)
4423
 
4424
;; Splits for all extensions to DImode
4425
(define_split
4426
  [(set (match_operand:DI 0 "s_register_operand" "")
4427
        (zero_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4428
  "TARGET_32BIT"
4429
  [(set (match_dup 0) (match_dup 1))]
4430
{
4431
  rtx lo_part = gen_lowpart (SImode, operands[0]);
4432
  enum machine_mode src_mode = GET_MODE (operands[1]);
4433
 
4434
  if (REG_P (operands[0])
4435
      && !reg_overlap_mentioned_p (operands[0], operands[1]))
4436
    emit_clobber (operands[0]);
4437
  if (!REG_P (lo_part) || src_mode != SImode
4438
      || !rtx_equal_p (lo_part, operands[1]))
4439
    {
4440
      if (src_mode == SImode)
4441
        emit_move_insn (lo_part, operands[1]);
4442
      else
4443
        emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4444
                                gen_rtx_ZERO_EXTEND (SImode, operands[1])));
4445
      operands[1] = lo_part;
4446
    }
4447
  operands[0] = gen_highpart (SImode, operands[0]);
4448
  operands[1] = const0_rtx;
4449
})
4450
 
4451
(define_split
4452
  [(set (match_operand:DI 0 "s_register_operand" "")
4453
        (sign_extend:DI (match_operand 1 "nonimmediate_operand" "")))]
4454
  "TARGET_32BIT"
4455
  [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
4456
{
4457
  rtx lo_part = gen_lowpart (SImode, operands[0]);
4458
  enum machine_mode src_mode = GET_MODE (operands[1]);
4459
 
4460
  if (REG_P (operands[0])
4461
      && !reg_overlap_mentioned_p (operands[0], operands[1]))
4462
    emit_clobber (operands[0]);
4463
 
4464
  if (!REG_P (lo_part) || src_mode != SImode
4465
      || !rtx_equal_p (lo_part, operands[1]))
4466
    {
4467
      if (src_mode == SImode)
4468
        emit_move_insn (lo_part, operands[1]);
4469
      else
4470
        emit_insn (gen_rtx_SET (VOIDmode, lo_part,
4471
                                gen_rtx_SIGN_EXTEND (SImode, operands[1])));
4472
      operands[1] = lo_part;
4473
    }
4474
  operands[0] = gen_highpart (SImode, operands[0]);
4475
})
4476
 
4477
(define_expand "zero_extendhisi2"
4478
  [(set (match_operand:SI 0 "s_register_operand" "")
4479
        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4480
  "TARGET_EITHER"
4481
{
4482
  if (TARGET_ARM && !arm_arch4 && MEM_P (operands[1]))
4483
    {
4484
      emit_insn (gen_movhi_bytes (operands[0], operands[1]));
4485
      DONE;
4486
    }
4487
  if (!arm_arch6 && !MEM_P (operands[1]))
4488
    {
4489
      rtx t = gen_lowpart (SImode, operands[1]);
4490
      rtx tmp = gen_reg_rtx (SImode);
4491
      emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4492
      emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (16)));
4493
      DONE;
4494
    }
4495
})
4496
 
4497
(define_split
4498
  [(set (match_operand:SI 0 "s_register_operand" "")
4499
        (zero_extend:SI (match_operand:HI 1 "s_register_operand" "")))]
4500
  "!TARGET_THUMB2 && !arm_arch6"
4501
  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4502
   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 16)))]
4503
{
4504
  operands[2] = gen_lowpart (SImode, operands[1]);
4505
})
4506
 
4507
(define_insn "*thumb1_zero_extendhisi2"
4508
  [(set (match_operand:SI 0 "register_operand" "=l,l")
4509
        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
4510
  "TARGET_THUMB1"
4511
{
4512
  rtx mem;
4513
 
4514
  if (which_alternative == 0 && arm_arch6)
4515
    return "uxth\t%0, %1";
4516
  if (which_alternative == 0)
4517
    return "#";
4518
 
4519
  mem = XEXP (operands[1], 0);
4520
 
4521
  if (GET_CODE (mem) == CONST)
4522
    mem = XEXP (mem, 0);
4523
 
4524
  if (GET_CODE (mem) == PLUS)
4525
    {
4526
      rtx a = XEXP (mem, 0);
4527
 
4528
      /* This can happen due to bugs in reload.  */
4529
      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
4530
        {
4531
          rtx ops[2];
4532
          ops[0] = operands[0];
4533
          ops[1] = a;
4534
 
4535
          output_asm_insn ("mov\t%0, %1", ops);
4536
 
4537
          XEXP (mem, 0) = operands[0];
4538
       }
4539
    }
4540
 
4541
  return "ldrh\t%0, %1";
4542
}
4543
  [(set_attr_alternative "length"
4544
                         [(if_then_else (eq_attr "is_arch6" "yes")
4545
                                       (const_int 2) (const_int 4))
4546
                         (const_int 4)])
4547
   (set_attr "type" "alu_shift,load_byte")]
4548
)
4549
 
4550
(define_insn "*arm_zero_extendhisi2"
4551
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4552
        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4553
  "TARGET_ARM && arm_arch4 && !arm_arch6"
4554
  "@
4555
   #
4556
   ldr%(h%)\\t%0, %1"
4557
  [(set_attr "type" "alu_shift,load_byte")
4558
   (set_attr "predicable" "yes")]
4559
)
4560
 
4561
(define_insn "*arm_zero_extendhisi2_v6"
4562
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4563
        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4564
  "TARGET_ARM && arm_arch6"
4565
  "@
4566
   uxth%?\\t%0, %1
4567
   ldr%(h%)\\t%0, %1"
4568
  [(set_attr "type" "alu_shift,load_byte")
4569
   (set_attr "predicable" "yes")]
4570
)
4571
 
4572
(define_insn "*arm_zero_extendhisi2addsi"
4573
  [(set (match_operand:SI 0 "s_register_operand" "=r")
4574
        (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4575
                 (match_operand:SI 2 "s_register_operand" "r")))]
4576
  "TARGET_INT_SIMD"
4577
  "uxtah%?\\t%0, %2, %1"
4578
  [(set_attr "type" "alu_shift")
4579
   (set_attr "predicable" "yes")]
4580
)
4581
 
4582
(define_expand "zero_extendqisi2"
4583
  [(set (match_operand:SI 0 "s_register_operand" "")
4584
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
4585
  "TARGET_EITHER"
4586
{
4587
  if (TARGET_ARM && !arm_arch6 && GET_CODE (operands[1]) != MEM)
4588
    {
4589
      emit_insn (gen_andsi3 (operands[0],
4590
                             gen_lowpart (SImode, operands[1]),
4591
                                          GEN_INT (255)));
4592
      DONE;
4593
    }
4594
  if (!arm_arch6 && !MEM_P (operands[1]))
4595
    {
4596
      rtx t = gen_lowpart (SImode, operands[1]);
4597
      rtx tmp = gen_reg_rtx (SImode);
4598
      emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4599
      emit_insn (gen_lshrsi3 (operands[0], tmp, GEN_INT (24)));
4600
      DONE;
4601
    }
4602
})
4603
 
4604
(define_split
4605
  [(set (match_operand:SI 0 "s_register_operand" "")
4606
        (zero_extend:SI (match_operand:QI 1 "s_register_operand" "")))]
4607
  "!arm_arch6"
4608
  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4609
   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
4610
{
4611
  operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4612
  if (TARGET_ARM)
4613
    {
4614
      emit_insn (gen_andsi3 (operands[0], operands[2], GEN_INT (255)));
4615
      DONE;
4616
    }
4617
})
4618
 
4619
(define_insn "*thumb1_zero_extendqisi2"
4620
  [(set (match_operand:SI 0 "register_operand" "=l,l")
4621
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4622
  "TARGET_THUMB1 && !arm_arch6"
4623
  "@
4624
   #
4625
   ldrb\\t%0, %1"
4626
  [(set_attr "length" "4,2")
4627
   (set_attr "type" "alu_shift,load_byte")
4628
   (set_attr "pool_range" "*,32")]
4629
)
4630
 
4631
(define_insn "*thumb1_zero_extendqisi2_v6"
4632
  [(set (match_operand:SI 0 "register_operand" "=l,l")
4633
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
4634
  "TARGET_THUMB1 && arm_arch6"
4635
  "@
4636
   uxtb\\t%0, %1
4637
   ldrb\\t%0, %1"
4638
  [(set_attr "length" "2")
4639
   (set_attr "type" "alu_shift,load_byte")]
4640
)
4641
 
4642
(define_insn "*arm_zero_extendqisi2"
4643
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4644
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4645
  "TARGET_ARM && !arm_arch6"
4646
  "@
4647
   #
4648
   ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4649
  [(set_attr "length" "8,4")
4650
   (set_attr "type" "alu_shift,load_byte")
4651
   (set_attr "predicable" "yes")]
4652
)
4653
 
4654
(define_insn "*arm_zero_extendqisi2_v6"
4655
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4656
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
4657
  "TARGET_ARM && arm_arch6"
4658
  "@
4659
   uxtb%(%)\\t%0, %1
4660
   ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
4661
  [(set_attr "type" "alu_shift,load_byte")
4662
   (set_attr "predicable" "yes")]
4663
)
4664
 
4665
(define_insn "*arm_zero_extendqisi2addsi"
4666
  [(set (match_operand:SI 0 "s_register_operand" "=r")
4667
        (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
4668
                 (match_operand:SI 2 "s_register_operand" "r")))]
4669
  "TARGET_INT_SIMD"
4670
  "uxtab%?\\t%0, %2, %1"
4671
  [(set_attr "predicable" "yes")
4672
   (set_attr "insn" "xtab")
4673
   (set_attr "type" "alu_shift")]
4674
)
4675
 
4676
(define_split
4677
  [(set (match_operand:SI 0 "s_register_operand" "")
4678
        (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
4679
   (clobber (match_operand:SI 2 "s_register_operand" ""))]
4680
  "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
4681
  [(set (match_dup 2) (match_dup 1))
4682
   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4683
  ""
4684
)
4685
 
4686
(define_split
4687
  [(set (match_operand:SI 0 "s_register_operand" "")
4688
        (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
4689
   (clobber (match_operand:SI 2 "s_register_operand" ""))]
4690
  "TARGET_32BIT && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
4691
  [(set (match_dup 2) (match_dup 1))
4692
   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
4693
  ""
4694
)
4695
 
4696
 
4697
(define_split
4698
  [(set (match_operand:SI 0 "s_register_operand" "")
4699
        (ior_xor:SI (and:SI (ashift:SI
4700
                             (match_operand:SI 1 "s_register_operand" "")
4701
                             (match_operand:SI 2 "const_int_operand" ""))
4702
                            (match_operand:SI 3 "const_int_operand" ""))
4703
                    (zero_extend:SI
4704
                     (match_operator 5 "subreg_lowpart_operator"
4705
                      [(match_operand:SI 4 "s_register_operand" "")]))))]
4706
  "TARGET_32BIT
4707
   && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
4708
       == (GET_MODE_MASK (GET_MODE (operands[5]))
4709
           & (GET_MODE_MASK (GET_MODE (operands[5]))
4710
              << (INTVAL (operands[2])))))"
4711
  [(set (match_dup 0) (ior_xor:SI (ashift:SI (match_dup 1) (match_dup 2))
4712
                                  (match_dup 4)))
4713
   (set (match_dup 0) (zero_extend:SI (match_dup 5)))]
4714
  "operands[5] = gen_lowpart (GET_MODE (operands[5]), operands[0]);"
4715
)
4716
 
4717
(define_insn "*compareqi_eq0"
4718
  [(set (reg:CC_Z CC_REGNUM)
4719
        (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
4720
                         (const_int 0)))]
4721
  "TARGET_32BIT"
4722
  "tst%?\\t%0, #255"
4723
  [(set_attr "conds" "set")
4724
   (set_attr "predicable" "yes")]
4725
)
4726
 
4727
(define_expand "extendhisi2"
4728
  [(set (match_operand:SI 0 "s_register_operand" "")
4729
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
4730
  "TARGET_EITHER"
4731
{
4732
  if (TARGET_THUMB1)
4733
    {
4734
      emit_insn (gen_thumb1_extendhisi2 (operands[0], operands[1]));
4735
      DONE;
4736
    }
4737
  if (MEM_P (operands[1]) && TARGET_ARM && !arm_arch4)
4738
    {
4739
      emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
4740
      DONE;
4741
    }
4742
 
4743
  if (!arm_arch6 && !MEM_P (operands[1]))
4744
    {
4745
      rtx t = gen_lowpart (SImode, operands[1]);
4746
      rtx tmp = gen_reg_rtx (SImode);
4747
      emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (16)));
4748
      emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (16)));
4749
      DONE;
4750
    }
4751
})
4752
 
4753
(define_split
4754
  [(parallel
4755
    [(set (match_operand:SI 0 "register_operand" "")
4756
          (sign_extend:SI (match_operand:HI 1 "register_operand" "")))
4757
     (clobber (match_scratch:SI 2 ""))])]
4758
  "!arm_arch6"
4759
  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4760
   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4761
{
4762
  operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4763
})
4764
 
4765
;; We used to have an early-clobber on the scratch register here.
4766
;; However, there's a bug somewhere in reload which means that this
4767
;; can be partially ignored during spill allocation if the memory
4768
;; address also needs reloading; this causes us to die later on when
4769
;; we try to verify the operands.  Fortunately, we don't really need
4770
;; the early-clobber: we can always use operand 0 if operand 2
4771
;; overlaps the address.
4772
(define_insn "thumb1_extendhisi2"
4773
  [(set (match_operand:SI 0 "register_operand" "=l,l")
4774
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
4775
   (clobber (match_scratch:SI 2 "=X,l"))]
4776
  "TARGET_THUMB1"
4777
  "*
4778
  {
4779
    rtx ops[4];
4780
    rtx mem;
4781
 
4782
    if (which_alternative == 0 && !arm_arch6)
4783
      return \"#\";
4784
    if (which_alternative == 0)
4785
      return \"sxth\\t%0, %1\";
4786
 
4787
    mem = XEXP (operands[1], 0);
4788
 
4789
    /* This code used to try to use 'V', and fix the address only if it was
4790
       offsettable, but this fails for e.g. REG+48 because 48 is outside the
4791
       range of QImode offsets, and offsettable_address_p does a QImode
4792
       address check.  */
4793
 
4794
    if (GET_CODE (mem) == CONST)
4795
      mem = XEXP (mem, 0);
4796
 
4797
    if (GET_CODE (mem) == LABEL_REF)
4798
      return \"ldr\\t%0, %1\";
4799
 
4800
    if (GET_CODE (mem) == PLUS)
4801
      {
4802
        rtx a = XEXP (mem, 0);
4803
        rtx b = XEXP (mem, 1);
4804
 
4805
        if (GET_CODE (a) == LABEL_REF
4806
            && GET_CODE (b) == CONST_INT)
4807
          return \"ldr\\t%0, %1\";
4808
 
4809
        if (GET_CODE (b) == REG)
4810
          return \"ldrsh\\t%0, %1\";
4811
 
4812
        ops[1] = a;
4813
        ops[2] = b;
4814
      }
4815
    else
4816
      {
4817
        ops[1] = mem;
4818
        ops[2] = const0_rtx;
4819
      }
4820
 
4821
    gcc_assert (GET_CODE (ops[1]) == REG);
4822
 
4823
    ops[0] = operands[0];
4824
    if (reg_mentioned_p (operands[2], ops[1]))
4825
      ops[3] = ops[0];
4826
    else
4827
      ops[3] = operands[2];
4828
    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
4829
    return \"\";
4830
  }"
4831
  [(set_attr_alternative "length"
4832
                         [(if_then_else (eq_attr "is_arch6" "yes")
4833
                                        (const_int 2) (const_int 4))
4834
                          (const_int 4)])
4835
   (set_attr "type" "alu_shift,load_byte")
4836
   (set_attr "pool_range" "*,1020")]
4837
)
4838
 
4839
;; This pattern will only be used when ldsh is not available
4840
(define_expand "extendhisi2_mem"
4841
  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4842
   (set (match_dup 3)
4843
        (zero_extend:SI (match_dup 7)))
4844
   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
4845
   (set (match_operand:SI 0 "" "")
4846
        (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
4847
  "TARGET_ARM"
4848
  "
4849
  {
4850
    rtx mem1, mem2;
4851
    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4852
 
4853
    mem1 = change_address (operands[1], QImode, addr);
4854
    mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4855
    operands[0] = gen_lowpart (SImode, operands[0]);
4856
    operands[1] = mem1;
4857
    operands[2] = gen_reg_rtx (SImode);
4858
    operands[3] = gen_reg_rtx (SImode);
4859
    operands[6] = gen_reg_rtx (SImode);
4860
    operands[7] = mem2;
4861
 
4862
    if (BYTES_BIG_ENDIAN)
4863
      {
4864
        operands[4] = operands[2];
4865
        operands[5] = operands[3];
4866
      }
4867
    else
4868
      {
4869
        operands[4] = operands[3];
4870
        operands[5] = operands[2];
4871
      }
4872
  }"
4873
)
4874
 
4875
(define_split
4876
  [(set (match_operand:SI 0 "register_operand" "")
4877
        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
4878
  "!arm_arch6"
4879
  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 16)))
4880
   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 16)))]
4881
{
4882
  operands[2] = simplify_gen_subreg (SImode, operands[1], HImode, 0);
4883
})
4884
 
4885
(define_insn "*arm_extendhisi2"
4886
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4887
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4888
  "TARGET_ARM && arm_arch4 && !arm_arch6"
4889
  "@
4890
   #
4891
   ldr%(sh%)\\t%0, %1"
4892
  [(set_attr "length" "8,4")
4893
   (set_attr "type" "alu_shift,load_byte")
4894
   (set_attr "predicable" "yes")
4895
   (set_attr "pool_range" "*,256")
4896
   (set_attr "neg_pool_range" "*,244")]
4897
)
4898
 
4899
;; ??? Check Thumb-2 pool range
4900
(define_insn "*arm_extendhisi2_v6"
4901
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4902
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
4903
  "TARGET_32BIT && arm_arch6"
4904
  "@
4905
   sxth%?\\t%0, %1
4906
   ldr%(sh%)\\t%0, %1"
4907
  [(set_attr "type" "alu_shift,load_byte")
4908
   (set_attr "predicable" "yes")
4909
   (set_attr "pool_range" "*,256")
4910
   (set_attr "neg_pool_range" "*,244")]
4911
)
4912
 
4913
(define_insn "*arm_extendhisi2addsi"
4914
  [(set (match_operand:SI 0 "s_register_operand" "=r")
4915
        (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
4916
                 (match_operand:SI 2 "s_register_operand" "r")))]
4917
  "TARGET_INT_SIMD"
4918
  "sxtah%?\\t%0, %2, %1"
4919
)
4920
 
4921
(define_expand "extendqihi2"
4922
  [(set (match_dup 2)
4923
        (ashift:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")
4924
                   (const_int 24)))
4925
   (set (match_operand:HI 0 "s_register_operand" "")
4926
        (ashiftrt:SI (match_dup 2)
4927
                     (const_int 24)))]
4928
  "TARGET_ARM"
4929
  "
4930
  {
4931
    if (arm_arch4 && GET_CODE (operands[1]) == MEM)
4932
      {
4933
        emit_insn (gen_rtx_SET (VOIDmode,
4934
                                operands[0],
4935
                                gen_rtx_SIGN_EXTEND (HImode, operands[1])));
4936
        DONE;
4937
      }
4938
    if (!s_register_operand (operands[1], QImode))
4939
      operands[1] = copy_to_mode_reg (QImode, operands[1]);
4940
    operands[0] = gen_lowpart (SImode, operands[0]);
4941
    operands[1] = gen_lowpart (SImode, operands[1]);
4942
    operands[2] = gen_reg_rtx (SImode);
4943
  }"
4944
)
4945
 
4946
(define_insn "*arm_extendqihi_insn"
4947
  [(set (match_operand:HI 0 "s_register_operand" "=r")
4948
        (sign_extend:HI (match_operand:QI 1 "arm_extendqisi_mem_op" "Uq")))]
4949
  "TARGET_ARM && arm_arch4"
4950
  "ldr%(sb%)\\t%0, %1"
4951
  [(set_attr "type" "load_byte")
4952
   (set_attr "predicable" "yes")
4953
   (set_attr "pool_range" "256")
4954
   (set_attr "neg_pool_range" "244")]
4955
)
4956
 
4957
(define_expand "extendqisi2"
4958
  [(set (match_operand:SI 0 "s_register_operand" "")
4959
        (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "")))]
4960
  "TARGET_EITHER"
4961
{
4962
  if (!arm_arch4 && MEM_P (operands[1]))
4963
    operands[1] = copy_to_mode_reg (QImode, operands[1]);
4964
 
4965
  if (!arm_arch6 && !MEM_P (operands[1]))
4966
    {
4967
      rtx t = gen_lowpart (SImode, operands[1]);
4968
      rtx tmp = gen_reg_rtx (SImode);
4969
      emit_insn (gen_ashlsi3 (tmp, t, GEN_INT (24)));
4970
      emit_insn (gen_ashrsi3 (operands[0], tmp, GEN_INT (24)));
4971
      DONE;
4972
    }
4973
})
4974
 
4975
(define_split
4976
  [(set (match_operand:SI 0 "register_operand" "")
4977
        (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
4978
  "!arm_arch6"
4979
  [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
4980
   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))]
4981
{
4982
  operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);
4983
})
4984
 
4985
(define_insn "*arm_extendqisi"
4986
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4987
        (sign_extend:SI (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
4988
  "TARGET_ARM && arm_arch4 && !arm_arch6"
4989
  "@
4990
   #
4991
   ldr%(sb%)\\t%0, %1"
4992
  [(set_attr "length" "8,4")
4993
   (set_attr "type" "alu_shift,load_byte")
4994
   (set_attr "predicable" "yes")
4995
   (set_attr "pool_range" "*,256")
4996
   (set_attr "neg_pool_range" "*,244")]
4997
)
4998
 
4999
(define_insn "*arm_extendqisi_v6"
5000
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5001
        (sign_extend:SI
5002
         (match_operand:QI 1 "arm_reg_or_extendqisi_mem_op" "r,Uq")))]
5003
  "TARGET_ARM && arm_arch6"
5004
  "@
5005
   sxtb%?\\t%0, %1
5006
   ldr%(sb%)\\t%0, %1"
5007
  [(set_attr "type" "alu_shift,load_byte")
5008
   (set_attr "predicable" "yes")
5009
   (set_attr "pool_range" "*,256")
5010
   (set_attr "neg_pool_range" "*,244")]
5011
)
5012
 
5013
(define_insn "*arm_extendqisi2addsi"
5014
  [(set (match_operand:SI 0 "s_register_operand" "=r")
5015
        (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
5016
                 (match_operand:SI 2 "s_register_operand" "r")))]
5017
  "TARGET_INT_SIMD"
5018
  "sxtab%?\\t%0, %2, %1"
5019
  [(set_attr "type" "alu_shift")
5020
   (set_attr "insn" "xtab")
5021
   (set_attr "predicable" "yes")]
5022
)
5023
 
5024
(define_split
5025
  [(set (match_operand:SI 0 "register_operand" "")
5026
        (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
5027
  "TARGET_THUMB1 && reload_completed"
5028
  [(set (match_dup 0) (match_dup 2))
5029
   (set (match_dup 0) (sign_extend:SI (match_dup 3)))]
5030
{
5031
  rtx addr = XEXP (operands[1], 0);
5032
 
5033
  if (GET_CODE (addr) == CONST)
5034
    addr = XEXP (addr, 0);
5035
 
5036
  if (GET_CODE (addr) == PLUS
5037
      && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5038
    /* No split necessary.  */
5039
    FAIL;
5040
 
5041
  if (GET_CODE (addr) == PLUS
5042
      && !REG_P (XEXP (addr, 0)) && !REG_P (XEXP (addr, 1)))
5043
    FAIL;
5044
 
5045
  if (reg_overlap_mentioned_p (operands[0], addr))
5046
    {
5047
      rtx t = gen_lowpart (QImode, operands[0]);
5048
      emit_move_insn (t, operands[1]);
5049
      emit_insn (gen_thumb1_extendqisi2 (operands[0], t));
5050
      DONE;
5051
    }
5052
 
5053
  if (REG_P (addr))
5054
    {
5055
      addr = gen_rtx_PLUS (Pmode, addr, operands[0]);
5056
      operands[2] = const0_rtx;
5057
    }
5058
  else if (GET_CODE (addr) != PLUS)
5059
    FAIL;
5060
  else if (REG_P (XEXP (addr, 0)))
5061
    {
5062
      operands[2] = XEXP (addr, 1);
5063
      addr = gen_rtx_PLUS (Pmode, XEXP (addr, 0), operands[0]);
5064
    }
5065
  else
5066
    {
5067
      operands[2] = XEXP (addr, 0);
5068
      addr = gen_rtx_PLUS (Pmode, XEXP (addr, 1), operands[0]);
5069
    }
5070
 
5071
  operands[3] = change_address (operands[1], QImode, addr);
5072
})
5073
 
5074
(define_peephole2
5075
  [(set (match_operand:SI 0 "register_operand" "")
5076
        (plus:SI (match_dup 0) (match_operand 1 "const_int_operand")))
5077
   (set (match_operand:SI 2 "register_operand" "") (const_int 0))
5078
   (set (match_operand:SI 3 "register_operand" "")
5079
        (sign_extend:SI (match_operand:QI 4 "memory_operand" "")))]
5080
  "TARGET_THUMB1
5081
   && GET_CODE (XEXP (operands[4], 0)) == PLUS
5082
   && rtx_equal_p (operands[0], XEXP (XEXP (operands[4], 0), 0))
5083
   && rtx_equal_p (operands[2], XEXP (XEXP (operands[4], 0), 1))
5084
   && (peep2_reg_dead_p (3, operands[0])
5085
       || rtx_equal_p (operands[0], operands[3]))
5086
   && (peep2_reg_dead_p (3, operands[2])
5087
       || rtx_equal_p (operands[2], operands[3]))"
5088
  [(set (match_dup 2) (match_dup 1))
5089
   (set (match_dup 3) (sign_extend:SI (match_dup 4)))]
5090
{
5091
  rtx addr = gen_rtx_PLUS (Pmode, operands[0], operands[2]);
5092
  operands[4] = change_address (operands[4], QImode, addr);
5093
})
5094
 
5095
(define_insn "thumb1_extendqisi2"
5096
  [(set (match_operand:SI 0 "register_operand" "=l,l,l")
5097
        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
5098
  "TARGET_THUMB1"
5099
{
5100
  rtx addr;
5101
 
5102
  if (which_alternative == 0 && arm_arch6)
5103
    return "sxtb\\t%0, %1";
5104
  if (which_alternative == 0)
5105
    return "#";
5106
 
5107
  addr = XEXP (operands[1], 0);
5108
  if (GET_CODE (addr) == PLUS
5109
      && REG_P (XEXP (addr, 0)) && REG_P (XEXP (addr, 1)))
5110
    return "ldrsb\\t%0, %1";
5111
 
5112
  return "#";
5113
}
5114
  [(set_attr_alternative "length"
5115
                         [(if_then_else (eq_attr "is_arch6" "yes")
5116
                                        (const_int 2) (const_int 4))
5117
                          (const_int 2)
5118
                          (if_then_else (eq_attr "is_arch6" "yes")
5119
                                        (const_int 4) (const_int 6))])
5120
   (set_attr "type" "alu_shift,load_byte,load_byte")]
5121
)
5122
 
5123
(define_expand "extendsfdf2"
5124
  [(set (match_operand:DF                  0 "s_register_operand" "")
5125
        (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
5126
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
5127
  ""
5128
)
5129
 
5130
/* HFmode -> DFmode conversions have to go through SFmode.  */
5131
(define_expand "extendhfdf2"
5132
  [(set (match_operand:DF                  0 "general_operand" "")
5133
        (float_extend:DF (match_operand:HF 1 "general_operand"  "")))]
5134
  "TARGET_EITHER"
5135
  "
5136
  {
5137
    rtx op1;
5138
    op1 = convert_to_mode (SFmode, operands[1], 0);
5139
    op1 = convert_to_mode (DFmode, op1, 0);
5140
    emit_insn (gen_movdf (operands[0], op1));
5141
    DONE;
5142
  }"
5143
)
5144
 
5145
;; Move insns (including loads and stores)
5146
 
5147
;; XXX Just some ideas about movti.
5148
;; I don't think these are a good idea on the arm, there just aren't enough
5149
;; registers
5150
;;(define_expand "loadti"
5151
;;  [(set (match_operand:TI 0 "s_register_operand" "")
5152
;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
5153
;;  "" "")
5154
 
5155
;;(define_expand "storeti"
5156
;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
5157
;;      (match_operand:TI 1 "s_register_operand" ""))]
5158
;;  "" "")
5159
 
5160
;;(define_expand "movti"
5161
;;  [(set (match_operand:TI 0 "general_operand" "")
5162
;;      (match_operand:TI 1 "general_operand" ""))]
5163
;;  ""
5164
;;  "
5165
;;{
5166
;;  rtx insn;
5167
;;
5168
;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
5169
;;    operands[1] = copy_to_reg (operands[1]);
5170
;;  if (GET_CODE (operands[0]) == MEM)
5171
;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
5172
;;  else if (GET_CODE (operands[1]) == MEM)
5173
;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
5174
;;  else
5175
;;    FAIL;
5176
;;
5177
;;  emit_insn (insn);
5178
;;  DONE;
5179
;;}")
5180
 
5181
;; Recognize garbage generated above.
5182
 
5183
;;(define_insn ""
5184
;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
5185
;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
5186
;;  ""
5187
;;  "*
5188
;;  {
5189
;;    register mem = (which_alternative < 3);
5190
;;    register const char *template;
5191
;;
5192
;;    operands[mem] = XEXP (operands[mem], 0);
5193
;;    switch (which_alternative)
5194
;;      {
5195
;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
5196
;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
5197
;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
5198
;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
5199
;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
5200
;;      case 5: template = \"stmia\\t%0, %M1\"; break;
5201
;;      }
5202
;;    output_asm_insn (template, operands);
5203
;;    return \"\";
5204
;;  }")
5205
 
5206
(define_expand "movdi"
5207
  [(set (match_operand:DI 0 "general_operand" "")
5208
        (match_operand:DI 1 "general_operand" ""))]
5209
  "TARGET_EITHER"
5210
  "
5211
  if (can_create_pseudo_p ())
5212
    {
5213
      if (GET_CODE (operands[0]) != REG)
5214
        operands[1] = force_reg (DImode, operands[1]);
5215
    }
5216
  "
5217
)
5218
 
5219
(define_insn "*arm_movdi"
5220
  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
5221
        (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
5222
  "TARGET_32BIT
5223
   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
5224
   && !TARGET_IWMMXT
5225
   && (   register_operand (operands[0], DImode)
5226
       || register_operand (operands[1], DImode))"
5227
  "*
5228
  switch (which_alternative)
5229
    {
5230
    case 0:
5231
    case 1:
5232
    case 2:
5233
      return \"#\";
5234
    default:
5235
      return output_move_double (operands, true, NULL);
5236
    }
5237
  "
5238
  [(set_attr "length" "8,12,16,8,8")
5239
   (set_attr "type" "*,*,*,load2,store2")
5240
   (set_attr "arm_pool_range" "*,*,*,1020,*")
5241
   (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
5242
   (set_attr "thumb2_pool_range" "*,*,*,4096,*")
5243
   (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
5244
)
5245
 
5246
(define_split
5247
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5248
        (match_operand:ANY64 1 "const_double_operand" ""))]
5249
  "TARGET_32BIT
5250
   && reload_completed
5251
   && (arm_const_double_inline_cost (operands[1])
5252
       <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
5253
  [(const_int 0)]
5254
  "
5255
  arm_split_constant (SET, SImode, curr_insn,
5256
                      INTVAL (gen_lowpart (SImode, operands[1])),
5257
                      gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
5258
  arm_split_constant (SET, SImode, curr_insn,
5259
                      INTVAL (gen_highpart_mode (SImode,
5260
                                                 GET_MODE (operands[0]),
5261
                                                 operands[1])),
5262
                      gen_highpart (SImode, operands[0]), NULL_RTX, 0);
5263
  DONE;
5264
  "
5265
)
5266
 
5267
; If optimizing for size, or if we have load delay slots, then
5268
; we want to split the constant into two separate operations.
5269
; In both cases this may split a trivial part into a single data op
5270
; leaving a single complex constant to load.  We can also get longer
5271
; offsets in a LDR which means we get better chances of sharing the pool
5272
; entries.  Finally, we can normally do a better job of scheduling
5273
; LDR instructions than we can with LDM.
5274
; This pattern will only match if the one above did not.
5275
(define_split
5276
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5277
        (match_operand:ANY64 1 "const_double_operand" ""))]
5278
  "TARGET_ARM && reload_completed
5279
   && arm_const_double_by_parts (operands[1])"
5280
  [(set (match_dup 0) (match_dup 1))
5281
   (set (match_dup 2) (match_dup 3))]
5282
  "
5283
  operands[2] = gen_highpart (SImode, operands[0]);
5284
  operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
5285
                                   operands[1]);
5286
  operands[0] = gen_lowpart (SImode, operands[0]);
5287
  operands[1] = gen_lowpart (SImode, operands[1]);
5288
  "
5289
)
5290
 
5291
(define_split
5292
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
5293
        (match_operand:ANY64 1 "arm_general_register_operand" ""))]
5294
  "TARGET_EITHER && reload_completed"
5295
  [(set (match_dup 0) (match_dup 1))
5296
   (set (match_dup 2) (match_dup 3))]
5297
  "
5298
  operands[2] = gen_highpart (SImode, operands[0]);
5299
  operands[3] = gen_highpart (SImode, operands[1]);
5300
  operands[0] = gen_lowpart (SImode, operands[0]);
5301
  operands[1] = gen_lowpart (SImode, operands[1]);
5302
 
5303
  /* Handle a partial overlap.  */
5304
  if (rtx_equal_p (operands[0], operands[3]))
5305
    {
5306
      rtx tmp0 = operands[0];
5307
      rtx tmp1 = operands[1];
5308
 
5309
      operands[0] = operands[2];
5310
      operands[1] = operands[3];
5311
      operands[2] = tmp0;
5312
      operands[3] = tmp1;
5313
    }
5314
  "
5315
)
5316
 
5317
;; We can't actually do base+index doubleword loads if the index and
5318
;; destination overlap.  Split here so that we at least have chance to
5319
;; schedule.
5320
(define_split
5321
  [(set (match_operand:DI 0 "s_register_operand" "")
5322
        (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
5323
                         (match_operand:SI 2 "s_register_operand" ""))))]
5324
  "TARGET_LDRD
5325
  && reg_overlap_mentioned_p (operands[0], operands[1])
5326
  && reg_overlap_mentioned_p (operands[0], operands[2])"
5327
  [(set (match_dup 4)
5328
        (plus:SI (match_dup 1)
5329
                 (match_dup 2)))
5330
   (set (match_dup 0)
5331
        (mem:DI (match_dup 4)))]
5332
  "
5333
  operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
5334
  "
5335
)
5336
 
5337
;;; ??? This should have alternatives for constants.
5338
;;; ??? This was originally identical to the movdf_insn pattern.
5339
;;; ??? The 'i' constraint looks funny, but it should always be replaced by
5340
;;; thumb_reorg with a memory reference.
5341
(define_insn "*thumb1_movdi_insn"
5342
  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
5343
        (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
5344
  "TARGET_THUMB1
5345
   && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
5346
   && (   register_operand (operands[0], DImode)
5347
       || register_operand (operands[1], DImode))"
5348
  "*
5349
  {
5350
  switch (which_alternative)
5351
    {
5352
    default:
5353
    case 0:
5354
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5355
        return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
5356
      return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
5357
    case 1:
5358
      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
5359
    case 2:
5360
      operands[1] = GEN_INT (- INTVAL (operands[1]));
5361
      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
5362
    case 3:
5363
      return \"ldmia\\t%1, {%0, %H0}\";
5364
    case 4:
5365
      return \"stmia\\t%0, {%1, %H1}\";
5366
    case 5:
5367
      return thumb_load_double_from_address (operands);
5368
    case 6:
5369
      operands[2] = gen_rtx_MEM (SImode,
5370
                             plus_constant (XEXP (operands[0], 0), 4));
5371
      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5372
      return \"\";
5373
    case 7:
5374
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5375
        return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5376
      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5377
    }
5378
  }"
5379
  [(set_attr "length" "4,4,6,2,2,6,4,4")
5380
   (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
5381
   (set_attr "insn" "*,mov,*,*,*,*,*,mov")
5382
   (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
5383
)
5384
 
5385
(define_expand "movsi"
5386
  [(set (match_operand:SI 0 "general_operand" "")
5387
        (match_operand:SI 1 "general_operand" ""))]
5388
  "TARGET_EITHER"
5389
  "
5390
  {
5391
  rtx base, offset, tmp;
5392
 
5393
  if (TARGET_32BIT)
5394
    {
5395
      /* Everything except mem = const or mem = mem can be done easily.  */
5396
      if (GET_CODE (operands[0]) == MEM)
5397
        operands[1] = force_reg (SImode, operands[1]);
5398
      if (arm_general_register_operand (operands[0], SImode)
5399
          && GET_CODE (operands[1]) == CONST_INT
5400
          && !(const_ok_for_arm (INTVAL (operands[1]))
5401
               || const_ok_for_arm (~INTVAL (operands[1]))))
5402
        {
5403
           arm_split_constant (SET, SImode, NULL_RTX,
5404
                               INTVAL (operands[1]), operands[0], NULL_RTX,
5405
                               optimize && can_create_pseudo_p ());
5406
          DONE;
5407
        }
5408
 
5409
      if (TARGET_USE_MOVT && !target_word_relocations
5410
          && GET_CODE (operands[1]) == SYMBOL_REF
5411
          && !flag_pic && !arm_tls_referenced_p (operands[1]))
5412
        {
5413
          arm_emit_movpair (operands[0], operands[1]);
5414
          DONE;
5415
        }
5416
    }
5417
  else /* TARGET_THUMB1...  */
5418
    {
5419
      if (can_create_pseudo_p ())
5420
        {
5421
          if (GET_CODE (operands[0]) != REG)
5422
            operands[1] = force_reg (SImode, operands[1]);
5423
        }
5424
    }
5425
 
5426
  if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
5427
    {
5428
      split_const (operands[1], &base, &offset);
5429
      if (GET_CODE (base) == SYMBOL_REF
5430
          && !offset_within_block_p (base, INTVAL (offset)))
5431
        {
5432
          tmp = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5433
          emit_move_insn (tmp, base);
5434
          emit_insn (gen_addsi3 (operands[0], tmp, offset));
5435
          DONE;
5436
        }
5437
    }
5438
 
5439
  /* Recognize the case where operand[1] is a reference to thread-local
5440
     data and load its address to a register.  */
5441
  if (arm_tls_referenced_p (operands[1]))
5442
    {
5443
      rtx tmp = operands[1];
5444
      rtx addend = NULL;
5445
 
5446
      if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
5447
        {
5448
          addend = XEXP (XEXP (tmp, 0), 1);
5449
          tmp = XEXP (XEXP (tmp, 0), 0);
5450
        }
5451
 
5452
      gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
5453
      gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
5454
 
5455
      tmp = legitimize_tls_address (tmp,
5456
                                    !can_create_pseudo_p () ? operands[0] : 0);
5457
      if (addend)
5458
        {
5459
          tmp = gen_rtx_PLUS (SImode, tmp, addend);
5460
          tmp = force_operand (tmp, operands[0]);
5461
        }
5462
      operands[1] = tmp;
5463
    }
5464
  else if (flag_pic
5465
           && (CONSTANT_P (operands[1])
5466
               || symbol_mentioned_p (operands[1])
5467
               || label_mentioned_p (operands[1])))
5468
      operands[1] = legitimize_pic_address (operands[1], SImode,
5469
                                            (!can_create_pseudo_p ()
5470
                                             ? operands[0]
5471
                                             : 0));
5472
  }
5473
  "
5474
)
5475
 
5476
;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
5477
;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
5478
;; so this does not matter.
5479
(define_insn "*arm_movt"
5480
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
5481
        (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
5482
                   (match_operand:SI 2 "general_operand"      "i")))]
5483
  "arm_arch_thumb2"
5484
  "movt%?\t%0, #:upper16:%c2"
5485
  [(set_attr "predicable" "yes")
5486
   (set_attr "length" "4")]
5487
)
5488
 
5489
(define_insn "*arm_movsi_insn"
5490
  [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
5491
        (match_operand:SI 1 "general_operand"      "rk, I,K,j,mi,rk"))]
5492
  "TARGET_ARM && ! TARGET_IWMMXT
5493
   && !(TARGET_HARD_FLOAT && TARGET_VFP)
5494
   && (   register_operand (operands[0], SImode)
5495
       || register_operand (operands[1], SImode))"
5496
  "@
5497
   mov%?\\t%0, %1
5498
   mov%?\\t%0, %1
5499
   mvn%?\\t%0, #%B1
5500
   movw%?\\t%0, %1
5501
   ldr%?\\t%0, %1
5502
   str%?\\t%1, %0"
5503
  [(set_attr "type" "*,*,*,*,load1,store1")
5504
   (set_attr "insn" "mov,mov,mvn,mov,*,*")
5505
   (set_attr "predicable" "yes")
5506
   (set_attr "pool_range" "*,*,*,*,4096,*")
5507
   (set_attr "neg_pool_range" "*,*,*,*,4084,*")]
5508
)
5509
 
5510
(define_split
5511
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
5512
        (match_operand:SI 1 "const_int_operand" ""))]
5513
  "TARGET_32BIT
5514
  && (!(const_ok_for_arm (INTVAL (operands[1]))
5515
        || const_ok_for_arm (~INTVAL (operands[1]))))"
5516
  [(clobber (const_int 0))]
5517
  "
5518
  arm_split_constant (SET, SImode, NULL_RTX,
5519
                      INTVAL (operands[1]), operands[0], NULL_RTX, 0);
5520
  DONE;
5521
  "
5522
)
5523
 
5524
(define_insn "*thumb1_movsi_insn"
5525
  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
5526
        (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*l*h*k"))]
5527
  "TARGET_THUMB1
5528
   && (   register_operand (operands[0], SImode)
5529
       || register_operand (operands[1], SImode))"
5530
  "@
5531
   mov  %0, %1
5532
   mov  %0, %1
5533
   #
5534
   #
5535
   ldmia\\t%1, {%0}
5536
   stmia\\t%0, {%1}
5537
   ldr\\t%0, %1
5538
   str\\t%1, %0
5539
   mov\\t%0, %1"
5540
  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
5541
   (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
5542
   (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")
5543
   (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
5544
 
5545
(define_split
5546
  [(set (match_operand:SI 0 "register_operand" "")
5547
        (match_operand:SI 1 "const_int_operand" ""))]
5548
  "TARGET_THUMB1 && satisfies_constraint_J (operands[1])"
5549
  [(set (match_dup 2) (match_dup 1))
5550
   (set (match_dup 0) (neg:SI (match_dup 2)))]
5551
  "
5552
  {
5553
    operands[1] = GEN_INT (- INTVAL (operands[1]));
5554
    operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5555
  }"
5556
)
5557
 
5558
(define_split
5559
  [(set (match_operand:SI 0 "register_operand" "")
5560
        (match_operand:SI 1 "const_int_operand" ""))]
5561
  "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
5562
  [(set (match_dup 2) (match_dup 1))
5563
   (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
5564
  "
5565
  {
5566
    unsigned HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffffffffu;
5567
    unsigned HOST_WIDE_INT mask = 0xff;
5568
    int i;
5569
 
5570
    for (i = 0; i < 25; i++)
5571
      if ((val & (mask << i)) == val)
5572
        break;
5573
 
5574
    /* Don't split if the shift is zero.  */
5575
    if (i == 0)
5576
      FAIL;
5577
 
5578
    operands[1] = GEN_INT (val >> i);
5579
    operands[2] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
5580
    operands[3] = GEN_INT (i);
5581
  }"
5582
)
5583
 
5584
;; When generating pic, we need to load the symbol offset into a register.
5585
;; So that the optimizer does not confuse this with a normal symbol load
5586
;; we use an unspec.  The offset will be loaded from a constant pool entry,
5587
;; since that is the only type of relocation we can use.
5588
 
5589
;; Wrap calculation of the whole PIC address in a single pattern for the
5590
;; benefit of optimizers, particularly, PRE and HOIST.  Calculation of
5591
;; a PIC address involves two loads from memory, so we want to CSE it
5592
;; as often as possible.
5593
;; This pattern will be split into one of the pic_load_addr_* patterns
5594
;; and a move after GCSE optimizations.
5595
;;
5596
;; Note: Update arm.c: legitimize_pic_address() when changing this pattern.
5597
(define_expand "calculate_pic_address"
5598
  [(set (match_operand:SI 0 "register_operand" "")
5599
        (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5600
                         (unspec:SI [(match_operand:SI 2 "" "")]
5601
                                    UNSPEC_PIC_SYM))))]
5602
  "flag_pic"
5603
)
5604
 
5605
;; Split calculate_pic_address into pic_load_addr_* and a move.
5606
(define_split
5607
  [(set (match_operand:SI 0 "register_operand" "")
5608
        (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "")
5609
                         (unspec:SI [(match_operand:SI 2 "" "")]
5610
                                    UNSPEC_PIC_SYM))))]
5611
  "flag_pic"
5612
  [(set (match_dup 3) (unspec:SI [(match_dup 2)] UNSPEC_PIC_SYM))
5613
   (set (match_dup 0) (mem:SI (plus:SI (match_dup 1) (match_dup 3))))]
5614
  "operands[3] = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];"
5615
)
5616
 
5617
;; operand1 is the memory address to go into
5618
;; pic_load_addr_32bit.
5619
;; operand2 is the PIC label to be emitted
5620
;; from pic_add_dot_plus_eight.
5621
;; We do this to allow hoisting of the entire insn.
5622
(define_insn_and_split "pic_load_addr_unified"
5623
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,l")
5624
        (unspec:SI [(match_operand:SI 1 "" "mX,mX,mX")
5625
                    (match_operand:SI 2 "" "")]
5626
                    UNSPEC_PIC_UNIFIED))]
5627
 "flag_pic"
5628
 "#"
5629
 "&& reload_completed"
5630
 [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_PIC_SYM))
5631
  (set (match_dup 0) (unspec:SI [(match_dup 0) (match_dup 3)
5632
                                 (match_dup 2)] UNSPEC_PIC_BASE))]
5633
 "operands[3] = TARGET_THUMB ? GEN_INT (4) : GEN_INT (8);"
5634
 [(set_attr "type" "load1,load1,load1")
5635
  (set_attr "pool_range" "4096,4096,1024")
5636
  (set_attr "neg_pool_range" "4084,0,0")
5637
  (set_attr "arch"  "a,t2,t1")
5638
  (set_attr "length" "8,6,4")]
5639
)
5640
 
5641
;; The rather odd constraints on the following are to force reload to leave
5642
;; the insn alone, and to force the minipool generation pass to then move
5643
;; the GOT symbol to memory.
5644
 
5645
(define_insn "pic_load_addr_32bit"
5646
  [(set (match_operand:SI 0 "s_register_operand" "=r")
5647
        (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5648
  "TARGET_32BIT && flag_pic"
5649
  "ldr%?\\t%0, %1"
5650
  [(set_attr "type" "load1")
5651
   (set_attr "pool_range" "4096")
5652
   (set (attr "neg_pool_range")
5653
        (if_then_else (eq_attr "is_thumb" "no")
5654
                      (const_int 4084)
5655
                      (const_int 0)))]
5656
)
5657
 
5658
(define_insn "pic_load_addr_thumb1"
5659
  [(set (match_operand:SI 0 "s_register_operand" "=l")
5660
        (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
5661
  "TARGET_THUMB1 && flag_pic"
5662
  "ldr\\t%0, %1"
5663
  [(set_attr "type" "load1")
5664
   (set (attr "pool_range") (const_int 1024))]
5665
)
5666
 
5667
(define_insn "pic_add_dot_plus_four"
5668
  [(set (match_operand:SI 0 "register_operand" "=r")
5669
        (unspec:SI [(match_operand:SI 1 "register_operand" "0")
5670
                    (const_int 4)
5671
                    (match_operand 2 "" "")]
5672
                   UNSPEC_PIC_BASE))]
5673
  "TARGET_THUMB"
5674
  "*
5675
  (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5676
                                     INTVAL (operands[2]));
5677
  return \"add\\t%0, %|pc\";
5678
  "
5679
  [(set_attr "length" "2")]
5680
)
5681
 
5682
(define_insn "pic_add_dot_plus_eight"
5683
  [(set (match_operand:SI 0 "register_operand" "=r")
5684
        (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5685
                    (const_int 8)
5686
                    (match_operand 2 "" "")]
5687
                   UNSPEC_PIC_BASE))]
5688
  "TARGET_ARM"
5689
  "*
5690
    (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5691
                                       INTVAL (operands[2]));
5692
    return \"add%?\\t%0, %|pc, %1\";
5693
  "
5694
  [(set_attr "predicable" "yes")]
5695
)
5696
 
5697
(define_insn "tls_load_dot_plus_eight"
5698
  [(set (match_operand:SI 0 "register_operand" "=r")
5699
        (mem:SI (unspec:SI [(match_operand:SI 1 "register_operand" "r")
5700
                            (const_int 8)
5701
                            (match_operand 2 "" "")]
5702
                           UNSPEC_PIC_BASE)))]
5703
  "TARGET_ARM"
5704
  "*
5705
    (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
5706
                                       INTVAL (operands[2]));
5707
    return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
5708
  "
5709
  [(set_attr "predicable" "yes")]
5710
)
5711
 
5712
;; PIC references to local variables can generate pic_add_dot_plus_eight
5713
;; followed by a load.  These sequences can be crunched down to
5714
;; tls_load_dot_plus_eight by a peephole.
5715
 
5716
(define_peephole2
5717
  [(set (match_operand:SI 0 "register_operand" "")
5718
        (unspec:SI [(match_operand:SI 3 "register_operand" "")
5719
                    (const_int 8)
5720
                    (match_operand 1 "" "")]
5721
                   UNSPEC_PIC_BASE))
5722
   (set (match_operand:SI 2 "arm_general_register_operand" "")
5723
        (mem:SI (match_dup 0)))]
5724
  "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
5725
  [(set (match_dup 2)
5726
        (mem:SI (unspec:SI [(match_dup 3)
5727
                            (const_int 8)
5728
                            (match_dup 1)]
5729
                           UNSPEC_PIC_BASE)))]
5730
  ""
5731
)
5732
 
5733
(define_insn "pic_offset_arm"
5734
  [(set (match_operand:SI 0 "register_operand" "=r")
5735
        (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
5736
                         (unspec:SI [(match_operand:SI 2 "" "X")]
5737
                                    UNSPEC_PIC_OFFSET))))]
5738
  "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
5739
  "ldr%?\\t%0, [%1,%2]"
5740
  [(set_attr "type" "load1")]
5741
)
5742
 
5743
(define_expand "builtin_setjmp_receiver"
5744
  [(label_ref (match_operand 0 "" ""))]
5745
  "flag_pic"
5746
  "
5747
{
5748
  /* r3 is clobbered by set/longjmp, so we can use it as a scratch
5749
     register.  */
5750
  if (arm_pic_register != INVALID_REGNUM)
5751
    arm_load_pic_register (1UL << 3);
5752
  DONE;
5753
}")
5754
 
5755
;; If copying one reg to another we can set the condition codes according to
5756
;; its value.  Such a move is common after a return from subroutine and the
5757
;; result is being tested against zero.
5758
 
5759
(define_insn "*movsi_compare0"
5760
  [(set (reg:CC CC_REGNUM)
5761
        (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
5762
                    (const_int 0)))
5763
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
5764
        (match_dup 1))]
5765
  "TARGET_32BIT"
5766
  "@
5767
   cmp%?\\t%0, #0
5768
   sub%.\\t%0, %1, #0"
5769
  [(set_attr "conds" "set")]
5770
)
5771
 
5772
;; Subroutine to store a half word from a register into memory.
5773
;; Operand 0 is the source register (HImode)
5774
;; Operand 1 is the destination address in a register (SImode)
5775
 
5776
;; In both this routine and the next, we must be careful not to spill
5777
;; a memory address of reg+large_const into a separate PLUS insn, since this
5778
;; can generate unrecognizable rtl.
5779
 
5780
(define_expand "storehi"
5781
  [;; store the low byte
5782
   (set (match_operand 1 "" "") (match_dup 3))
5783
   ;; extract the high byte
5784
   (set (match_dup 2)
5785
        (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5786
   ;; store the high byte
5787
   (set (match_dup 4) (match_dup 5))]
5788
  "TARGET_ARM"
5789
  "
5790
  {
5791
    rtx op1 = operands[1];
5792
    rtx addr = XEXP (op1, 0);
5793
    enum rtx_code code = GET_CODE (addr);
5794
 
5795
    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5796
        || code == MINUS)
5797
      op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
5798
 
5799
    operands[4] = adjust_address (op1, QImode, 1);
5800
    operands[1] = adjust_address (operands[1], QImode, 0);
5801
    operands[3] = gen_lowpart (QImode, operands[0]);
5802
    operands[0] = gen_lowpart (SImode, operands[0]);
5803
    operands[2] = gen_reg_rtx (SImode);
5804
    operands[5] = gen_lowpart (QImode, operands[2]);
5805
  }"
5806
)
5807
 
5808
(define_expand "storehi_bigend"
5809
  [(set (match_dup 4) (match_dup 3))
5810
   (set (match_dup 2)
5811
        (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
5812
   (set (match_operand 1 "" "") (match_dup 5))]
5813
  "TARGET_ARM"
5814
  "
5815
  {
5816
    rtx op1 = operands[1];
5817
    rtx addr = XEXP (op1, 0);
5818
    enum rtx_code code = GET_CODE (addr);
5819
 
5820
    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5821
        || code == MINUS)
5822
      op1 = replace_equiv_address (op1, force_reg (SImode, addr));
5823
 
5824
    operands[4] = adjust_address (op1, QImode, 1);
5825
    operands[1] = adjust_address (operands[1], QImode, 0);
5826
    operands[3] = gen_lowpart (QImode, operands[0]);
5827
    operands[0] = gen_lowpart (SImode, operands[0]);
5828
    operands[2] = gen_reg_rtx (SImode);
5829
    operands[5] = gen_lowpart (QImode, operands[2]);
5830
  }"
5831
)
5832
 
5833
;; Subroutine to store a half word integer constant into memory.
5834
(define_expand "storeinthi"
5835
  [(set (match_operand 0 "" "")
5836
        (match_operand 1 "" ""))
5837
   (set (match_dup 3) (match_dup 2))]
5838
  "TARGET_ARM"
5839
  "
5840
  {
5841
    HOST_WIDE_INT value = INTVAL (operands[1]);
5842
    rtx addr = XEXP (operands[0], 0);
5843
    rtx op0 = operands[0];
5844
    enum rtx_code code = GET_CODE (addr);
5845
 
5846
    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
5847
        || code == MINUS)
5848
      op0 = replace_equiv_address (op0, force_reg (SImode, addr));
5849
 
5850
    operands[1] = gen_reg_rtx (SImode);
5851
    if (BYTES_BIG_ENDIAN)
5852
      {
5853
        emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
5854
        if ((value & 255) == ((value >> 8) & 255))
5855
          operands[2] = operands[1];
5856
        else
5857
          {
5858
            operands[2] = gen_reg_rtx (SImode);
5859
            emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
5860
          }
5861
      }
5862
    else
5863
      {
5864
        emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
5865
        if ((value & 255) == ((value >> 8) & 255))
5866
          operands[2] = operands[1];
5867
        else
5868
          {
5869
            operands[2] = gen_reg_rtx (SImode);
5870
            emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
5871
          }
5872
      }
5873
 
5874
    operands[3] = adjust_address (op0, QImode, 1);
5875
    operands[0] = adjust_address (operands[0], QImode, 0);
5876
    operands[2] = gen_lowpart (QImode, operands[2]);
5877
    operands[1] = gen_lowpart (QImode, operands[1]);
5878
  }"
5879
)
5880
 
5881
(define_expand "storehi_single_op"
5882
  [(set (match_operand:HI 0 "memory_operand" "")
5883
        (match_operand:HI 1 "general_operand" ""))]
5884
  "TARGET_32BIT && arm_arch4"
5885
  "
5886
  if (!s_register_operand (operands[1], HImode))
5887
    operands[1] = copy_to_mode_reg (HImode, operands[1]);
5888
  "
5889
)
5890
 
5891
(define_expand "movhi"
5892
  [(set (match_operand:HI 0 "general_operand" "")
5893
        (match_operand:HI 1 "general_operand" ""))]
5894
  "TARGET_EITHER"
5895
  "
5896
  if (TARGET_ARM)
5897
    {
5898
      if (can_create_pseudo_p ())
5899
        {
5900
          if (GET_CODE (operands[0]) == MEM)
5901
            {
5902
              if (arm_arch4)
5903
                {
5904
                  emit_insn (gen_storehi_single_op (operands[0], operands[1]));
5905
                  DONE;
5906
                }
5907
              if (GET_CODE (operands[1]) == CONST_INT)
5908
                emit_insn (gen_storeinthi (operands[0], operands[1]));
5909
              else
5910
                {
5911
                  if (GET_CODE (operands[1]) == MEM)
5912
                    operands[1] = force_reg (HImode, operands[1]);
5913
                  if (BYTES_BIG_ENDIAN)
5914
                    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
5915
                  else
5916
                   emit_insn (gen_storehi (operands[1], operands[0]));
5917
                }
5918
              DONE;
5919
            }
5920
          /* Sign extend a constant, and keep it in an SImode reg.  */
5921
          else if (GET_CODE (operands[1]) == CONST_INT)
5922
            {
5923
              rtx reg = gen_reg_rtx (SImode);
5924
              HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
5925
 
5926
              /* If the constant is already valid, leave it alone.  */
5927
              if (!const_ok_for_arm (val))
5928
                {
5929
                  /* If setting all the top bits will make the constant
5930
                     loadable in a single instruction, then set them.
5931
                     Otherwise, sign extend the number.  */
5932
 
5933
                  if (const_ok_for_arm (~(val | ~0xffff)))
5934
                    val |= ~0xffff;
5935
                  else if (val & 0x8000)
5936
                    val |= ~0xffff;
5937
                }
5938
 
5939
              emit_insn (gen_movsi (reg, GEN_INT (val)));
5940
              operands[1] = gen_lowpart (HImode, reg);
5941
            }
5942
          else if (arm_arch4 && optimize && can_create_pseudo_p ()
5943
                   && GET_CODE (operands[1]) == MEM)
5944
            {
5945
              rtx reg = gen_reg_rtx (SImode);
5946
 
5947
              emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
5948
              operands[1] = gen_lowpart (HImode, reg);
5949
            }
5950
          else if (!arm_arch4)
5951
            {
5952
              if (GET_CODE (operands[1]) == MEM)
5953
                {
5954
                  rtx base;
5955
                  rtx offset = const0_rtx;
5956
                  rtx reg = gen_reg_rtx (SImode);
5957
 
5958
                  if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
5959
                       || (GET_CODE (base) == PLUS
5960
                           && (GET_CODE (offset = XEXP (base, 1))
5961
                               == CONST_INT)
5962
                           && ((INTVAL(offset) & 1) != 1)
5963
                           && GET_CODE (base = XEXP (base, 0)) == REG))
5964
                      && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
5965
                    {
5966
                      rtx new_rtx;
5967
 
5968
                      new_rtx = widen_memory_access (operands[1], SImode,
5969
                                                     ((INTVAL (offset) & ~3)
5970
                                                      - INTVAL (offset)));
5971
                      emit_insn (gen_movsi (reg, new_rtx));
5972
                      if (((INTVAL (offset) & 2) != 0)
5973
                          ^ (BYTES_BIG_ENDIAN ? 1 : 0))
5974
                        {
5975
                          rtx reg2 = gen_reg_rtx (SImode);
5976
 
5977
                          emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
5978
                          reg = reg2;
5979
                        }
5980
                    }
5981
                  else
5982
                    emit_insn (gen_movhi_bytes (reg, operands[1]));
5983
 
5984
                  operands[1] = gen_lowpart (HImode, reg);
5985
               }
5986
           }
5987
        }
5988
      /* Handle loading a large integer during reload.  */
5989
      else if (GET_CODE (operands[1]) == CONST_INT
5990
               && !const_ok_for_arm (INTVAL (operands[1]))
5991
               && !const_ok_for_arm (~INTVAL (operands[1])))
5992
        {
5993
          /* Writing a constant to memory needs a scratch, which should
5994
             be handled with SECONDARY_RELOADs.  */
5995
          gcc_assert (GET_CODE (operands[0]) == REG);
5996
 
5997
          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5998
          emit_insn (gen_movsi (operands[0], operands[1]));
5999
          DONE;
6000
       }
6001
    }
6002
  else if (TARGET_THUMB2)
6003
    {
6004
      /* Thumb-2 can do everything except mem=mem and mem=const easily.  */
6005
      if (can_create_pseudo_p ())
6006
        {
6007
          if (GET_CODE (operands[0]) != REG)
6008
            operands[1] = force_reg (HImode, operands[1]);
6009
          /* Zero extend a constant, and keep it in an SImode reg.  */
6010
          else if (GET_CODE (operands[1]) == CONST_INT)
6011
            {
6012
              rtx reg = gen_reg_rtx (SImode);
6013
              HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
6014
 
6015
              emit_insn (gen_movsi (reg, GEN_INT (val)));
6016
              operands[1] = gen_lowpart (HImode, reg);
6017
            }
6018
        }
6019
    }
6020
  else /* TARGET_THUMB1 */
6021
    {
6022
      if (can_create_pseudo_p ())
6023
        {
6024
          if (GET_CODE (operands[1]) == CONST_INT)
6025
            {
6026
              rtx reg = gen_reg_rtx (SImode);
6027
 
6028
              emit_insn (gen_movsi (reg, operands[1]));
6029
              operands[1] = gen_lowpart (HImode, reg);
6030
            }
6031
 
6032
          /* ??? We shouldn't really get invalid addresses here, but this can
6033
             happen if we are passed a SP (never OK for HImode/QImode) or
6034
             virtual register (also rejected as illegitimate for HImode/QImode)
6035
             relative address.  */
6036
          /* ??? This should perhaps be fixed elsewhere, for instance, in
6037
             fixup_stack_1, by checking for other kinds of invalid addresses,
6038
             e.g. a bare reference to a virtual register.  This may confuse the
6039
             alpha though, which must handle this case differently.  */
6040
          if (GET_CODE (operands[0]) == MEM
6041
              && !memory_address_p (GET_MODE (operands[0]),
6042
                                    XEXP (operands[0], 0)))
6043
            operands[0]
6044
              = replace_equiv_address (operands[0],
6045
                                       copy_to_reg (XEXP (operands[0], 0)));
6046
 
6047
          if (GET_CODE (operands[1]) == MEM
6048
              && !memory_address_p (GET_MODE (operands[1]),
6049
                                    XEXP (operands[1], 0)))
6050
            operands[1]
6051
              = replace_equiv_address (operands[1],
6052
                                       copy_to_reg (XEXP (operands[1], 0)));
6053
 
6054
          if (GET_CODE (operands[1]) == MEM && optimize > 0)
6055
            {
6056
              rtx reg = gen_reg_rtx (SImode);
6057
 
6058
              emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
6059
              operands[1] = gen_lowpart (HImode, reg);
6060
            }
6061
 
6062
          if (GET_CODE (operands[0]) == MEM)
6063
            operands[1] = force_reg (HImode, operands[1]);
6064
        }
6065
      else if (GET_CODE (operands[1]) == CONST_INT
6066
                && !satisfies_constraint_I (operands[1]))
6067
        {
6068
          /* Handle loading a large integer during reload.  */
6069
 
6070
          /* Writing a constant to memory needs a scratch, which should
6071
             be handled with SECONDARY_RELOADs.  */
6072
          gcc_assert (GET_CODE (operands[0]) == REG);
6073
 
6074
          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6075
          emit_insn (gen_movsi (operands[0], operands[1]));
6076
          DONE;
6077
        }
6078
    }
6079
  "
6080
)
6081
 
6082
(define_insn "*thumb1_movhi_insn"
6083
  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6084
        (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
6085
  "TARGET_THUMB1
6086
   && (   register_operand (operands[0], HImode)
6087
       || register_operand (operands[1], HImode))"
6088
  "*
6089
  switch (which_alternative)
6090
    {
6091
    case 0: return \"add        %0, %1, #0\";
6092
    case 2: return \"strh       %1, %0\";
6093
    case 3: return \"mov        %0, %1\";
6094
    case 4: return \"mov        %0, %1\";
6095
    case 5: return \"mov        %0, %1\";
6096
    default: gcc_unreachable ();
6097
    case 1:
6098
      /* The stack pointer can end up being taken as an index register.
6099
          Catch this case here and deal with it.  */
6100
      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
6101
          && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
6102
          && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
6103
        {
6104
          rtx ops[2];
6105
          ops[0] = operands[0];
6106
          ops[1] = XEXP (XEXP (operands[1], 0), 0);
6107
 
6108
          output_asm_insn (\"mov        %0, %1\", ops);
6109
 
6110
          XEXP (XEXP (operands[1], 0), 0) = operands[0];
6111
 
6112
        }
6113
      return \"ldrh     %0, %1\";
6114
    }"
6115
  [(set_attr "length" "2,4,2,2,2,2")
6116
   (set_attr "type" "*,load1,store1,*,*,*")
6117
   (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
6118
 
6119
 
6120
(define_expand "movhi_bytes"
6121
  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
6122
   (set (match_dup 3)
6123
        (zero_extend:SI (match_dup 6)))
6124
   (set (match_operand:SI 0 "" "")
6125
         (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
6126
  "TARGET_ARM"
6127
  "
6128
  {
6129
    rtx mem1, mem2;
6130
    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
6131
 
6132
    mem1 = change_address (operands[1], QImode, addr);
6133
    mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
6134
    operands[0] = gen_lowpart (SImode, operands[0]);
6135
    operands[1] = mem1;
6136
    operands[2] = gen_reg_rtx (SImode);
6137
    operands[3] = gen_reg_rtx (SImode);
6138
    operands[6] = mem2;
6139
 
6140
    if (BYTES_BIG_ENDIAN)
6141
      {
6142
        operands[4] = operands[2];
6143
        operands[5] = operands[3];
6144
      }
6145
    else
6146
      {
6147
        operands[4] = operands[3];
6148
        operands[5] = operands[2];
6149
      }
6150
  }"
6151
)
6152
 
6153
(define_expand "movhi_bigend"
6154
  [(set (match_dup 2)
6155
        (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
6156
                   (const_int 16)))
6157
   (set (match_dup 3)
6158
        (ashiftrt:SI (match_dup 2) (const_int 16)))
6159
   (set (match_operand:HI 0 "s_register_operand" "")
6160
        (match_dup 4))]
6161
  "TARGET_ARM"
6162
  "
6163
  operands[2] = gen_reg_rtx (SImode);
6164
  operands[3] = gen_reg_rtx (SImode);
6165
  operands[4] = gen_lowpart (HImode, operands[3]);
6166
  "
6167
)
6168
 
6169
;; Pattern to recognize insn generated default case above
6170
(define_insn "*movhi_insn_arch4"
6171
  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
6172
        (match_operand:HI 1 "general_operand"      "rI,K,r,mi"))]
6173
  "TARGET_ARM
6174
   && arm_arch4
6175
   && (register_operand (operands[0], HImode)
6176
       || register_operand (operands[1], HImode))"
6177
  "@
6178
   mov%?\\t%0, %1\\t%@ movhi
6179
   mvn%?\\t%0, #%B1\\t%@ movhi
6180
   str%(h%)\\t%1, %0\\t%@ movhi
6181
   ldr%(h%)\\t%0, %1\\t%@ movhi"
6182
  [(set_attr "type" "*,*,store1,load1")
6183
   (set_attr "predicable" "yes")
6184
   (set_attr "insn" "mov,mvn,*,*")
6185
   (set_attr "pool_range" "*,*,*,256")
6186
   (set_attr "neg_pool_range" "*,*,*,244")]
6187
)
6188
 
6189
(define_insn "*movhi_bytes"
6190
  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
6191
        (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
6192
  "TARGET_ARM"
6193
  "@
6194
   mov%?\\t%0, %1\\t%@ movhi
6195
   mvn%?\\t%0, #%B1\\t%@ movhi"
6196
  [(set_attr "predicable" "yes")
6197
   (set_attr "insn" "mov,mvn")]
6198
)
6199
 
6200
(define_expand "thumb_movhi_clobber"
6201
  [(set (match_operand:HI     0 "memory_operand"   "")
6202
        (match_operand:HI     1 "register_operand" ""))
6203
   (clobber (match_operand:DI 2 "register_operand" ""))]
6204
  "TARGET_THUMB1"
6205
  "
6206
  if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
6207
      && REGNO (operands[1]) <= LAST_LO_REGNUM)
6208
    {
6209
      emit_insn (gen_movhi (operands[0], operands[1]));
6210
      DONE;
6211
    }
6212
  /* XXX Fixme, need to handle other cases here as well.  */
6213
  gcc_unreachable ();
6214
  "
6215
)
6216
 
6217
;; We use a DImode scratch because we may occasionally need an additional
6218
;; temporary if the address isn't offsettable -- push_reload doesn't seem
6219
;; to take any notice of the "o" constraints on reload_memory_operand operand.
6220
(define_expand "reload_outhi"
6221
  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
6222
              (match_operand:HI 1 "s_register_operand"        "r")
6223
              (match_operand:DI 2 "s_register_operand"        "=&l")])]
6224
  "TARGET_EITHER"
6225
  "if (TARGET_ARM)
6226
     arm_reload_out_hi (operands);
6227
   else
6228
     thumb_reload_out_hi (operands);
6229
  DONE;
6230
  "
6231
)
6232
 
6233
(define_expand "reload_inhi"
6234
  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
6235
              (match_operand:HI 1 "arm_reload_memory_operand" "o")
6236
              (match_operand:DI 2 "s_register_operand" "=&r")])]
6237
  "TARGET_EITHER"
6238
  "
6239
  if (TARGET_ARM)
6240
    arm_reload_in_hi (operands);
6241
  else
6242
    thumb_reload_out_hi (operands);
6243
  DONE;
6244
")
6245
 
6246
(define_expand "movqi"
6247
  [(set (match_operand:QI 0 "general_operand" "")
6248
        (match_operand:QI 1 "general_operand" ""))]
6249
  "TARGET_EITHER"
6250
  "
6251
  /* Everything except mem = const or mem = mem can be done easily */
6252
 
6253
  if (can_create_pseudo_p ())
6254
    {
6255
      if (GET_CODE (operands[1]) == CONST_INT)
6256
        {
6257
          rtx reg = gen_reg_rtx (SImode);
6258
 
6259
          /* For thumb we want an unsigned immediate, then we are more likely
6260
             to be able to use a movs insn.  */
6261
          if (TARGET_THUMB)
6262
            operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
6263
 
6264
          emit_insn (gen_movsi (reg, operands[1]));
6265
          operands[1] = gen_lowpart (QImode, reg);
6266
        }
6267
 
6268
      if (TARGET_THUMB)
6269
        {
6270
          /* ??? We shouldn't really get invalid addresses here, but this can
6271
             happen if we are passed a SP (never OK for HImode/QImode) or
6272
             virtual register (also rejected as illegitimate for HImode/QImode)
6273
             relative address.  */
6274
          /* ??? This should perhaps be fixed elsewhere, for instance, in
6275
             fixup_stack_1, by checking for other kinds of invalid addresses,
6276
             e.g. a bare reference to a virtual register.  This may confuse the
6277
             alpha though, which must handle this case differently.  */
6278
          if (GET_CODE (operands[0]) == MEM
6279
              && !memory_address_p (GET_MODE (operands[0]),
6280
                                     XEXP (operands[0], 0)))
6281
            operands[0]
6282
              = replace_equiv_address (operands[0],
6283
                                       copy_to_reg (XEXP (operands[0], 0)));
6284
          if (GET_CODE (operands[1]) == MEM
6285
              && !memory_address_p (GET_MODE (operands[1]),
6286
                                    XEXP (operands[1], 0)))
6287
             operands[1]
6288
               = replace_equiv_address (operands[1],
6289
                                        copy_to_reg (XEXP (operands[1], 0)));
6290
        }
6291
 
6292
      if (GET_CODE (operands[1]) == MEM && optimize > 0)
6293
        {
6294
          rtx reg = gen_reg_rtx (SImode);
6295
 
6296
          emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
6297
          operands[1] = gen_lowpart (QImode, reg);
6298
        }
6299
 
6300
      if (GET_CODE (operands[0]) == MEM)
6301
        operands[1] = force_reg (QImode, operands[1]);
6302
    }
6303
  else if (TARGET_THUMB
6304
           && GET_CODE (operands[1]) == CONST_INT
6305
           && !satisfies_constraint_I (operands[1]))
6306
    {
6307
      /* Handle loading a large integer during reload.  */
6308
 
6309
      /* Writing a constant to memory needs a scratch, which should
6310
         be handled with SECONDARY_RELOADs.  */
6311
      gcc_assert (GET_CODE (operands[0]) == REG);
6312
 
6313
      operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
6314
      emit_insn (gen_movsi (operands[0], operands[1]));
6315
      DONE;
6316
    }
6317
  "
6318
)
6319
 
6320
 
6321
(define_insn "*arm_movqi_insn"
6322
  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,l,Uu,r,m")
6323
        (match_operand:QI 1 "general_operand" "rI,K,Uu,l,m,r"))]
6324
  "TARGET_32BIT
6325
   && (   register_operand (operands[0], QImode)
6326
       || register_operand (operands[1], QImode))"
6327
  "@
6328
   mov%?\\t%0, %1
6329
   mvn%?\\t%0, #%B1
6330
   ldr%(b%)\\t%0, %1
6331
   str%(b%)\\t%1, %0
6332
   ldr%(b%)\\t%0, %1
6333
   str%(b%)\\t%1, %0"
6334
  [(set_attr "type" "*,*,load1,store1,load1,store1")
6335
   (set_attr "insn" "mov,mvn,*,*,*,*")
6336
   (set_attr "predicable" "yes")
6337
   (set_attr "arch" "any,any,t2,t2,any,any")
6338
   (set_attr "length" "4,4,2,2,4,4")]
6339
)
6340
 
6341
(define_insn "*thumb1_movqi_insn"
6342
  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
6343
        (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
6344
  "TARGET_THUMB1
6345
   && (   register_operand (operands[0], QImode)
6346
       || register_operand (operands[1], QImode))"
6347
  "@
6348
   add\\t%0, %1, #0
6349
   ldrb\\t%0, %1
6350
   strb\\t%1, %0
6351
   mov\\t%0, %1
6352
   mov\\t%0, %1
6353
   mov\\t%0, %1"
6354
  [(set_attr "length" "2")
6355
   (set_attr "type" "*,load1,store1,*,*,*")
6356
   (set_attr "insn" "*,*,*,mov,mov,mov")
6357
   (set_attr "pool_range" "*,32,*,*,*,*")
6358
   (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
6359
 
6360
;; HFmode moves
6361
(define_expand "movhf"
6362
  [(set (match_operand:HF 0 "general_operand" "")
6363
        (match_operand:HF 1 "general_operand" ""))]
6364
  "TARGET_EITHER"
6365
  "
6366
  if (TARGET_32BIT)
6367
    {
6368
      if (GET_CODE (operands[0]) == MEM)
6369
        operands[1] = force_reg (HFmode, operands[1]);
6370
    }
6371
  else /* TARGET_THUMB1 */
6372
    {
6373
      if (can_create_pseudo_p ())
6374
        {
6375
           if (GET_CODE (operands[0]) != REG)
6376
             operands[1] = force_reg (HFmode, operands[1]);
6377
        }
6378
    }
6379
  "
6380
)
6381
 
6382
(define_insn "*arm32_movhf"
6383
  [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
6384
        (match_operand:HF 1 "general_operand"      " m,r,r,F"))]
6385
  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
6386
   && (   s_register_operand (operands[0], HFmode)
6387
       || s_register_operand (operands[1], HFmode))"
6388
  "*
6389
  switch (which_alternative)
6390
    {
6391
    case 0:     /* ARM register from memory */
6392
      return \"ldr%(h%)\\t%0, %1\\t%@ __fp16\";
6393
    case 1:     /* memory from ARM register */
6394
      return \"str%(h%)\\t%1, %0\\t%@ __fp16\";
6395
    case 2:     /* ARM register from ARM register */
6396
      return \"mov%?\\t%0, %1\\t%@ __fp16\";
6397
    case 3:     /* ARM register from constant */
6398
      {
6399
        REAL_VALUE_TYPE r;
6400
        long bits;
6401
        rtx ops[4];
6402
 
6403
        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
6404
        bits = real_to_target (NULL, &r, HFmode);
6405
        ops[0] = operands[0];
6406
        ops[1] = GEN_INT (bits);
6407
        ops[2] = GEN_INT (bits & 0xff00);
6408
        ops[3] = GEN_INT (bits & 0x00ff);
6409
 
6410
        if (arm_arch_thumb2)
6411
          output_asm_insn (\"movw%?\\t%0, %1\", ops);
6412
        else
6413
          output_asm_insn (\"mov%?\\t%0, %2\;orr%?\\t%0, %0, %3\", ops);
6414
        return \"\";
6415
       }
6416
    default:
6417
      gcc_unreachable ();
6418
    }
6419
  "
6420
  [(set_attr "conds" "unconditional")
6421
   (set_attr "type" "load1,store1,*,*")
6422
   (set_attr "insn" "*,*,mov,mov")
6423
   (set_attr "length" "4,4,4,8")
6424
   (set_attr "predicable" "yes")]
6425
)
6426
 
6427
(define_insn "*thumb1_movhf"
6428
  [(set (match_operand:HF     0 "nonimmediate_operand" "=l,l,m,*r,*h")
6429
        (match_operand:HF     1 "general_operand"      "l,mF,l,*h,*r"))]
6430
  "TARGET_THUMB1
6431
   && (   s_register_operand (operands[0], HFmode)
6432
       || s_register_operand (operands[1], HFmode))"
6433
  "*
6434
  switch (which_alternative)
6435
    {
6436
    case 1:
6437
      {
6438
        rtx addr;
6439
        gcc_assert (GET_CODE(operands[1]) == MEM);
6440
        addr = XEXP (operands[1], 0);
6441
        if (GET_CODE (addr) == LABEL_REF
6442
            || (GET_CODE (addr) == CONST
6443
                && GET_CODE (XEXP (addr, 0)) == PLUS
6444
                && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF
6445
                && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT))
6446
          {
6447
            /* Constant pool entry.  */
6448
            return \"ldr\\t%0, %1\";
6449
          }
6450
        return \"ldrh\\t%0, %1\";
6451
      }
6452
    case 2: return \"strh\\t%1, %0\";
6453
    default: return \"mov\\t%0, %1\";
6454
    }
6455
  "
6456
  [(set_attr "length" "2")
6457
   (set_attr "type" "*,load1,store1,*,*")
6458
   (set_attr "insn" "mov,*,*,mov,mov")
6459
   (set_attr "pool_range" "*,1020,*,*,*")
6460
   (set_attr "conds" "clob,nocond,nocond,nocond,nocond")])
6461
 
6462
(define_expand "movsf"
6463
  [(set (match_operand:SF 0 "general_operand" "")
6464
        (match_operand:SF 1 "general_operand" ""))]
6465
  "TARGET_EITHER"
6466
  "
6467
  if (TARGET_32BIT)
6468
    {
6469
      if (GET_CODE (operands[0]) == MEM)
6470
        operands[1] = force_reg (SFmode, operands[1]);
6471
    }
6472
  else /* TARGET_THUMB1 */
6473
    {
6474
      if (can_create_pseudo_p ())
6475
        {
6476
           if (GET_CODE (operands[0]) != REG)
6477
             operands[1] = force_reg (SFmode, operands[1]);
6478
        }
6479
    }
6480
  "
6481
)
6482
 
6483
;; Transform a floating-point move of a constant into a core register into
6484
;; an SImode operation.
6485
(define_split
6486
  [(set (match_operand:SF 0 "arm_general_register_operand" "")
6487
        (match_operand:SF 1 "immediate_operand" ""))]
6488
  "TARGET_EITHER
6489
   && reload_completed
6490
   && GET_CODE (operands[1]) == CONST_DOUBLE"
6491
  [(set (match_dup 2) (match_dup 3))]
6492
  "
6493
  operands[2] = gen_lowpart (SImode, operands[0]);
6494
  operands[3] = gen_lowpart (SImode, operands[1]);
6495
  if (operands[2] == 0 || operands[3] == 0)
6496
    FAIL;
6497
  "
6498
)
6499
 
6500
(define_insn "*arm_movsf_soft_insn"
6501
  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
6502
        (match_operand:SF 1 "general_operand"  "r,mE,r"))]
6503
  "TARGET_32BIT
6504
   && TARGET_SOFT_FLOAT
6505
   && (GET_CODE (operands[0]) != MEM
6506
       || register_operand (operands[1], SFmode))"
6507
  "@
6508
   mov%?\\t%0, %1
6509
   ldr%?\\t%0, %1\\t%@ float
6510
   str%?\\t%1, %0\\t%@ float"
6511
  [(set_attr "predicable" "yes")
6512
   (set_attr "type" "*,load1,store1")
6513
   (set_attr "insn" "mov,*,*")
6514
   (set_attr "pool_range" "*,4096,*")
6515
   (set_attr "arm_neg_pool_range" "*,4084,*")
6516
   (set_attr "thumb2_neg_pool_range" "*,0,*")]
6517
)
6518
 
6519
;;; ??? This should have alternatives for constants.
6520
(define_insn "*thumb1_movsf_insn"
6521
  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
6522
        (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
6523
  "TARGET_THUMB1
6524
   && (   register_operand (operands[0], SFmode)
6525
       || register_operand (operands[1], SFmode))"
6526
  "@
6527
   add\\t%0, %1, #0
6528
   ldmia\\t%1, {%0}
6529
   stmia\\t%0, {%1}
6530
   ldr\\t%0, %1
6531
   str\\t%1, %0
6532
   mov\\t%0, %1
6533
   mov\\t%0, %1"
6534
  [(set_attr "length" "2")
6535
   (set_attr "type" "*,load1,store1,load1,store1,*,*")
6536
   (set_attr "pool_range" "*,*,*,1020,*,*,*")
6537
   (set_attr "insn" "*,*,*,*,*,mov,mov")
6538
   (set_attr "conds" "clob,nocond,nocond,nocond,nocond,nocond,nocond")]
6539
)
6540
 
6541
(define_expand "movdf"
6542
  [(set (match_operand:DF 0 "general_operand" "")
6543
        (match_operand:DF 1 "general_operand" ""))]
6544
  "TARGET_EITHER"
6545
  "
6546
  if (TARGET_32BIT)
6547
    {
6548
      if (GET_CODE (operands[0]) == MEM)
6549
        operands[1] = force_reg (DFmode, operands[1]);
6550
    }
6551
  else /* TARGET_THUMB */
6552
    {
6553
      if (can_create_pseudo_p ())
6554
        {
6555
          if (GET_CODE (operands[0]) != REG)
6556
            operands[1] = force_reg (DFmode, operands[1]);
6557
        }
6558
    }
6559
  "
6560
)
6561
 
6562
;; Reloading a df mode value stored in integer regs to memory can require a
6563
;; scratch reg.
6564
(define_expand "reload_outdf"
6565
  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
6566
   (match_operand:DF 1 "s_register_operand" "r")
6567
   (match_operand:SI 2 "s_register_operand" "=&r")]
6568
  "TARGET_THUMB2"
6569
  "
6570
  {
6571
    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
6572
 
6573
    if (code == REG)
6574
      operands[2] = XEXP (operands[0], 0);
6575
    else if (code == POST_INC || code == PRE_DEC)
6576
      {
6577
        operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
6578
        operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
6579
        emit_insn (gen_movdi (operands[0], operands[1]));
6580
        DONE;
6581
      }
6582
    else if (code == PRE_INC)
6583
      {
6584
        rtx reg = XEXP (XEXP (operands[0], 0), 0);
6585
 
6586
        emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
6587
        operands[2] = reg;
6588
      }
6589
    else if (code == POST_DEC)
6590
      operands[2] = XEXP (XEXP (operands[0], 0), 0);
6591
    else
6592
      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
6593
                             XEXP (XEXP (operands[0], 0), 1)));
6594
 
6595
    emit_insn (gen_rtx_SET (VOIDmode,
6596
                            replace_equiv_address (operands[0], operands[2]),
6597
                            operands[1]));
6598
 
6599
    if (code == POST_DEC)
6600
      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
6601
 
6602
    DONE;
6603
  }"
6604
)
6605
 
6606
(define_insn "*movdf_soft_insn"
6607
  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
6608
        (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
6609
  "TARGET_32BIT && TARGET_SOFT_FLOAT
6610
   && (   register_operand (operands[0], DFmode)
6611
       || register_operand (operands[1], DFmode))"
6612
  "*
6613
  switch (which_alternative)
6614
    {
6615
    case 0:
6616
    case 1:
6617
    case 2:
6618
      return \"#\";
6619
    default:
6620
      return output_move_double (operands, true, NULL);
6621
    }
6622
  "
6623
  [(set_attr "length" "8,12,16,8,8")
6624
   (set_attr "type" "*,*,*,load2,store2")
6625
   (set_attr "pool_range" "*,*,*,1020,*")
6626
   (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
6627
   (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
6628
)
6629
 
6630
;;; ??? This should have alternatives for constants.
6631
;;; ??? This was originally identical to the movdi_insn pattern.
6632
;;; ??? The 'F' constraint looks funny, but it should always be replaced by
6633
;;; thumb_reorg with a memory reference.
6634
(define_insn "*thumb_movdf_insn"
6635
  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
6636
        (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
6637
  "TARGET_THUMB1
6638
   && (   register_operand (operands[0], DFmode)
6639
       || register_operand (operands[1], DFmode))"
6640
  "*
6641
  switch (which_alternative)
6642
    {
6643
    default:
6644
    case 0:
6645
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6646
        return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
6647
      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
6648
    case 1:
6649
      return \"ldmia\\t%1, {%0, %H0}\";
6650
    case 2:
6651
      return \"stmia\\t%0, {%1, %H1}\";
6652
    case 3:
6653
      return thumb_load_double_from_address (operands);
6654
    case 4:
6655
      operands[2] = gen_rtx_MEM (SImode,
6656
                                 plus_constant (XEXP (operands[0], 0), 4));
6657
      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
6658
      return \"\";
6659
    case 5:
6660
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
6661
        return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
6662
      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
6663
    }
6664
  "
6665
  [(set_attr "length" "4,2,2,6,4,4")
6666
   (set_attr "type" "*,load2,store2,load2,store2,*")
6667
   (set_attr "insn" "*,*,*,*,*,mov")
6668
   (set_attr "pool_range" "*,*,*,1020,*,*")]
6669
)
6670
 
6671
(define_expand "movxf"
6672
  [(set (match_operand:XF 0 "general_operand" "")
6673
        (match_operand:XF 1 "general_operand" ""))]
6674
  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
6675
  "
6676
  if (GET_CODE (operands[0]) == MEM)
6677
    operands[1] = force_reg (XFmode, operands[1]);
6678
  "
6679
)
6680
 
6681
 
6682
 
6683
;; load- and store-multiple insns
6684
;; The arm can load/store any set of registers, provided that they are in
6685
;; ascending order, but these expanders assume a contiguous set.
6686
 
6687
(define_expand "load_multiple"
6688
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6689
                          (match_operand:SI 1 "" ""))
6690
                     (use (match_operand:SI 2 "" ""))])]
6691
  "TARGET_32BIT"
6692
{
6693
  HOST_WIDE_INT offset = 0;
6694
 
6695
  /* Support only fixed point registers.  */
6696
  if (GET_CODE (operands[2]) != CONST_INT
6697
      || INTVAL (operands[2]) > 14
6698
      || INTVAL (operands[2]) < 2
6699
      || GET_CODE (operands[1]) != MEM
6700
      || GET_CODE (operands[0]) != REG
6701
      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
6702
      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6703
    FAIL;
6704
 
6705
  operands[3]
6706
    = arm_gen_load_multiple (arm_regs_in_sequence + REGNO (operands[0]),
6707
                             INTVAL (operands[2]),
6708
                             force_reg (SImode, XEXP (operands[1], 0)),
6709
                             FALSE, operands[1], &offset);
6710
})
6711
 
6712
(define_expand "store_multiple"
6713
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
6714
                          (match_operand:SI 1 "" ""))
6715
                     (use (match_operand:SI 2 "" ""))])]
6716
  "TARGET_32BIT"
6717
{
6718
  HOST_WIDE_INT offset = 0;
6719
 
6720
  /* Support only fixed point registers.  */
6721
  if (GET_CODE (operands[2]) != CONST_INT
6722
      || INTVAL (operands[2]) > 14
6723
      || INTVAL (operands[2]) < 2
6724
      || GET_CODE (operands[1]) != REG
6725
      || GET_CODE (operands[0]) != MEM
6726
      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
6727
      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
6728
    FAIL;
6729
 
6730
  operands[3]
6731
    = arm_gen_store_multiple (arm_regs_in_sequence + REGNO (operands[1]),
6732
                              INTVAL (operands[2]),
6733
                              force_reg (SImode, XEXP (operands[0], 0)),
6734
                              FALSE, operands[0], &offset);
6735
})
6736
 
6737
 
6738
;; Move a block of memory if it is word aligned and MORE than 2 words long.
6739
;; We could let this apply for blocks of less than this, but it clobbers so
6740
;; many registers that there is then probably a better way.
6741
 
6742
(define_expand "movmemqi"
6743
  [(match_operand:BLK 0 "general_operand" "")
6744
   (match_operand:BLK 1 "general_operand" "")
6745
   (match_operand:SI 2 "const_int_operand" "")
6746
   (match_operand:SI 3 "const_int_operand" "")]
6747
  "TARGET_EITHER"
6748
  "
6749
  if (TARGET_32BIT)
6750
    {
6751
      if (arm_gen_movmemqi (operands))
6752
        DONE;
6753
      FAIL;
6754
    }
6755
  else /* TARGET_THUMB1 */
6756
    {
6757
      if (   INTVAL (operands[3]) != 4
6758
          || INTVAL (operands[2]) > 48)
6759
        FAIL;
6760
 
6761
      thumb_expand_movmemqi (operands);
6762
      DONE;
6763
    }
6764
  "
6765
)
6766
 
6767
;; Thumb block-move insns
6768
 
6769
(define_insn "movmem12b"
6770
  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6771
        (mem:SI (match_operand:SI 3 "register_operand" "1")))
6772
   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6773
        (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6774
   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
6775
        (mem:SI (plus:SI (match_dup 3) (const_int 8))))
6776
   (set (match_operand:SI 0 "register_operand" "=l")
6777
        (plus:SI (match_dup 2) (const_int 12)))
6778
   (set (match_operand:SI 1 "register_operand" "=l")
6779
        (plus:SI (match_dup 3) (const_int 12)))
6780
   (clobber (match_scratch:SI 4 "=&l"))
6781
   (clobber (match_scratch:SI 5 "=&l"))
6782
   (clobber (match_scratch:SI 6 "=&l"))]
6783
  "TARGET_THUMB1"
6784
  "* return thumb_output_move_mem_multiple (3, operands);"
6785
  [(set_attr "length" "4")
6786
   ; This isn't entirely accurate...  It loads as well, but in terms of
6787
   ; scheduling the following insn it is better to consider it as a store
6788
   (set_attr "type" "store3")]
6789
)
6790
 
6791
(define_insn "movmem8b"
6792
  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
6793
        (mem:SI (match_operand:SI 3 "register_operand" "1")))
6794
   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
6795
        (mem:SI (plus:SI (match_dup 3) (const_int 4))))
6796
   (set (match_operand:SI 0 "register_operand" "=l")
6797
        (plus:SI (match_dup 2) (const_int 8)))
6798
   (set (match_operand:SI 1 "register_operand" "=l")
6799
        (plus:SI (match_dup 3) (const_int 8)))
6800
   (clobber (match_scratch:SI 4 "=&l"))
6801
   (clobber (match_scratch:SI 5 "=&l"))]
6802
  "TARGET_THUMB1"
6803
  "* return thumb_output_move_mem_multiple (2, operands);"
6804
  [(set_attr "length" "4")
6805
   ; This isn't entirely accurate...  It loads as well, but in terms of
6806
   ; scheduling the following insn it is better to consider it as a store
6807
   (set_attr "type" "store2")]
6808
)
6809
 
6810
 
6811
 
6812
;; Compare & branch insns
6813
;; The range calculations are based as follows:
6814
;; For forward branches, the address calculation returns the address of
6815
;; the next instruction.  This is 2 beyond the branch instruction.
6816
;; For backward branches, the address calculation returns the address of
6817
;; the first instruction in this pattern (cmp).  This is 2 before the branch
6818
;; instruction for the shortest sequence, and 4 before the branch instruction
6819
;; if we have to jump around an unconditional branch.
6820
;; To the basic branch range the PC offset must be added (this is +4).
6821
;; So for forward branches we have
6822
;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
6823
;; And for backward branches we have
6824
;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
6825
;;
6826
;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
6827
;; For a 'b' pos_range = 254,  neg_range = -256  giving (-250 ->256).
6828
 
6829
(define_expand "cbranchsi4"
6830
  [(set (pc) (if_then_else
6831
              (match_operator 0 "expandable_comparison_operator"
6832
               [(match_operand:SI 1 "s_register_operand" "")
6833
                (match_operand:SI 2 "nonmemory_operand" "")])
6834
              (label_ref (match_operand 3 "" ""))
6835
              (pc)))]
6836
  "TARGET_THUMB1 || TARGET_32BIT"
6837
  "
6838
  if (!TARGET_THUMB1)
6839
    {
6840
      if (!arm_add_operand (operands[2], SImode))
6841
        operands[2] = force_reg (SImode, operands[2]);
6842
      emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6843
                                      operands[3]));
6844
      DONE;
6845
    }
6846
  if (thumb1_cmpneg_operand (operands[2], SImode))
6847
    {
6848
      emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
6849
                                              operands[3], operands[0]));
6850
      DONE;
6851
    }
6852
  if (!thumb1_cmp_operand (operands[2], SImode))
6853
    operands[2] = force_reg (SImode, operands[2]);
6854
  ")
6855
 
6856
;; A pattern to recognize a special situation and optimize for it.
6857
;; On the thumb, zero-extension from memory is preferrable to sign-extension
6858
;; due to the available addressing modes.  Hence, convert a signed comparison
6859
;; with zero into an unsigned comparison with 127 if possible.
6860
(define_expand "cbranchqi4"
6861
  [(set (pc) (if_then_else
6862
              (match_operator 0 "lt_ge_comparison_operator"
6863
               [(match_operand:QI 1 "memory_operand" "")
6864
                (match_operand:QI 2 "const0_operand" "")])
6865
              (label_ref (match_operand 3 "" ""))
6866
              (pc)))]
6867
  "TARGET_THUMB1"
6868
{
6869
  rtx xops[4];
6870
  xops[1] = gen_reg_rtx (SImode);
6871
  emit_insn (gen_zero_extendqisi2 (xops[1], operands[1]));
6872
  xops[2] = GEN_INT (127);
6873
  xops[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]) == GE ? LEU : GTU,
6874
                            VOIDmode, xops[1], xops[2]);
6875
  xops[3] = operands[3];
6876
  emit_insn (gen_cbranchsi4 (xops[0], xops[1], xops[2], xops[3]));
6877
  DONE;
6878
})
6879
 
6880
(define_expand "cbranchsf4"
6881
  [(set (pc) (if_then_else
6882
              (match_operator 0 "expandable_comparison_operator"
6883
               [(match_operand:SF 1 "s_register_operand" "")
6884
                (match_operand:SF 2 "arm_float_compare_operand" "")])
6885
              (label_ref (match_operand 3 "" ""))
6886
              (pc)))]
6887
  "TARGET_32BIT && TARGET_HARD_FLOAT"
6888
  "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6889
                                   operands[3])); DONE;"
6890
)
6891
 
6892
(define_expand "cbranchdf4"
6893
  [(set (pc) (if_then_else
6894
              (match_operator 0 "expandable_comparison_operator"
6895
               [(match_operand:DF 1 "s_register_operand" "")
6896
                (match_operand:DF 2 "arm_float_compare_operand" "")])
6897
              (label_ref (match_operand 3 "" ""))
6898
              (pc)))]
6899
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
6900
  "emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6901
                                   operands[3])); DONE;"
6902
)
6903
 
6904
(define_expand "cbranchdi4"
6905
  [(set (pc) (if_then_else
6906
              (match_operator 0 "expandable_comparison_operator"
6907
               [(match_operand:DI 1 "cmpdi_operand" "")
6908
                (match_operand:DI 2 "cmpdi_operand" "")])
6909
              (label_ref (match_operand 3 "" ""))
6910
              (pc)))]
6911
  "TARGET_32BIT"
6912
  "{
6913
     rtx swap = NULL_RTX;
6914
     enum rtx_code code = GET_CODE (operands[0]);
6915
 
6916
     /* We should not have two constants.  */
6917
     gcc_assert (GET_MODE (operands[1]) == DImode
6918
                 || GET_MODE (operands[2]) == DImode);
6919
 
6920
    /* Flip unimplemented DImode comparisons to a form that
6921
       arm_gen_compare_reg can handle.  */
6922
     switch (code)
6923
     {
6924
     case GT:
6925
       swap = gen_rtx_LT (VOIDmode, operands[2], operands[1]); break;
6926
     case LE:
6927
       swap = gen_rtx_GE (VOIDmode, operands[2], operands[1]); break;
6928
     case GTU:
6929
       swap = gen_rtx_LTU (VOIDmode, operands[2], operands[1]); break;
6930
     case LEU:
6931
       swap = gen_rtx_GEU (VOIDmode, operands[2], operands[1]); break;
6932
     default:
6933
       break;
6934
     }
6935
     if (swap)
6936
       emit_jump_insn (gen_cbranch_cc (swap, operands[2], operands[1],
6937
                                       operands[3]));
6938
     else
6939
       emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
6940
                                       operands[3]));
6941
     DONE;
6942
   }"
6943
)
6944
 
6945
(define_insn "cbranchsi4_insn"
6946
  [(set (pc) (if_then_else
6947
              (match_operator 0 "arm_comparison_operator"
6948
               [(match_operand:SI 1 "s_register_operand" "l,l*h")
6949
                (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")])
6950
              (label_ref (match_operand 3 "" ""))
6951
              (pc)))]
6952
  "TARGET_THUMB1"
6953
{
6954
  rtx t = cfun->machine->thumb1_cc_insn;
6955
  if (t != NULL_RTX)
6956
    {
6957
      if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1])
6958
          || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2]))
6959
        t = NULL_RTX;
6960
      if (cfun->machine->thumb1_cc_mode == CC_NOOVmode)
6961
        {
6962
          if (!noov_comparison_operator (operands[0], VOIDmode))
6963
            t = NULL_RTX;
6964
        }
6965
      else if (cfun->machine->thumb1_cc_mode != CCmode)
6966
        t = NULL_RTX;
6967
    }
6968
  if (t == NULL_RTX)
6969
    {
6970
      output_asm_insn ("cmp\t%1, %2", operands);
6971
      cfun->machine->thumb1_cc_insn = insn;
6972
      cfun->machine->thumb1_cc_op0 = operands[1];
6973
      cfun->machine->thumb1_cc_op1 = operands[2];
6974
      cfun->machine->thumb1_cc_mode = CCmode;
6975
    }
6976
  else
6977
    /* Ensure we emit the right type of condition code on the jump.  */
6978
    XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode,
6979
                                         CC_REGNUM);
6980
 
6981
  switch (get_attr_length (insn))
6982
    {
6983
    case 4:  return \"b%d0\\t%l3\";
6984
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6985
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6986
    }
6987
}
6988
  [(set (attr "far_jump")
6989
        (if_then_else
6990
            (eq_attr "length" "8")
6991
            (const_string "yes")
6992
            (const_string "no")))
6993
   (set (attr "length")
6994
        (if_then_else
6995
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6996
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
6997
            (const_int 4)
6998
            (if_then_else
6999
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7000
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
7001
                (const_int 6)
7002
                (const_int 8))))]
7003
)
7004
 
7005
(define_insn "cbranchsi4_scratch"
7006
  [(set (pc) (if_then_else
7007
              (match_operator 4 "arm_comparison_operator"
7008
               [(match_operand:SI 1 "s_register_operand" "l,0")
7009
                (match_operand:SI 2 "thumb1_cmpneg_operand" "L,J")])
7010
              (label_ref (match_operand 3 "" ""))
7011
              (pc)))
7012
   (clobber (match_scratch:SI 0 "=l,l"))]
7013
  "TARGET_THUMB1"
7014
  "*
7015
  output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
7016
 
7017
  switch (get_attr_length (insn))
7018
    {
7019
    case 4:  return \"b%d4\\t%l3\";
7020
    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7021
    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7022
    }
7023
  "
7024
  [(set (attr "far_jump")
7025
        (if_then_else
7026
            (eq_attr "length" "8")
7027
            (const_string "yes")
7028
            (const_string "no")))
7029
   (set (attr "length")
7030
        (if_then_else
7031
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7032
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
7033
            (const_int 4)
7034
            (if_then_else
7035
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7036
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
7037
                (const_int 6)
7038
                (const_int 8))))]
7039
)
7040
 
7041
;; Two peepholes to generate subtract of 0 instead of a move if the
7042
;; condition codes will be useful.
7043
(define_peephole2
7044
  [(set (match_operand:SI 0 "low_register_operand" "")
7045
        (match_operand:SI 1 "low_register_operand" ""))
7046
   (set (pc)
7047
        (if_then_else (match_operator 2 "arm_comparison_operator"
7048
                       [(match_dup 1) (const_int 0)])
7049
                      (label_ref (match_operand 3 "" ""))
7050
                      (pc)))]
7051
  "TARGET_THUMB1"
7052
  [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7053
   (set (pc)
7054
        (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
7055
                      (label_ref (match_dup 3))
7056
                      (pc)))]
7057
  "")
7058
 
7059
;; Sigh!  This variant shouldn't be needed, but combine often fails to
7060
;; merge cases like this because the op1 is a hard register in
7061
;; arm_class_likely_spilled_p.
7062
(define_peephole2
7063
  [(set (match_operand:SI 0 "low_register_operand" "")
7064
        (match_operand:SI 1 "low_register_operand" ""))
7065
   (set (pc)
7066
        (if_then_else (match_operator 2 "arm_comparison_operator"
7067
                       [(match_dup 0) (const_int 0)])
7068
                      (label_ref (match_operand 3 "" ""))
7069
                      (pc)))]
7070
  "TARGET_THUMB1"
7071
  [(set (match_dup 0) (minus:SI (match_dup 1) (const_int 0)))
7072
   (set (pc)
7073
        (if_then_else (match_op_dup 2 [(match_dup 0) (const_int 0)])
7074
                      (label_ref (match_dup 3))
7075
                      (pc)))]
7076
  "")
7077
 
7078
(define_insn "*negated_cbranchsi4"
7079
  [(set (pc)
7080
        (if_then_else
7081
         (match_operator 0 "equality_operator"
7082
          [(match_operand:SI 1 "s_register_operand" "l")
7083
           (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
7084
         (label_ref (match_operand 3 "" ""))
7085
         (pc)))]
7086
  "TARGET_THUMB1"
7087
  "*
7088
  output_asm_insn (\"cmn\\t%1, %2\", operands);
7089
  switch (get_attr_length (insn))
7090
    {
7091
    case 4:  return \"b%d0\\t%l3\";
7092
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7093
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7094
    }
7095
  "
7096
  [(set (attr "far_jump")
7097
        (if_then_else
7098
            (eq_attr "length" "8")
7099
            (const_string "yes")
7100
            (const_string "no")))
7101
   (set (attr "length")
7102
        (if_then_else
7103
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7104
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
7105
            (const_int 4)
7106
            (if_then_else
7107
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7108
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
7109
                (const_int 6)
7110
                (const_int 8))))]
7111
)
7112
 
7113
(define_insn "*tbit_cbranch"
7114
  [(set (pc)
7115
        (if_then_else
7116
         (match_operator 0 "equality_operator"
7117
          [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7118
                            (const_int 1)
7119
                            (match_operand:SI 2 "const_int_operand" "i"))
7120
           (const_int 0)])
7121
         (label_ref (match_operand 3 "" ""))
7122
         (pc)))
7123
   (clobber (match_scratch:SI 4 "=l"))]
7124
  "TARGET_THUMB1"
7125
  "*
7126
  {
7127
  rtx op[3];
7128
  op[0] = operands[4];
7129
  op[1] = operands[1];
7130
  op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
7131
 
7132
  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7133
  switch (get_attr_length (insn))
7134
    {
7135
    case 4:  return \"b%d0\\t%l3\";
7136
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7137
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7138
    }
7139
  }"
7140
  [(set (attr "far_jump")
7141
        (if_then_else
7142
            (eq_attr "length" "8")
7143
            (const_string "yes")
7144
            (const_string "no")))
7145
   (set (attr "length")
7146
        (if_then_else
7147
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7148
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
7149
            (const_int 4)
7150
            (if_then_else
7151
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7152
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
7153
                (const_int 6)
7154
                (const_int 8))))]
7155
)
7156
 
7157
(define_insn "*tlobits_cbranch"
7158
  [(set (pc)
7159
        (if_then_else
7160
         (match_operator 0 "equality_operator"
7161
          [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
7162
                            (match_operand:SI 2 "const_int_operand" "i")
7163
                            (const_int 0))
7164
           (const_int 0)])
7165
         (label_ref (match_operand 3 "" ""))
7166
         (pc)))
7167
   (clobber (match_scratch:SI 4 "=l"))]
7168
  "TARGET_THUMB1"
7169
  "*
7170
  {
7171
  rtx op[3];
7172
  op[0] = operands[4];
7173
  op[1] = operands[1];
7174
  op[2] = GEN_INT (32 - INTVAL (operands[2]));
7175
 
7176
  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
7177
  switch (get_attr_length (insn))
7178
    {
7179
    case 4:  return \"b%d0\\t%l3\";
7180
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
7181
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
7182
    }
7183
  }"
7184
  [(set (attr "far_jump")
7185
        (if_then_else
7186
            (eq_attr "length" "8")
7187
            (const_string "yes")
7188
            (const_string "no")))
7189
   (set (attr "length")
7190
        (if_then_else
7191
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
7192
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
7193
            (const_int 4)
7194
            (if_then_else
7195
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
7196
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
7197
                (const_int 6)
7198
                (const_int 8))))]
7199
)
7200
 
7201
(define_insn "*tstsi3_cbranch"
7202
  [(set (pc)
7203
        (if_then_else
7204
         (match_operator 3 "equality_operator"
7205
          [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
7206
                   (match_operand:SI 1 "s_register_operand" "l"))
7207
           (const_int 0)])
7208
         (label_ref (match_operand 2 "" ""))
7209
         (pc)))]
7210
  "TARGET_THUMB1"
7211
  "*
7212
  {
7213
  output_asm_insn (\"tst\\t%0, %1\", operands);
7214
  switch (get_attr_length (insn))
7215
    {
7216
    case 4:  return \"b%d3\\t%l2\";
7217
    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
7218
    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
7219
    }
7220
  }"
7221
  [(set (attr "far_jump")
7222
        (if_then_else
7223
            (eq_attr "length" "8")
7224
            (const_string "yes")
7225
            (const_string "no")))
7226
   (set (attr "length")
7227
        (if_then_else
7228
            (and (ge (minus (match_dup 2) (pc)) (const_int -250))
7229
                 (le (minus (match_dup 2) (pc)) (const_int 256)))
7230
            (const_int 4)
7231
            (if_then_else
7232
                (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
7233
                     (le (minus (match_dup 2) (pc)) (const_int 2048)))
7234
                (const_int 6)
7235
                (const_int 8))))]
7236
)
7237
 
7238
(define_insn "*cbranchne_decr1"
7239
  [(set (pc)
7240
        (if_then_else (match_operator 3 "equality_operator"
7241
                       [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
7242
                        (const_int 0)])
7243
                      (label_ref (match_operand 4 "" ""))
7244
                      (pc)))
7245
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
7246
        (plus:SI (match_dup 2) (const_int -1)))
7247
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
7248
  "TARGET_THUMB1"
7249
  "*
7250
   {
7251
     rtx cond[2];
7252
     cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
7253
                                ? GEU : LTU),
7254
                               VOIDmode, operands[2], const1_rtx);
7255
     cond[1] = operands[4];
7256
 
7257
     if (which_alternative == 0)
7258
       output_asm_insn (\"sub\\t%0, %2, #1\", operands);
7259
     else if (which_alternative == 1)
7260
       {
7261
         /* We must provide an alternative for a hi reg because reload
7262
            cannot handle output reloads on a jump instruction, but we
7263
            can't subtract into that.  Fortunately a mov from lo to hi
7264
            does not clobber the condition codes.  */
7265
         output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7266
         output_asm_insn (\"mov\\t%0, %1\", operands);
7267
       }
7268
     else
7269
       {
7270
         /* Similarly, but the target is memory.  */
7271
         output_asm_insn (\"sub\\t%1, %2, #1\", operands);
7272
         output_asm_insn (\"str\\t%1, %0\", operands);
7273
       }
7274
 
7275
     switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
7276
       {
7277
         case 4:
7278
           output_asm_insn (\"b%d0\\t%l1\", cond);
7279
           return \"\";
7280
         case 6:
7281
           output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7282
           return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
7283
         default:
7284
           output_asm_insn (\"b%D0\\t.LCB%=\", cond);
7285
           return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7286
       }
7287
   }
7288
  "
7289
  [(set (attr "far_jump")
7290
        (if_then_else
7291
            (ior (and (eq (symbol_ref ("which_alternative"))
7292
                          (const_int 0))
7293
                      (eq_attr "length" "8"))
7294
                 (eq_attr "length" "10"))
7295
            (const_string "yes")
7296
            (const_string "no")))
7297
   (set_attr_alternative "length"
7298
      [
7299
       ;; Alternative 0
7300
       (if_then_else
7301
         (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7302
              (le (minus (match_dup 4) (pc)) (const_int 256)))
7303
         (const_int 4)
7304
         (if_then_else
7305
           (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7306
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
7307
           (const_int 6)
7308
           (const_int 8)))
7309
       ;; Alternative 1
7310
       (if_then_else
7311
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7312
              (le (minus (match_dup 4) (pc)) (const_int 256)))
7313
         (const_int 6)
7314
         (if_then_else
7315
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7316
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
7317
           (const_int 8)
7318
           (const_int 10)))
7319
       ;; Alternative 2
7320
       (if_then_else
7321
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7322
              (le (minus (match_dup 4) (pc)) (const_int 256)))
7323
         (const_int 6)
7324
         (if_then_else
7325
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7326
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
7327
           (const_int 8)
7328
           (const_int 10)))
7329
       ;; Alternative 3
7330
       (if_then_else
7331
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
7332
              (le (minus (match_dup 4) (pc)) (const_int 256)))
7333
         (const_int 6)
7334
         (if_then_else
7335
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
7336
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
7337
           (const_int 8)
7338
           (const_int 10)))])]
7339
)
7340
 
7341
(define_insn "*addsi3_cbranch"
7342
  [(set (pc)
7343
        (if_then_else
7344
         (match_operator 4 "arm_comparison_operator"
7345
          [(plus:SI
7346
            (match_operand:SI 2 "s_register_operand" "%0,l,*l,1,1,1")
7347
            (match_operand:SI 3 "reg_or_int_operand" "IJ,lL,*l,lIJ,lIJ,lIJ"))
7348
           (const_int 0)])
7349
         (label_ref (match_operand 5 "" ""))
7350
         (pc)))
7351
   (set
7352
    (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
7353
    (plus:SI (match_dup 2) (match_dup 3)))
7354
   (clobber (match_scratch:SI 1 "=X,X,l,l,&l,&l"))]
7355
  "TARGET_THUMB1
7356
   && (GET_CODE (operands[4]) == EQ
7357
       || GET_CODE (operands[4]) == NE
7358
       || GET_CODE (operands[4]) == GE
7359
       || GET_CODE (operands[4]) == LT)"
7360
  "*
7361
   {
7362
     rtx cond[3];
7363
 
7364
     cond[0] = (which_alternative < 2) ? operands[0] : operands[1];
7365
     cond[1] = operands[2];
7366
     cond[2] = operands[3];
7367
 
7368
     if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
7369
       output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
7370
     else
7371
       output_asm_insn (\"add\\t%0, %1, %2\", cond);
7372
 
7373
     if (which_alternative >= 2
7374
         && which_alternative < 4)
7375
       output_asm_insn (\"mov\\t%0, %1\", operands);
7376
     else if (which_alternative >= 4)
7377
       output_asm_insn (\"str\\t%1, %0\", operands);
7378
 
7379
     switch (get_attr_length (insn) - ((which_alternative >= 2) ? 2 : 0))
7380
       {
7381
         case 4:
7382
           return \"b%d4\\t%l5\";
7383
         case 6:
7384
           return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
7385
         default:
7386
           return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
7387
       }
7388
   }
7389
  "
7390
  [(set (attr "far_jump")
7391
        (if_then_else
7392
            (ior (and (lt (symbol_ref ("which_alternative"))
7393
                          (const_int 2))
7394
                      (eq_attr "length" "8"))
7395
                 (eq_attr "length" "10"))
7396
            (const_string "yes")
7397
            (const_string "no")))
7398
   (set (attr "length")
7399
     (if_then_else
7400
       (lt (symbol_ref ("which_alternative"))
7401
                       (const_int 2))
7402
       (if_then_else
7403
         (and (ge (minus (match_dup 5) (pc)) (const_int -250))
7404
              (le (minus (match_dup 5) (pc)) (const_int 256)))
7405
         (const_int 4)
7406
         (if_then_else
7407
           (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
7408
                (le (minus (match_dup 5) (pc)) (const_int 2048)))
7409
           (const_int 6)
7410
           (const_int 8)))
7411
       (if_then_else
7412
         (and (ge (minus (match_dup 5) (pc)) (const_int -248))
7413
              (le (minus (match_dup 5) (pc)) (const_int 256)))
7414
         (const_int 6)
7415
         (if_then_else
7416
           (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
7417
                (le (minus (match_dup 5) (pc)) (const_int 2048)))
7418
           (const_int 8)
7419
           (const_int 10)))))]
7420
)
7421
 
7422
(define_insn "*addsi3_cbranch_scratch"
7423
  [(set (pc)
7424
        (if_then_else
7425
         (match_operator 3 "arm_comparison_operator"
7426
          [(plus:SI
7427
            (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
7428
            (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
7429
           (const_int 0)])
7430
         (label_ref (match_operand 4 "" ""))
7431
         (pc)))
7432
   (clobber (match_scratch:SI 0 "=X,X,l,l"))]
7433
  "TARGET_THUMB1
7434
   && (GET_CODE (operands[3]) == EQ
7435
       || GET_CODE (operands[3]) == NE
7436
       || GET_CODE (operands[3]) == GE
7437
       || GET_CODE (operands[3]) == LT)"
7438
  "*
7439
   {
7440
     switch (which_alternative)
7441
       {
7442
       case 0:
7443
         output_asm_insn (\"cmp\t%1, #%n2\", operands);
7444
         break;
7445
       case 1:
7446
         output_asm_insn (\"cmn\t%1, %2\", operands);
7447
         break;
7448
       case 2:
7449
         if (INTVAL (operands[2]) < 0)
7450
           output_asm_insn (\"sub\t%0, %1, %2\", operands);
7451
         else
7452
           output_asm_insn (\"add\t%0, %1, %2\", operands);
7453
         break;
7454
       case 3:
7455
         if (INTVAL (operands[2]) < 0)
7456
           output_asm_insn (\"sub\t%0, %0, %2\", operands);
7457
         else
7458
           output_asm_insn (\"add\t%0, %0, %2\", operands);
7459
         break;
7460
       }
7461
 
7462
     switch (get_attr_length (insn))
7463
       {
7464
         case 4:
7465
           return \"b%d3\\t%l4\";
7466
         case 6:
7467
           return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
7468
         default:
7469
           return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
7470
       }
7471
   }
7472
  "
7473
  [(set (attr "far_jump")
7474
        (if_then_else
7475
            (eq_attr "length" "8")
7476
            (const_string "yes")
7477
            (const_string "no")))
7478
   (set (attr "length")
7479
       (if_then_else
7480
         (and (ge (minus (match_dup 4) (pc)) (const_int -250))
7481
              (le (minus (match_dup 4) (pc)) (const_int 256)))
7482
         (const_int 4)
7483
         (if_then_else
7484
           (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
7485
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
7486
           (const_int 6)
7487
           (const_int 8))))]
7488
)
7489
 
7490
 
7491
;; Comparison and test insns
7492
 
7493
(define_insn "*arm_cmpsi_insn"
7494
  [(set (reg:CC CC_REGNUM)
7495
        (compare:CC (match_operand:SI 0 "s_register_operand" "l,r,r,r")
7496
                    (match_operand:SI 1 "arm_add_operand"    "Py,r,rI,L")))]
7497
  "TARGET_32BIT"
7498
  "@
7499
   cmp%?\\t%0, %1
7500
   cmp%?\\t%0, %1
7501
   cmp%?\\t%0, %1
7502
   cmn%?\\t%0, #%n1"
7503
  [(set_attr "conds" "set")
7504
   (set_attr "arch" "t2,t2,any,any")
7505
   (set_attr "length" "2,2,4,4")
7506
   (set_attr "predicable" "yes")]
7507
)
7508
 
7509
(define_insn "*cmpsi_shiftsi"
7510
  [(set (reg:CC CC_REGNUM)
7511
        (compare:CC (match_operand:SI   0 "s_register_operand" "r,r")
7512
                    (match_operator:SI  3 "shift_operator"
7513
                     [(match_operand:SI 1 "s_register_operand" "r,r")
7514
                      (match_operand:SI 2 "shift_amount_operand" "M,rM")])))]
7515
  "TARGET_32BIT"
7516
  "cmp%?\\t%0, %1%S3"
7517
  [(set_attr "conds" "set")
7518
   (set_attr "shift" "1")
7519
   (set_attr "arch" "32,a")
7520
   (set_attr "type" "alu_shift,alu_shift_reg")])
7521
 
7522
(define_insn "*cmpsi_shiftsi_swp"
7523
  [(set (reg:CC_SWP CC_REGNUM)
7524
        (compare:CC_SWP (match_operator:SI 3 "shift_operator"
7525
                         [(match_operand:SI 1 "s_register_operand" "r,r")
7526
                          (match_operand:SI 2 "shift_amount_operand" "M,rM")])
7527
                        (match_operand:SI 0 "s_register_operand" "r,r")))]
7528
  "TARGET_32BIT"
7529
  "cmp%?\\t%0, %1%S3"
7530
  [(set_attr "conds" "set")
7531
   (set_attr "shift" "1")
7532
   (set_attr "arch" "32,a")
7533
   (set_attr "type" "alu_shift,alu_shift_reg")])
7534
 
7535
(define_insn "*arm_cmpsi_negshiftsi_si"
7536
  [(set (reg:CC_Z CC_REGNUM)
7537
        (compare:CC_Z
7538
         (neg:SI (match_operator:SI 1 "shift_operator"
7539
                    [(match_operand:SI 2 "s_register_operand" "r")
7540
                     (match_operand:SI 3 "reg_or_int_operand" "rM")]))
7541
         (match_operand:SI 0 "s_register_operand" "r")))]
7542
  "TARGET_ARM"
7543
  "cmn%?\\t%0, %2%S1"
7544
  [(set_attr "conds" "set")
7545
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
7546
                                    (const_string "alu_shift")
7547
                                    (const_string "alu_shift_reg")))
7548
   (set_attr "predicable" "yes")]
7549
)
7550
 
7551
;; DImode comparisons.  The generic code generates branches that
7552
;; if-conversion can not reduce to a conditional compare, so we do
7553
;; that directly.
7554
 
7555
(define_insn "*arm_cmpdi_insn"
7556
  [(set (reg:CC_NCV CC_REGNUM)
7557
        (compare:CC_NCV (match_operand:DI 0 "s_register_operand" "r")
7558
                        (match_operand:DI 1 "arm_di_operand"       "rDi")))
7559
   (clobber (match_scratch:SI 2 "=r"))]
7560
  "TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
7561
  "cmp\\t%Q0, %Q1\;sbcs\\t%2, %R0, %R1"
7562
  [(set_attr "conds" "set")
7563
   (set_attr "length" "8")]
7564
)
7565
 
7566
(define_insn "*arm_cmpdi_unsigned"
7567
  [(set (reg:CC_CZ CC_REGNUM)
7568
        (compare:CC_CZ (match_operand:DI 0 "s_register_operand" "r")
7569
                       (match_operand:DI 1 "arm_di_operand"     "rDi")))]
7570
  "TARGET_32BIT"
7571
  "cmp\\t%R0, %R1\;it eq\;cmpeq\\t%Q0, %Q1"
7572
  [(set_attr "conds" "set")
7573
   (set_attr "length" "8")]
7574
)
7575
 
7576
(define_insn "*arm_cmpdi_zero"
7577
  [(set (reg:CC_Z CC_REGNUM)
7578
        (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r")
7579
                      (const_int 0)))
7580
   (clobber (match_scratch:SI 1 "=r"))]
7581
  "TARGET_32BIT"
7582
  "orr%.\\t%1, %Q0, %R0"
7583
  [(set_attr "conds" "set")]
7584
)
7585
 
7586
(define_insn "*thumb_cmpdi_zero"
7587
  [(set (reg:CC_Z CC_REGNUM)
7588
        (compare:CC_Z (match_operand:DI 0 "s_register_operand" "l")
7589
                      (const_int 0)))
7590
   (clobber (match_scratch:SI 1 "=l"))]
7591
  "TARGET_THUMB1"
7592
  "orr\\t%1, %Q0, %R0"
7593
  [(set_attr "conds" "set")
7594
   (set_attr "length" "2")]
7595
)
7596
 
7597
;; Cirrus SF compare instruction
7598
(define_insn "*cirrus_cmpsf"
7599
  [(set (reg:CCFP CC_REGNUM)
7600
        (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
7601
                      (match_operand:SF 1 "cirrus_fp_register" "v")))]
7602
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7603
  "cfcmps%?\\tr15, %V0, %V1"
7604
  [(set_attr "type"   "mav_farith")
7605
   (set_attr "cirrus" "compare")]
7606
)
7607
 
7608
;; Cirrus DF compare instruction
7609
(define_insn "*cirrus_cmpdf"
7610
  [(set (reg:CCFP CC_REGNUM)
7611
        (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
7612
                      (match_operand:DF 1 "cirrus_fp_register" "v")))]
7613
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7614
  "cfcmpd%?\\tr15, %V0, %V1"
7615
  [(set_attr "type"   "mav_farith")
7616
   (set_attr "cirrus" "compare")]
7617
)
7618
 
7619
(define_insn "*cirrus_cmpdi"
7620
  [(set (reg:CC CC_REGNUM)
7621
        (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
7622
                    (match_operand:DI 1 "cirrus_fp_register" "v")))]
7623
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
7624
  "cfcmp64%?\\tr15, %V0, %V1"
7625
  [(set_attr "type"   "mav_farith")
7626
   (set_attr "cirrus" "compare")]
7627
)
7628
 
7629
; This insn allows redundant compares to be removed by cse, nothing should
7630
; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7631
; is deleted later on. The match_dup will match the mode here, so that
7632
; mode changes of the condition codes aren't lost by this even though we don't
7633
; specify what they are.
7634
 
7635
(define_insn "*deleted_compare"
7636
  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7637
  "TARGET_32BIT"
7638
  "\\t%@ deleted compare"
7639
  [(set_attr "conds" "set")
7640
   (set_attr "length" "0")]
7641
)
7642
 
7643
 
7644
;; Conditional branch insns
7645
 
7646
(define_expand "cbranch_cc"
7647
  [(set (pc)
7648
        (if_then_else (match_operator 0 "" [(match_operand 1 "" "")
7649
                                            (match_operand 2 "" "")])
7650
                      (label_ref (match_operand 3 "" ""))
7651
                      (pc)))]
7652
  "TARGET_32BIT"
7653
  "operands[1] = arm_gen_compare_reg (GET_CODE (operands[0]),
7654
                                      operands[1], operands[2], NULL_RTX);
7655
   operands[2] = const0_rtx;"
7656
)
7657
 
7658
;;
7659
;; Patterns to match conditional branch insns.
7660
;;
7661
 
7662
(define_insn "*arm_cond_branch"
7663
  [(set (pc)
7664
        (if_then_else (match_operator 1 "arm_comparison_operator"
7665
                       [(match_operand 2 "cc_register" "") (const_int 0)])
7666
                      (label_ref (match_operand 0 "" ""))
7667
                      (pc)))]
7668
  "TARGET_32BIT"
7669
  "*
7670
  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7671
    {
7672
      arm_ccfsm_state += 2;
7673
      return \"\";
7674
    }
7675
  return \"b%d1\\t%l0\";
7676
  "
7677
  [(set_attr "conds" "use")
7678
   (set_attr "type" "branch")
7679
   (set (attr "length")
7680
        (if_then_else
7681
           (and (match_test "TARGET_THUMB2")
7682
                (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7683
                     (le (minus (match_dup 0) (pc)) (const_int 256))))
7684
           (const_int 2)
7685
           (const_int 4)))]
7686
)
7687
 
7688
(define_insn "*arm_cond_branch_reversed"
7689
  [(set (pc)
7690
        (if_then_else (match_operator 1 "arm_comparison_operator"
7691
                       [(match_operand 2 "cc_register" "") (const_int 0)])
7692
                      (pc)
7693
                      (label_ref (match_operand 0 "" ""))))]
7694
  "TARGET_32BIT"
7695
  "*
7696
  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7697
    {
7698
      arm_ccfsm_state += 2;
7699
      return \"\";
7700
    }
7701
  return \"b%D1\\t%l0\";
7702
  "
7703
  [(set_attr "conds" "use")
7704
   (set_attr "type" "branch")
7705
   (set (attr "length")
7706
        (if_then_else
7707
           (and (match_test "TARGET_THUMB2")
7708
                (and (ge (minus (match_dup 0) (pc)) (const_int -250))
7709
                     (le (minus (match_dup 0) (pc)) (const_int 256))))
7710
           (const_int 2)
7711
           (const_int 4)))]
7712
)
7713
 
7714
 
7715
 
7716
; scc insns
7717
 
7718
(define_expand "cstore_cc"
7719
  [(set (match_operand:SI 0 "s_register_operand" "")
7720
        (match_operator:SI 1 "" [(match_operand 2 "" "")
7721
                                 (match_operand 3 "" "")]))]
7722
  "TARGET_32BIT"
7723
  "operands[2] = arm_gen_compare_reg (GET_CODE (operands[1]),
7724
                                      operands[2], operands[3], NULL_RTX);
7725
   operands[3] = const0_rtx;"
7726
)
7727
 
7728
(define_insn "*mov_scc"
7729
  [(set (match_operand:SI 0 "s_register_operand" "=r")
7730
        (match_operator:SI 1 "arm_comparison_operator"
7731
         [(match_operand 2 "cc_register" "") (const_int 0)]))]
7732
  "TARGET_ARM"
7733
  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7734
  [(set_attr "conds" "use")
7735
   (set_attr "insn" "mov")
7736
   (set_attr "length" "8")]
7737
)
7738
 
7739
(define_insn "*mov_negscc"
7740
  [(set (match_operand:SI 0 "s_register_operand" "=r")
7741
        (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7742
                 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7743
  "TARGET_ARM"
7744
  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7745
  [(set_attr "conds" "use")
7746
   (set_attr "insn" "mov")
7747
   (set_attr "length" "8")]
7748
)
7749
 
7750
(define_insn "*mov_notscc"
7751
  [(set (match_operand:SI 0 "s_register_operand" "=r")
7752
        (not:SI (match_operator:SI 1 "arm_comparison_operator"
7753
                 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7754
  "TARGET_ARM"
7755
  "mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7756
  [(set_attr "conds" "use")
7757
   (set_attr "insn" "mov")
7758
   (set_attr "length" "8")]
7759
)
7760
 
7761
(define_expand "cstoresi4"
7762
  [(set (match_operand:SI 0 "s_register_operand" "")
7763
        (match_operator:SI 1 "expandable_comparison_operator"
7764
         [(match_operand:SI 2 "s_register_operand" "")
7765
          (match_operand:SI 3 "reg_or_int_operand" "")]))]
7766
  "TARGET_32BIT || TARGET_THUMB1"
7767
  "{
7768
  rtx op3, scratch, scratch2;
7769
 
7770
  if (!TARGET_THUMB1)
7771
    {
7772
      if (!arm_add_operand (operands[3], SImode))
7773
        operands[3] = force_reg (SImode, operands[3]);
7774
      emit_insn (gen_cstore_cc (operands[0], operands[1],
7775
                                operands[2], operands[3]));
7776
      DONE;
7777
    }
7778
 
7779
  if (operands[3] == const0_rtx)
7780
    {
7781
      switch (GET_CODE (operands[1]))
7782
        {
7783
        case EQ:
7784
          emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], operands[2]));
7785
          break;
7786
 
7787
        case NE:
7788
          emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], operands[2]));
7789
          break;
7790
 
7791
        case LE:
7792
          scratch = expand_binop (SImode, add_optab, operands[2], constm1_rtx,
7793
                                  NULL_RTX, 0, OPTAB_WIDEN);
7794
          scratch = expand_binop (SImode, ior_optab, operands[2], scratch,
7795
                                  NULL_RTX, 0, OPTAB_WIDEN);
7796
          expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7797
                        operands[0], 1, OPTAB_WIDEN);
7798
          break;
7799
 
7800
        case GE:
7801
          scratch = expand_unop (SImode, one_cmpl_optab, operands[2],
7802
                                 NULL_RTX, 1);
7803
          expand_binop (SImode, lshr_optab, scratch, GEN_INT (31),
7804
                        NULL_RTX, 1, OPTAB_WIDEN);
7805
          break;
7806
 
7807
        case GT:
7808
          scratch = expand_binop (SImode, ashr_optab, operands[2],
7809
                                  GEN_INT (31), NULL_RTX, 0, OPTAB_WIDEN);
7810
          scratch = expand_binop (SImode, sub_optab, scratch, operands[2],
7811
                                  NULL_RTX, 0, OPTAB_WIDEN);
7812
          expand_binop (SImode, lshr_optab, scratch, GEN_INT (31), operands[0],
7813
                        0, OPTAB_WIDEN);
7814
          break;
7815
 
7816
        /* LT is handled by generic code.  No need for unsigned with 0.  */
7817
        default:
7818
          FAIL;
7819
        }
7820
      DONE;
7821
    }
7822
 
7823
  switch (GET_CODE (operands[1]))
7824
    {
7825
    case EQ:
7826
      scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7827
                              NULL_RTX, 0, OPTAB_WIDEN);
7828
      emit_insn (gen_cstoresi_eq0_thumb1 (operands[0], scratch));
7829
      break;
7830
 
7831
    case NE:
7832
      scratch = expand_binop (SImode, sub_optab, operands[2], operands[3],
7833
                              NULL_RTX, 0, OPTAB_WIDEN);
7834
      emit_insn (gen_cstoresi_ne0_thumb1 (operands[0], scratch));
7835
      break;
7836
 
7837
    case LE:
7838
      op3 = force_reg (SImode, operands[3]);
7839
 
7840
      scratch = expand_binop (SImode, lshr_optab, operands[2], GEN_INT (31),
7841
                              NULL_RTX, 1, OPTAB_WIDEN);
7842
      scratch2 = expand_binop (SImode, ashr_optab, op3, GEN_INT (31),
7843
                              NULL_RTX, 0, OPTAB_WIDEN);
7844
      emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7845
                                          op3, operands[2]));
7846
      break;
7847
 
7848
    case GE:
7849
      op3 = operands[3];
7850
      if (!thumb1_cmp_operand (op3, SImode))
7851
        op3 = force_reg (SImode, op3);
7852
      scratch = expand_binop (SImode, ashr_optab, operands[2], GEN_INT (31),
7853
                              NULL_RTX, 0, OPTAB_WIDEN);
7854
      scratch2 = expand_binop (SImode, lshr_optab, op3, GEN_INT (31),
7855
                               NULL_RTX, 1, OPTAB_WIDEN);
7856
      emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch2,
7857
                                          operands[2], op3));
7858
      break;
7859
 
7860
    case LEU:
7861
      op3 = force_reg (SImode, operands[3]);
7862
      scratch = force_reg (SImode, const0_rtx);
7863
      emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7864
                                          op3, operands[2]));
7865
      break;
7866
 
7867
    case GEU:
7868
      op3 = operands[3];
7869
      if (!thumb1_cmp_operand (op3, SImode))
7870
        op3 = force_reg (SImode, op3);
7871
      scratch = force_reg (SImode, const0_rtx);
7872
      emit_insn (gen_thumb1_addsi3_addgeu (operands[0], scratch, scratch,
7873
                                          operands[2], op3));
7874
      break;
7875
 
7876
    case LTU:
7877
      op3 = operands[3];
7878
      if (!thumb1_cmp_operand (op3, SImode))
7879
        op3 = force_reg (SImode, op3);
7880
      scratch = gen_reg_rtx (SImode);
7881
      emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], operands[2], op3));
7882
      break;
7883
 
7884
    case GTU:
7885
      op3 = force_reg (SImode, operands[3]);
7886
      scratch = gen_reg_rtx (SImode);
7887
      emit_insn (gen_cstoresi_ltu_thumb1 (operands[0], op3, operands[2]));
7888
      break;
7889
 
7890
    /* No good sequences for GT, LT.  */
7891
    default:
7892
      FAIL;
7893
    }
7894
  DONE;
7895
}")
7896
 
7897
(define_expand "cstoresf4"
7898
  [(set (match_operand:SI 0 "s_register_operand" "")
7899
        (match_operator:SI 1 "expandable_comparison_operator"
7900
         [(match_operand:SF 2 "s_register_operand" "")
7901
          (match_operand:SF 3 "arm_float_compare_operand" "")]))]
7902
  "TARGET_32BIT && TARGET_HARD_FLOAT"
7903
  "emit_insn (gen_cstore_cc (operands[0], operands[1],
7904
                             operands[2], operands[3])); DONE;"
7905
)
7906
 
7907
(define_expand "cstoredf4"
7908
  [(set (match_operand:SI 0 "s_register_operand" "")
7909
        (match_operator:SI 1 "expandable_comparison_operator"
7910
         [(match_operand:DF 2 "s_register_operand" "")
7911
          (match_operand:DF 3 "arm_float_compare_operand" "")]))]
7912
  "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
7913
  "emit_insn (gen_cstore_cc (operands[0], operands[1],
7914
                             operands[2], operands[3])); DONE;"
7915
)
7916
 
7917
(define_expand "cstoredi4"
7918
  [(set (match_operand:SI 0 "s_register_operand" "")
7919
        (match_operator:SI 1 "expandable_comparison_operator"
7920
         [(match_operand:DI 2 "cmpdi_operand" "")
7921
          (match_operand:DI 3 "cmpdi_operand" "")]))]
7922
  "TARGET_32BIT"
7923
  "{
7924
     rtx swap = NULL_RTX;
7925
     enum rtx_code code = GET_CODE (operands[1]);
7926
 
7927
     /* We should not have two constants.  */
7928
     gcc_assert (GET_MODE (operands[2]) == DImode
7929
                 || GET_MODE (operands[3]) == DImode);
7930
 
7931
    /* Flip unimplemented DImode comparisons to a form that
7932
       arm_gen_compare_reg can handle.  */
7933
     switch (code)
7934
     {
7935
     case GT:
7936
       swap = gen_rtx_LT (VOIDmode, operands[3], operands[2]); break;
7937
     case LE:
7938
       swap = gen_rtx_GE (VOIDmode, operands[3], operands[2]); break;
7939
     case GTU:
7940
       swap = gen_rtx_LTU (VOIDmode, operands[3], operands[2]); break;
7941
     case LEU:
7942
       swap = gen_rtx_GEU (VOIDmode, operands[3], operands[2]); break;
7943
     default:
7944
       break;
7945
     }
7946
     if (swap)
7947
       emit_insn (gen_cstore_cc (operands[0], swap, operands[3],
7948
                                 operands[2]));
7949
     else
7950
       emit_insn (gen_cstore_cc (operands[0], operands[1], operands[2],
7951
                                 operands[3]));
7952
     DONE;
7953
   }"
7954
)
7955
 
7956
(define_expand "cstoresi_eq0_thumb1"
7957
  [(parallel
7958
    [(set (match_operand:SI 0 "s_register_operand" "")
7959
          (eq:SI (match_operand:SI 1 "s_register_operand" "")
7960
                 (const_int 0)))
7961
     (clobber (match_dup:SI 2))])]
7962
  "TARGET_THUMB1"
7963
  "operands[2] = gen_reg_rtx (SImode);"
7964
)
7965
 
7966
(define_expand "cstoresi_ne0_thumb1"
7967
  [(parallel
7968
    [(set (match_operand:SI 0 "s_register_operand" "")
7969
          (ne:SI (match_operand:SI 1 "s_register_operand" "")
7970
                 (const_int 0)))
7971
     (clobber (match_dup:SI 2))])]
7972
  "TARGET_THUMB1"
7973
  "operands[2] = gen_reg_rtx (SImode);"
7974
)
7975
 
7976
(define_insn "*cstoresi_eq0_thumb1_insn"
7977
  [(set (match_operand:SI 0 "s_register_operand" "=&l,l")
7978
        (eq:SI (match_operand:SI 1 "s_register_operand" "l,0")
7979
               (const_int 0)))
7980
   (clobber (match_operand:SI 2 "s_register_operand" "=X,l"))]
7981
  "TARGET_THUMB1"
7982
  "@
7983
   neg\\t%0, %1\;adc\\t%0, %0, %1
7984
   neg\\t%2, %1\;adc\\t%0, %1, %2"
7985
  [(set_attr "length" "4")]
7986
)
7987
 
7988
(define_insn "*cstoresi_ne0_thumb1_insn"
7989
  [(set (match_operand:SI 0 "s_register_operand" "=l")
7990
        (ne:SI (match_operand:SI 1 "s_register_operand" "0")
7991
               (const_int 0)))
7992
   (clobber (match_operand:SI 2 "s_register_operand" "=l"))]
7993
  "TARGET_THUMB1"
7994
  "sub\\t%2, %1, #1\;sbc\\t%0, %1, %2"
7995
  [(set_attr "length" "4")]
7996
)
7997
 
7998
;; Used as part of the expansion of thumb ltu and gtu sequences
7999
(define_insn "cstoresi_nltu_thumb1"
8000
  [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8001
        (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8002
                        (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
8003
  "TARGET_THUMB1"
8004
  "cmp\\t%1, %2\;sbc\\t%0, %0, %0"
8005
  [(set_attr "length" "4")]
8006
)
8007
 
8008
(define_insn_and_split "cstoresi_ltu_thumb1"
8009
  [(set (match_operand:SI 0 "s_register_operand" "=l,l")
8010
        (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
8011
                (match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r")))]
8012
  "TARGET_THUMB1"
8013
  "#"
8014
  "TARGET_THUMB1"
8015
  [(set (match_dup 3)
8016
        (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
8017
   (set (match_dup 0) (neg:SI (match_dup 3)))]
8018
  "operands[3] = gen_reg_rtx (SImode);"
8019
  [(set_attr "length" "4")]
8020
)
8021
 
8022
;; Used as part of the expansion of thumb les sequence.
8023
(define_insn "thumb1_addsi3_addgeu"
8024
  [(set (match_operand:SI 0 "s_register_operand" "=l")
8025
        (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8026
                          (match_operand:SI 2 "s_register_operand" "l"))
8027
                 (geu:SI (match_operand:SI 3 "s_register_operand" "l")
8028
                         (match_operand:SI 4 "thumb1_cmp_operand" "lI"))))]
8029
  "TARGET_THUMB1"
8030
  "cmp\\t%3, %4\;adc\\t%0, %1, %2"
8031
  [(set_attr "length" "4")]
8032
)
8033
 
8034
 
8035
;; Conditional move insns
8036
 
8037
(define_expand "movsicc"
8038
  [(set (match_operand:SI 0 "s_register_operand" "")
8039
        (if_then_else:SI (match_operand 1 "expandable_comparison_operator" "")
8040
                         (match_operand:SI 2 "arm_not_operand" "")
8041
                         (match_operand:SI 3 "arm_not_operand" "")))]
8042
  "TARGET_32BIT"
8043
  "
8044
  {
8045
    enum rtx_code code = GET_CODE (operands[1]);
8046
    rtx ccreg;
8047
 
8048
    if (code == UNEQ || code == LTGT)
8049
      FAIL;
8050
 
8051
    ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8052
                                 XEXP (operands[1], 1), NULL_RTX);
8053
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8054
  }"
8055
)
8056
 
8057
(define_expand "movsfcc"
8058
  [(set (match_operand:SF 0 "s_register_operand" "")
8059
        (if_then_else:SF (match_operand 1 "expandable_comparison_operator" "")
8060
                         (match_operand:SF 2 "s_register_operand" "")
8061
                         (match_operand:SF 3 "nonmemory_operand" "")))]
8062
  "TARGET_32BIT && TARGET_HARD_FLOAT"
8063
  "
8064
  {
8065
    enum rtx_code code = GET_CODE (operands[1]);
8066
    rtx ccreg;
8067
 
8068
    if (code == UNEQ || code == LTGT)
8069
      FAIL;
8070
 
8071
    /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
8072
       Otherwise, ensure it is a valid FP add operand */
8073
    if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
8074
        || (!arm_float_add_operand (operands[3], SFmode)))
8075
      operands[3] = force_reg (SFmode, operands[3]);
8076
 
8077
    ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8078
                                 XEXP (operands[1], 1), NULL_RTX);
8079
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8080
  }"
8081
)
8082
 
8083
(define_expand "movdfcc"
8084
  [(set (match_operand:DF 0 "s_register_operand" "")
8085
        (if_then_else:DF (match_operand 1 "expandable_comparison_operator" "")
8086
                         (match_operand:DF 2 "s_register_operand" "")
8087
                         (match_operand:DF 3 "arm_float_add_operand" "")))]
8088
  "TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
8089
  "
8090
  {
8091
    enum rtx_code code = GET_CODE (operands[1]);
8092
    rtx ccreg;
8093
 
8094
    if (code == UNEQ || code == LTGT)
8095
      FAIL;
8096
 
8097
    ccreg = arm_gen_compare_reg (code, XEXP (operands[1], 0),
8098
                                 XEXP (operands[1], 1), NULL_RTX);
8099
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
8100
  }"
8101
)
8102
 
8103
(define_insn "*movsicc_insn"
8104
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
8105
        (if_then_else:SI
8106
         (match_operator 3 "arm_comparison_operator"
8107
          [(match_operand 4 "cc_register" "") (const_int 0)])
8108
         (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
8109
         (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
8110
  "TARGET_ARM"
8111
  "@
8112
   mov%D3\\t%0, %2
8113
   mvn%D3\\t%0, #%B2
8114
   mov%d3\\t%0, %1
8115
   mvn%d3\\t%0, #%B1
8116
   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
8117
   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
8118
   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
8119
   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
8120
  [(set_attr "length" "4,4,4,4,8,8,8,8")
8121
   (set_attr "conds" "use")
8122
   (set_attr "insn" "mov,mvn,mov,mvn,mov,mov,mvn,mvn")]
8123
)
8124
 
8125
(define_insn "*movsfcc_soft_insn"
8126
  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
8127
        (if_then_else:SF (match_operator 3 "arm_comparison_operator"
8128
                          [(match_operand 4 "cc_register" "") (const_int 0)])
8129
                         (match_operand:SF 1 "s_register_operand" "0,r")
8130
                         (match_operand:SF 2 "s_register_operand" "r,0")))]
8131
  "TARGET_ARM && TARGET_SOFT_FLOAT"
8132
  "@
8133
   mov%D3\\t%0, %2
8134
   mov%d3\\t%0, %1"
8135
  [(set_attr "conds" "use")
8136
   (set_attr "insn" "mov")]
8137
)
8138
 
8139
 
8140
;; Jump and linkage insns
8141
 
8142
(define_expand "jump"
8143
  [(set (pc)
8144
        (label_ref (match_operand 0 "" "")))]
8145
  "TARGET_EITHER"
8146
  ""
8147
)
8148
 
8149
(define_insn "*arm_jump"
8150
  [(set (pc)
8151
        (label_ref (match_operand 0 "" "")))]
8152
  "TARGET_32BIT"
8153
  "*
8154
  {
8155
    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
8156
      {
8157
        arm_ccfsm_state += 2;
8158
        return \"\";
8159
      }
8160
    return \"b%?\\t%l0\";
8161
  }
8162
  "
8163
  [(set_attr "predicable" "yes")
8164
   (set (attr "length")
8165
        (if_then_else
8166
           (and (match_test "TARGET_THUMB2")
8167
                (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8168
                     (le (minus (match_dup 0) (pc)) (const_int 2048))))
8169
           (const_int 2)
8170
           (const_int 4)))]
8171
)
8172
 
8173
(define_insn "*thumb_jump"
8174
  [(set (pc)
8175
        (label_ref (match_operand 0 "" "")))]
8176
  "TARGET_THUMB1"
8177
  "*
8178
  if (get_attr_length (insn) == 2)
8179
    return \"b\\t%l0\";
8180
  return \"bl\\t%l0\\t%@ far jump\";
8181
  "
8182
  [(set (attr "far_jump")
8183
        (if_then_else
8184
            (eq_attr "length" "4")
8185
            (const_string "yes")
8186
            (const_string "no")))
8187
   (set (attr "length")
8188
        (if_then_else
8189
            (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
8190
                 (le (minus (match_dup 0) (pc)) (const_int 2048)))
8191
            (const_int 2)
8192
            (const_int 4)))]
8193
)
8194
 
8195
(define_expand "call"
8196
  [(parallel [(call (match_operand 0 "memory_operand" "")
8197
                    (match_operand 1 "general_operand" ""))
8198
              (use (match_operand 2 "" ""))
8199
              (clobber (reg:SI LR_REGNUM))])]
8200
  "TARGET_EITHER"
8201
  "
8202
  {
8203
    rtx callee, pat;
8204
 
8205
    /* In an untyped call, we can get NULL for operand 2.  */
8206
    if (operands[2] == NULL_RTX)
8207
      operands[2] = const0_rtx;
8208
 
8209
    /* Decide if we should generate indirect calls by loading the
8210
       32-bit address of the callee into a register before performing the
8211
       branch and link.  */
8212
    callee = XEXP (operands[0], 0);
8213
    if (GET_CODE (callee) == SYMBOL_REF
8214
        ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8215
        : !REG_P (callee))
8216
      XEXP (operands[0], 0) = force_reg (Pmode, callee);
8217
 
8218
    pat = gen_call_internal (operands[0], operands[1], operands[2]);
8219
    arm_emit_call_insn (pat, XEXP (operands[0], 0));
8220
    DONE;
8221
  }"
8222
)
8223
 
8224
(define_expand "call_internal"
8225
  [(parallel [(call (match_operand 0 "memory_operand" "")
8226
                    (match_operand 1 "general_operand" ""))
8227
              (use (match_operand 2 "" ""))
8228
              (clobber (reg:SI LR_REGNUM))])])
8229
 
8230
(define_insn "*call_reg_armv5"
8231
  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8232
         (match_operand 1 "" ""))
8233
   (use (match_operand 2 "" ""))
8234
   (clobber (reg:SI LR_REGNUM))]
8235
  "TARGET_ARM && arm_arch5"
8236
  "blx%?\\t%0"
8237
  [(set_attr "type" "call")]
8238
)
8239
 
8240
(define_insn "*call_reg_arm"
8241
  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
8242
         (match_operand 1 "" ""))
8243
   (use (match_operand 2 "" ""))
8244
   (clobber (reg:SI LR_REGNUM))]
8245
  "TARGET_ARM && !arm_arch5"
8246
  "*
8247
  return output_call (operands);
8248
  "
8249
  ;; length is worst case, normally it is only two
8250
  [(set_attr "length" "12")
8251
   (set_attr "type" "call")]
8252
)
8253
 
8254
 
8255
;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
8256
;; considered a function call by the branch predictor of some cores (PR40887).
8257
;; Falls back to blx rN (*call_reg_armv5).
8258
 
8259
(define_insn "*call_mem"
8260
  [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
8261
         (match_operand 1 "" ""))
8262
   (use (match_operand 2 "" ""))
8263
   (clobber (reg:SI LR_REGNUM))]
8264
  "TARGET_ARM && !arm_arch5"
8265
  "*
8266
  return output_call_mem (operands);
8267
  "
8268
  [(set_attr "length" "12")
8269
   (set_attr "type" "call")]
8270
)
8271
 
8272
(define_insn "*call_reg_thumb1_v5"
8273
  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8274
         (match_operand 1 "" ""))
8275
   (use (match_operand 2 "" ""))
8276
   (clobber (reg:SI LR_REGNUM))]
8277
  "TARGET_THUMB1 && arm_arch5"
8278
  "blx\\t%0"
8279
  [(set_attr "length" "2")
8280
   (set_attr "type" "call")]
8281
)
8282
 
8283
(define_insn "*call_reg_thumb1"
8284
  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
8285
         (match_operand 1 "" ""))
8286
   (use (match_operand 2 "" ""))
8287
   (clobber (reg:SI LR_REGNUM))]
8288
  "TARGET_THUMB1 && !arm_arch5"
8289
  "*
8290
  {
8291
    if (!TARGET_CALLER_INTERWORKING)
8292
      return thumb_call_via_reg (operands[0]);
8293
    else if (operands[1] == const0_rtx)
8294
      return \"bl\\t%__interwork_call_via_%0\";
8295
    else if (frame_pointer_needed)
8296
      return \"bl\\t%__interwork_r7_call_via_%0\";
8297
    else
8298
      return \"bl\\t%__interwork_r11_call_via_%0\";
8299
  }"
8300
  [(set_attr "type" "call")]
8301
)
8302
 
8303
(define_expand "call_value"
8304
  [(parallel [(set (match_operand       0 "" "")
8305
                   (call (match_operand 1 "memory_operand" "")
8306
                         (match_operand 2 "general_operand" "")))
8307
              (use (match_operand 3 "" ""))
8308
              (clobber (reg:SI LR_REGNUM))])]
8309
  "TARGET_EITHER"
8310
  "
8311
  {
8312
    rtx pat, callee;
8313
 
8314
    /* In an untyped call, we can get NULL for operand 2.  */
8315
    if (operands[3] == 0)
8316
      operands[3] = const0_rtx;
8317
 
8318
    /* Decide if we should generate indirect calls by loading the
8319
       32-bit address of the callee into a register before performing the
8320
       branch and link.  */
8321
    callee = XEXP (operands[1], 0);
8322
    if (GET_CODE (callee) == SYMBOL_REF
8323
        ? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
8324
        : !REG_P (callee))
8325
      XEXP (operands[1], 0) = force_reg (Pmode, callee);
8326
 
8327
    pat = gen_call_value_internal (operands[0], operands[1],
8328
                                   operands[2], operands[3]);
8329
    arm_emit_call_insn (pat, XEXP (operands[1], 0));
8330
    DONE;
8331
  }"
8332
)
8333
 
8334
(define_expand "call_value_internal"
8335
  [(parallel [(set (match_operand       0 "" "")
8336
                   (call (match_operand 1 "memory_operand" "")
8337
                         (match_operand 2 "general_operand" "")))
8338
              (use (match_operand 3 "" ""))
8339
              (clobber (reg:SI LR_REGNUM))])])
8340
 
8341
(define_insn "*call_value_reg_armv5"
8342
  [(set (match_operand 0 "" "")
8343
        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8344
              (match_operand 2 "" "")))
8345
   (use (match_operand 3 "" ""))
8346
   (clobber (reg:SI LR_REGNUM))]
8347
  "TARGET_ARM && arm_arch5"
8348
  "blx%?\\t%1"
8349
  [(set_attr "type" "call")]
8350
)
8351
 
8352
(define_insn "*call_value_reg_arm"
8353
  [(set (match_operand 0 "" "")
8354
        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
8355
              (match_operand 2 "" "")))
8356
   (use (match_operand 3 "" ""))
8357
   (clobber (reg:SI LR_REGNUM))]
8358
  "TARGET_ARM && !arm_arch5"
8359
  "*
8360
  return output_call (&operands[1]);
8361
  "
8362
  [(set_attr "length" "12")
8363
   (set_attr "type" "call")]
8364
)
8365
 
8366
;; Note: see *call_mem
8367
 
8368
(define_insn "*call_value_mem"
8369
  [(set (match_operand 0 "" "")
8370
        (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
8371
              (match_operand 2 "" "")))
8372
   (use (match_operand 3 "" ""))
8373
   (clobber (reg:SI LR_REGNUM))]
8374
  "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
8375
  "*
8376
  return output_call_mem (&operands[1]);
8377
  "
8378
  [(set_attr "length" "12")
8379
   (set_attr "type" "call")]
8380
)
8381
 
8382
(define_insn "*call_value_reg_thumb1_v5"
8383
  [(set (match_operand 0 "" "")
8384
        (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8385
              (match_operand 2 "" "")))
8386
   (use (match_operand 3 "" ""))
8387
   (clobber (reg:SI LR_REGNUM))]
8388
  "TARGET_THUMB1 && arm_arch5"
8389
  "blx\\t%1"
8390
  [(set_attr "length" "2")
8391
   (set_attr "type" "call")]
8392
)
8393
 
8394
(define_insn "*call_value_reg_thumb1"
8395
  [(set (match_operand 0 "" "")
8396
        (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
8397
              (match_operand 2 "" "")))
8398
   (use (match_operand 3 "" ""))
8399
   (clobber (reg:SI LR_REGNUM))]
8400
  "TARGET_THUMB1 && !arm_arch5"
8401
  "*
8402
  {
8403
    if (!TARGET_CALLER_INTERWORKING)
8404
      return thumb_call_via_reg (operands[1]);
8405
    else if (operands[2] == const0_rtx)
8406
      return \"bl\\t%__interwork_call_via_%1\";
8407
    else if (frame_pointer_needed)
8408
      return \"bl\\t%__interwork_r7_call_via_%1\";
8409
    else
8410
      return \"bl\\t%__interwork_r11_call_via_%1\";
8411
  }"
8412
  [(set_attr "type" "call")]
8413
)
8414
 
8415
;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
8416
;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
8417
 
8418
(define_insn "*call_symbol"
8419
  [(call (mem:SI (match_operand:SI 0 "" ""))
8420
         (match_operand 1 "" ""))
8421
   (use (match_operand 2 "" ""))
8422
   (clobber (reg:SI LR_REGNUM))]
8423
  "TARGET_32BIT
8424
   && (GET_CODE (operands[0]) == SYMBOL_REF)
8425
   && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8426
  "*
8427
  {
8428
    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
8429
  }"
8430
  [(set_attr "type" "call")]
8431
)
8432
 
8433
(define_insn "*call_value_symbol"
8434
  [(set (match_operand 0 "" "")
8435
        (call (mem:SI (match_operand:SI 1 "" ""))
8436
        (match_operand:SI 2 "" "")))
8437
   (use (match_operand 3 "" ""))
8438
   (clobber (reg:SI LR_REGNUM))]
8439
  "TARGET_32BIT
8440
   && (GET_CODE (operands[1]) == SYMBOL_REF)
8441
   && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8442
  "*
8443
  {
8444
    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
8445
  }"
8446
  [(set_attr "type" "call")]
8447
)
8448
 
8449
(define_insn "*call_insn"
8450
  [(call (mem:SI (match_operand:SI 0 "" ""))
8451
         (match_operand:SI 1 "" ""))
8452
   (use (match_operand 2 "" ""))
8453
   (clobber (reg:SI LR_REGNUM))]
8454
  "TARGET_THUMB1
8455
   && GET_CODE (operands[0]) == SYMBOL_REF
8456
   && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))"
8457
  "bl\\t%a0"
8458
  [(set_attr "length" "4")
8459
   (set_attr "type" "call")]
8460
)
8461
 
8462
(define_insn "*call_value_insn"
8463
  [(set (match_operand 0 "" "")
8464
        (call (mem:SI (match_operand 1 "" ""))
8465
              (match_operand 2 "" "")))
8466
   (use (match_operand 3 "" ""))
8467
   (clobber (reg:SI LR_REGNUM))]
8468
  "TARGET_THUMB1
8469
   && GET_CODE (operands[1]) == SYMBOL_REF
8470
   && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))"
8471
  "bl\\t%a1"
8472
  [(set_attr "length" "4")
8473
   (set_attr "type" "call")]
8474
)
8475
 
8476
;; We may also be able to do sibcalls for Thumb, but it's much harder...
8477
(define_expand "sibcall"
8478
  [(parallel [(call (match_operand 0 "memory_operand" "")
8479
                    (match_operand 1 "general_operand" ""))
8480
              (return)
8481
              (use (match_operand 2 "" ""))])]
8482
  "TARGET_32BIT"
8483
  "
8484
  {
8485
    if (operands[2] == NULL_RTX)
8486
      operands[2] = const0_rtx;
8487
  }"
8488
)
8489
 
8490
(define_expand "sibcall_value"
8491
  [(parallel [(set (match_operand 0 "" "")
8492
                   (call (match_operand 1 "memory_operand" "")
8493
                         (match_operand 2 "general_operand" "")))
8494
              (return)
8495
              (use (match_operand 3 "" ""))])]
8496
  "TARGET_32BIT"
8497
  "
8498
  {
8499
    if (operands[3] == NULL_RTX)
8500
      operands[3] = const0_rtx;
8501
  }"
8502
)
8503
 
8504
(define_insn "*sibcall_insn"
8505
 [(call (mem:SI (match_operand:SI 0 "" "X"))
8506
        (match_operand 1 "" ""))
8507
  (return)
8508
  (use (match_operand 2 "" ""))]
8509
  "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF"
8510
  "*
8511
  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
8512
  "
8513
  [(set_attr "type" "call")]
8514
)
8515
 
8516
(define_insn "*sibcall_value_insn"
8517
 [(set (match_operand 0 "" "")
8518
       (call (mem:SI (match_operand:SI 1 "" "X"))
8519
             (match_operand 2 "" "")))
8520
  (return)
8521
  (use (match_operand 3 "" ""))]
8522
  "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF"
8523
  "*
8524
  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
8525
  "
8526
  [(set_attr "type" "call")]
8527
)
8528
 
8529
(define_expand "return"
8530
  [(return)]
8531
  "TARGET_32BIT && USE_RETURN_INSN (FALSE)"
8532
  "")
8533
 
8534
;; Often the return insn will be the same as loading from memory, so set attr
8535
(define_insn "*arm_return"
8536
  [(return)]
8537
  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
8538
  "*
8539
  {
8540
    if (arm_ccfsm_state == 2)
8541
      {
8542
        arm_ccfsm_state += 2;
8543
        return \"\";
8544
      }
8545
    return output_return_instruction (const_true_rtx, TRUE, FALSE);
8546
  }"
8547
  [(set_attr "type" "load1")
8548
   (set_attr "length" "12")
8549
   (set_attr "predicable" "yes")]
8550
)
8551
 
8552
(define_insn "*cond_return"
8553
  [(set (pc)
8554
        (if_then_else (match_operator 0 "arm_comparison_operator"
8555
                       [(match_operand 1 "cc_register" "") (const_int 0)])
8556
                      (return)
8557
                      (pc)))]
8558
  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8559
  "*
8560
  {
8561
    if (arm_ccfsm_state == 2)
8562
      {
8563
        arm_ccfsm_state += 2;
8564
        return \"\";
8565
      }
8566
    return output_return_instruction (operands[0], TRUE, FALSE);
8567
  }"
8568
  [(set_attr "conds" "use")
8569
   (set_attr "length" "12")
8570
   (set_attr "type" "load1")]
8571
)
8572
 
8573
(define_insn "*cond_return_inverted"
8574
  [(set (pc)
8575
        (if_then_else (match_operator 0 "arm_comparison_operator"
8576
                       [(match_operand 1 "cc_register" "") (const_int 0)])
8577
                      (pc)
8578
                      (return)))]
8579
  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
8580
  "*
8581
  {
8582
    if (arm_ccfsm_state == 2)
8583
      {
8584
        arm_ccfsm_state += 2;
8585
        return \"\";
8586
      }
8587
    return output_return_instruction (operands[0], TRUE, TRUE);
8588
  }"
8589
  [(set_attr "conds" "use")
8590
   (set_attr "length" "12")
8591
   (set_attr "type" "load1")]
8592
)
8593
 
8594
;; Generate a sequence of instructions to determine if the processor is
8595
;; in 26-bit or 32-bit mode, and return the appropriate return address
8596
;; mask.
8597
 
8598
(define_expand "return_addr_mask"
8599
  [(set (match_dup 1)
8600
      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8601
                       (const_int 0)))
8602
   (set (match_operand:SI 0 "s_register_operand" "")
8603
      (if_then_else:SI (eq (match_dup 1) (const_int 0))
8604
                       (const_int -1)
8605
                       (const_int 67108860)))] ; 0x03fffffc
8606
  "TARGET_ARM"
8607
  "
8608
  operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
8609
  ")
8610
 
8611
(define_insn "*check_arch2"
8612
  [(set (match_operand:CC_NOOV 0 "cc_register" "")
8613
      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8614
                       (const_int 0)))]
8615
  "TARGET_ARM"
8616
  "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8617
  [(set_attr "length" "8")
8618
   (set_attr "conds" "set")]
8619
)
8620
 
8621
;; Call subroutine returning any type.
8622
 
8623
(define_expand "untyped_call"
8624
  [(parallel [(call (match_operand 0 "" "")
8625
                    (const_int 0))
8626
              (match_operand 1 "" "")
8627
              (match_operand 2 "" "")])]
8628
  "TARGET_EITHER"
8629
  "
8630
  {
8631
    int i;
8632
    rtx par = gen_rtx_PARALLEL (VOIDmode,
8633
                                rtvec_alloc (XVECLEN (operands[2], 0)));
8634
    rtx addr = gen_reg_rtx (Pmode);
8635
    rtx mem;
8636
    int size = 0;
8637
 
8638
    emit_move_insn (addr, XEXP (operands[1], 0));
8639
    mem = change_address (operands[1], BLKmode, addr);
8640
 
8641
    for (i = 0; i < XVECLEN (operands[2], 0); i++)
8642
      {
8643
        rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8644
 
8645
        /* Default code only uses r0 as a return value, but we could
8646
           be using anything up to 4 registers.  */
8647
        if (REGNO (src) == R0_REGNUM)
8648
          src = gen_rtx_REG (TImode, R0_REGNUM);
8649
 
8650
        XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8651
                                                 GEN_INT (size));
8652
        size += GET_MODE_SIZE (GET_MODE (src));
8653
      }
8654
 
8655
    emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8656
                                    const0_rtx));
8657
 
8658
    size = 0;
8659
 
8660
    for (i = 0; i < XVECLEN (par, 0); i++)
8661
      {
8662
        HOST_WIDE_INT offset = 0;
8663
        rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8664
 
8665
        if (size != 0)
8666
          emit_move_insn (addr, plus_constant (addr, size));
8667
 
8668
        mem = change_address (mem, GET_MODE (reg), NULL);
8669
        if (REGNO (reg) == R0_REGNUM)
8670
          {
8671
            /* On thumb we have to use a write-back instruction.  */
8672
            emit_insn (arm_gen_store_multiple (arm_regs_in_sequence, 4, addr,
8673
                       TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8674
            size = TARGET_ARM ? 16 : 0;
8675
          }
8676
        else
8677
          {
8678
            emit_move_insn (mem, reg);
8679
            size = GET_MODE_SIZE (GET_MODE (reg));
8680
          }
8681
      }
8682
 
8683
    /* The optimizer does not know that the call sets the function value
8684
       registers we stored in the result block.  We avoid problems by
8685
       claiming that all hard registers are used and clobbered at this
8686
       point.  */
8687
    emit_insn (gen_blockage ());
8688
 
8689
    DONE;
8690
  }"
8691
)
8692
 
8693
(define_expand "untyped_return"
8694
  [(match_operand:BLK 0 "memory_operand" "")
8695
   (match_operand 1 "" "")]
8696
  "TARGET_EITHER"
8697
  "
8698
  {
8699
    int i;
8700
    rtx addr = gen_reg_rtx (Pmode);
8701
    rtx mem;
8702
    int size = 0;
8703
 
8704
    emit_move_insn (addr, XEXP (operands[0], 0));
8705
    mem = change_address (operands[0], BLKmode, addr);
8706
 
8707
    for (i = 0; i < XVECLEN (operands[1], 0); i++)
8708
      {
8709
        HOST_WIDE_INT offset = 0;
8710
        rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8711
 
8712
        if (size != 0)
8713
          emit_move_insn (addr, plus_constant (addr, size));
8714
 
8715
        mem = change_address (mem, GET_MODE (reg), NULL);
8716
        if (REGNO (reg) == R0_REGNUM)
8717
          {
8718
            /* On thumb we have to use a write-back instruction.  */
8719
            emit_insn (arm_gen_load_multiple (arm_regs_in_sequence, 4, addr,
8720
                       TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8721
            size = TARGET_ARM ? 16 : 0;
8722
          }
8723
        else
8724
          {
8725
            emit_move_insn (reg, mem);
8726
            size = GET_MODE_SIZE (GET_MODE (reg));
8727
          }
8728
      }
8729
 
8730
    /* Emit USE insns before the return.  */
8731
    for (i = 0; i < XVECLEN (operands[1], 0); i++)
8732
      emit_use (SET_DEST (XVECEXP (operands[1], 0, i)));
8733
 
8734
    /* Construct the return.  */
8735
    expand_naked_return ();
8736
 
8737
    DONE;
8738
  }"
8739
)
8740
 
8741
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8742
;; all of memory.  This blocks insns from being moved across this point.
8743
 
8744
(define_insn "blockage"
8745
  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8746
  "TARGET_EITHER"
8747
  ""
8748
  [(set_attr "length" "0")
8749
   (set_attr "type" "block")]
8750
)
8751
 
8752
(define_expand "casesi"
8753
  [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8754
   (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8755
   (match_operand:SI 2 "const_int_operand" "")  ; total range
8756
   (match_operand:SI 3 "" "")                   ; table label
8757
   (match_operand:SI 4 "" "")]                  ; Out of range label
8758
  "TARGET_32BIT || optimize_size || flag_pic"
8759
  "
8760
  {
8761
    enum insn_code code;
8762
    if (operands[1] != const0_rtx)
8763
      {
8764
        rtx reg = gen_reg_rtx (SImode);
8765
 
8766
        emit_insn (gen_addsi3 (reg, operands[0],
8767
                               gen_int_mode (-INTVAL (operands[1]),
8768
                                             SImode)));
8769
        operands[0] = reg;
8770
      }
8771
 
8772
    if (TARGET_ARM)
8773
      code = CODE_FOR_arm_casesi_internal;
8774
    else if (TARGET_THUMB1)
8775
      code = CODE_FOR_thumb1_casesi_internal_pic;
8776
    else if (flag_pic)
8777
      code = CODE_FOR_thumb2_casesi_internal_pic;
8778
    else
8779
      code = CODE_FOR_thumb2_casesi_internal;
8780
 
8781
    if (!insn_data[(int) code].operand[1].predicate(operands[2], SImode))
8782
      operands[2] = force_reg (SImode, operands[2]);
8783
 
8784
    emit_jump_insn (GEN_FCN ((int) code) (operands[0], operands[2],
8785
                                          operands[3], operands[4]));
8786
    DONE;
8787
  }"
8788
)
8789
 
8790
;; The USE in this pattern is needed to tell flow analysis that this is
8791
;; a CASESI insn.  It has no other purpose.
8792
(define_insn "arm_casesi_internal"
8793
  [(parallel [(set (pc)
8794
               (if_then_else
8795
                (leu (match_operand:SI 0 "s_register_operand" "r")
8796
                     (match_operand:SI 1 "arm_rhs_operand" "rI"))
8797
                (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8798
                                 (label_ref (match_operand 2 "" ""))))
8799
                (label_ref (match_operand 3 "" ""))))
8800
              (clobber (reg:CC CC_REGNUM))
8801
              (use (label_ref (match_dup 2)))])]
8802
  "TARGET_ARM"
8803
  "*
8804
    if (flag_pic)
8805
      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8806
    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8807
  "
8808
  [(set_attr "conds" "clob")
8809
   (set_attr "length" "12")]
8810
)
8811
 
8812
(define_expand "thumb1_casesi_internal_pic"
8813
  [(match_operand:SI 0 "s_register_operand" "")
8814
   (match_operand:SI 1 "thumb1_cmp_operand" "")
8815
   (match_operand 2 "" "")
8816
   (match_operand 3 "" "")]
8817
  "TARGET_THUMB1"
8818
  {
8819
    rtx reg0;
8820
    rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[1]);
8821
    emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[1],
8822
                                    operands[3]));
8823
    reg0 = gen_rtx_REG (SImode, 0);
8824
    emit_move_insn (reg0, operands[0]);
8825
    emit_jump_insn (gen_thumb1_casesi_dispatch (operands[2]/*, operands[3]*/));
8826
    DONE;
8827
  }
8828
)
8829
 
8830
(define_insn "thumb1_casesi_dispatch"
8831
  [(parallel [(set (pc) (unspec [(reg:SI 0)
8832
                                 (label_ref (match_operand 0 "" ""))
8833
;;                               (label_ref (match_operand 1 "" ""))
8834
]
8835
                         UNSPEC_THUMB1_CASESI))
8836
              (clobber (reg:SI IP_REGNUM))
8837
              (clobber (reg:SI LR_REGNUM))])]
8838
  "TARGET_THUMB1"
8839
  "* return thumb1_output_casesi(operands);"
8840
  [(set_attr "length" "4")]
8841
)
8842
 
8843
(define_expand "indirect_jump"
8844
  [(set (pc)
8845
        (match_operand:SI 0 "s_register_operand" ""))]
8846
  "TARGET_EITHER"
8847
  "
8848
  /* Thumb-2 doesn't have mov pc, reg.  Explicitly set the low bit of the
8849
     address and use bx.  */
8850
  if (TARGET_THUMB2)
8851
    {
8852
      rtx tmp;
8853
      tmp = gen_reg_rtx (SImode);
8854
      emit_insn (gen_iorsi3 (tmp, operands[0], GEN_INT(1)));
8855
      operands[0] = tmp;
8856
    }
8857
  "
8858
)
8859
 
8860
;; NB Never uses BX.
8861
(define_insn "*arm_indirect_jump"
8862
  [(set (pc)
8863
        (match_operand:SI 0 "s_register_operand" "r"))]
8864
  "TARGET_ARM"
8865
  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8866
  [(set_attr "predicable" "yes")]
8867
)
8868
 
8869
(define_insn "*load_indirect_jump"
8870
  [(set (pc)
8871
        (match_operand:SI 0 "memory_operand" "m"))]
8872
  "TARGET_ARM"
8873
  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8874
  [(set_attr "type" "load1")
8875
   (set_attr "pool_range" "4096")
8876
   (set_attr "neg_pool_range" "4084")
8877
   (set_attr "predicable" "yes")]
8878
)
8879
 
8880
;; NB Never uses BX.
8881
(define_insn "*thumb1_indirect_jump"
8882
  [(set (pc)
8883
        (match_operand:SI 0 "register_operand" "l*r"))]
8884
  "TARGET_THUMB1"
8885
  "mov\\tpc, %0"
8886
  [(set_attr "conds" "clob")
8887
   (set_attr "length" "2")]
8888
)
8889
 
8890
 
8891
;; Misc insns
8892
 
8893
(define_insn "nop"
8894
  [(const_int 0)]
8895
  "TARGET_EITHER"
8896
  "*
8897
  if (TARGET_UNIFIED_ASM)
8898
    return \"nop\";
8899
  if (TARGET_ARM)
8900
    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8901
  return  \"mov\\tr8, r8\";
8902
  "
8903
  [(set (attr "length")
8904
        (if_then_else (eq_attr "is_thumb" "yes")
8905
                      (const_int 2)
8906
                      (const_int 4)))]
8907
)
8908
 
8909
 
8910
;; Patterns to allow combination of arithmetic, cond code and shifts
8911
 
8912
(define_insn "*arith_shiftsi"
8913
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8914
        (match_operator:SI 1 "shiftable_operator"
8915
          [(match_operator:SI 3 "shift_operator"
8916
             [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
8917
              (match_operand:SI 5 "shift_amount_operand" "M,M,M,r")])
8918
           (match_operand:SI 2 "s_register_operand" "rk,rk,r,rk")]))]
8919
  "TARGET_32BIT"
8920
  "%i1%?\\t%0, %2, %4%S3"
8921
  [(set_attr "predicable" "yes")
8922
   (set_attr "shift" "4")
8923
   (set_attr "arch" "a,t2,t2,a")
8924
   ;; Thumb2 doesn't allow the stack pointer to be used for
8925
   ;; operand1 for all operations other than add and sub. In this case
8926
   ;; the minus operation is a candidate for an rsub and hence needs
8927
   ;; to be disabled.
8928
   ;; We have to make sure to disable the fourth alternative if
8929
   ;; the shift_operator is MULT, since otherwise the insn will
8930
   ;; also match a multiply_accumulate pattern and validate_change
8931
   ;; will allow a replacement of the constant with a register
8932
   ;; despite the checks done in shift_operator.
8933
   (set_attr_alternative "insn_enabled"
8934
                         [(const_string "yes")
8935
                          (if_then_else
8936
                           (match_operand:SI 1 "add_operator" "")
8937
                           (const_string "yes") (const_string "no"))
8938
                          (const_string "yes")
8939
                          (if_then_else
8940
                           (match_operand:SI 3 "mult_operator" "")
8941
                           (const_string "no") (const_string "yes"))])
8942
   (set_attr "type" "alu_shift,alu_shift,alu_shift,alu_shift_reg")])
8943
 
8944
(define_split
8945
  [(set (match_operand:SI 0 "s_register_operand" "")
8946
        (match_operator:SI 1 "shiftable_operator"
8947
         [(match_operator:SI 2 "shiftable_operator"
8948
           [(match_operator:SI 3 "shift_operator"
8949
             [(match_operand:SI 4 "s_register_operand" "")
8950
              (match_operand:SI 5 "reg_or_int_operand" "")])
8951
            (match_operand:SI 6 "s_register_operand" "")])
8952
          (match_operand:SI 7 "arm_rhs_operand" "")]))
8953
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
8954
  "TARGET_32BIT"
8955
  [(set (match_dup 8)
8956
        (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8957
                         (match_dup 6)]))
8958
   (set (match_dup 0)
8959
        (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8960
  "")
8961
 
8962
(define_insn "*arith_shiftsi_compare0"
8963
  [(set (reg:CC_NOOV CC_REGNUM)
8964
        (compare:CC_NOOV
8965
         (match_operator:SI 1 "shiftable_operator"
8966
          [(match_operator:SI 3 "shift_operator"
8967
            [(match_operand:SI 4 "s_register_operand" "r,r")
8968
             (match_operand:SI 5 "shift_amount_operand" "M,r")])
8969
           (match_operand:SI 2 "s_register_operand" "r,r")])
8970
         (const_int 0)))
8971
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
8972
        (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8973
                         (match_dup 2)]))]
8974
  "TARGET_32BIT"
8975
  "%i1%.\\t%0, %2, %4%S3"
8976
  [(set_attr "conds" "set")
8977
   (set_attr "shift" "4")
8978
   (set_attr "arch" "32,a")
8979
   (set_attr "type" "alu_shift,alu_shift_reg")])
8980
 
8981
(define_insn "*arith_shiftsi_compare0_scratch"
8982
  [(set (reg:CC_NOOV CC_REGNUM)
8983
        (compare:CC_NOOV
8984
         (match_operator:SI 1 "shiftable_operator"
8985
          [(match_operator:SI 3 "shift_operator"
8986
            [(match_operand:SI 4 "s_register_operand" "r,r")
8987
             (match_operand:SI 5 "shift_amount_operand" "M,r")])
8988
           (match_operand:SI 2 "s_register_operand" "r,r")])
8989
         (const_int 0)))
8990
   (clobber (match_scratch:SI 0 "=r,r"))]
8991
  "TARGET_32BIT"
8992
  "%i1%.\\t%0, %2, %4%S3"
8993
  [(set_attr "conds" "set")
8994
   (set_attr "shift" "4")
8995
   (set_attr "arch" "32,a")
8996
   (set_attr "type" "alu_shift,alu_shift_reg")])
8997
 
8998
(define_insn "*sub_shiftsi"
8999
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9000
        (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9001
                  (match_operator:SI 2 "shift_operator"
9002
                   [(match_operand:SI 3 "s_register_operand" "r,r")
9003
                    (match_operand:SI 4 "shift_amount_operand" "M,r")])))]
9004
  "TARGET_32BIT"
9005
  "sub%?\\t%0, %1, %3%S2"
9006
  [(set_attr "predicable" "yes")
9007
   (set_attr "shift" "3")
9008
   (set_attr "arch" "32,a")
9009
   (set_attr "type" "alu_shift,alu_shift_reg")])
9010
 
9011
(define_insn "*sub_shiftsi_compare0"
9012
  [(set (reg:CC_NOOV CC_REGNUM)
9013
        (compare:CC_NOOV
9014
         (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9015
                   (match_operator:SI 2 "shift_operator"
9016
                    [(match_operand:SI 3 "s_register_operand" "r,r")
9017
                     (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
9018
         (const_int 0)))
9019
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
9020
        (minus:SI (match_dup 1)
9021
                  (match_op_dup 2 [(match_dup 3) (match_dup 4)])))]
9022
  "TARGET_32BIT"
9023
  "sub%.\\t%0, %1, %3%S2"
9024
  [(set_attr "conds" "set")
9025
   (set_attr "shift" "3")
9026
   (set_attr "arch" "32,a")
9027
   (set_attr "type" "alu_shift,alu_shift_reg")])
9028
 
9029
(define_insn "*sub_shiftsi_compare0_scratch"
9030
  [(set (reg:CC_NOOV CC_REGNUM)
9031
        (compare:CC_NOOV
9032
         (minus:SI (match_operand:SI 1 "s_register_operand" "r,r")
9033
                   (match_operator:SI 2 "shift_operator"
9034
                    [(match_operand:SI 3 "s_register_operand" "r,r")
9035
                     (match_operand:SI 4 "shift_amount_operand" "M,rM")]))
9036
         (const_int 0)))
9037
   (clobber (match_scratch:SI 0 "=r,r"))]
9038
  "TARGET_32BIT"
9039
  "sub%.\\t%0, %1, %3%S2"
9040
  [(set_attr "conds" "set")
9041
   (set_attr "shift" "3")
9042
   (set_attr "arch" "32,a")
9043
   (set_attr "type" "alu_shift,alu_shift_reg")])
9044
 
9045
 
9046
(define_insn "*and_scc"
9047
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9048
        (and:SI (match_operator:SI 1 "arm_comparison_operator"
9049
                 [(match_operand 3 "cc_register" "") (const_int 0)])
9050
                (match_operand:SI 2 "s_register_operand" "r")))]
9051
  "TARGET_ARM"
9052
  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
9053
  [(set_attr "conds" "use")
9054
   (set_attr "insn" "mov")
9055
   (set_attr "length" "8")]
9056
)
9057
 
9058
(define_insn "*ior_scc"
9059
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9060
        (ior:SI (match_operator:SI 2 "arm_comparison_operator"
9061
                 [(match_operand 3 "cc_register" "") (const_int 0)])
9062
                (match_operand:SI 1 "s_register_operand" "0,?r")))]
9063
  "TARGET_ARM"
9064
  "@
9065
   orr%d2\\t%0, %1, #1
9066
   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
9067
  [(set_attr "conds" "use")
9068
   (set_attr "length" "4,8")]
9069
)
9070
 
9071
; A series of splitters for the compare_scc pattern below.  Note that
9072
; order is important.
9073
(define_split
9074
  [(set (match_operand:SI 0 "s_register_operand" "")
9075
        (lt:SI (match_operand:SI 1 "s_register_operand" "")
9076
               (const_int 0)))
9077
   (clobber (reg:CC CC_REGNUM))]
9078
  "TARGET_32BIT && reload_completed"
9079
  [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (const_int 31)))])
9080
 
9081
(define_split
9082
  [(set (match_operand:SI 0 "s_register_operand" "")
9083
        (ge:SI (match_operand:SI 1 "s_register_operand" "")
9084
               (const_int 0)))
9085
   (clobber (reg:CC CC_REGNUM))]
9086
  "TARGET_32BIT && reload_completed"
9087
  [(set (match_dup 0) (not:SI (match_dup 1)))
9088
   (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 31)))])
9089
 
9090
(define_split
9091
  [(set (match_operand:SI 0 "s_register_operand" "")
9092
        (eq:SI (match_operand:SI 1 "s_register_operand" "")
9093
               (const_int 0)))
9094
   (clobber (reg:CC CC_REGNUM))]
9095
  "TARGET_32BIT && reload_completed"
9096
  [(parallel
9097
    [(set (reg:CC CC_REGNUM)
9098
          (compare:CC (const_int 1) (match_dup 1)))
9099
     (set (match_dup 0)
9100
          (minus:SI (const_int 1) (match_dup 1)))])
9101
   (cond_exec (ltu:CC (reg:CC CC_REGNUM) (const_int 0))
9102
              (set (match_dup 0) (const_int 0)))])
9103
 
9104
(define_split
9105
  [(set (match_operand:SI 0 "s_register_operand" "")
9106
        (ne:SI (match_operand:SI 1 "s_register_operand" "")
9107
               (match_operand:SI 2 "const_int_operand" "")))
9108
   (clobber (reg:CC CC_REGNUM))]
9109
  "TARGET_32BIT && reload_completed"
9110
  [(parallel
9111
    [(set (reg:CC CC_REGNUM)
9112
          (compare:CC (match_dup 1) (match_dup 2)))
9113
     (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))])
9114
   (cond_exec (ne:CC (reg:CC CC_REGNUM) (const_int 0))
9115
              (set (match_dup 0) (const_int 1)))]
9116
{
9117
  operands[3] = GEN_INT (-INTVAL (operands[2]));
9118
})
9119
 
9120
(define_split
9121
  [(set (match_operand:SI 0 "s_register_operand" "")
9122
        (ne:SI (match_operand:SI 1 "s_register_operand" "")
9123
               (match_operand:SI 2 "arm_add_operand" "")))
9124
   (clobber (reg:CC CC_REGNUM))]
9125
  "TARGET_32BIT && reload_completed"
9126
  [(parallel
9127
    [(set (reg:CC_NOOV CC_REGNUM)
9128
          (compare:CC_NOOV (minus:SI (match_dup 1) (match_dup 2))
9129
                           (const_int 0)))
9130
     (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2)))])
9131
   (cond_exec (ne:CC_NOOV (reg:CC_NOOV CC_REGNUM) (const_int 0))
9132
              (set (match_dup 0) (const_int 1)))])
9133
 
9134
(define_insn_and_split "*compare_scc"
9135
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9136
        (match_operator:SI 1 "arm_comparison_operator"
9137
         [(match_operand:SI 2 "s_register_operand" "r,r")
9138
          (match_operand:SI 3 "arm_add_operand" "rI,L")]))
9139
   (clobber (reg:CC CC_REGNUM))]
9140
  "TARGET_32BIT"
9141
  "#"
9142
  "&& reload_completed"
9143
  [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 3)))
9144
   (cond_exec (match_dup 4) (set (match_dup 0) (const_int 0)))
9145
   (cond_exec (match_dup 5) (set (match_dup 0) (const_int 1)))]
9146
{
9147
  rtx tmp1;
9148
  enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9149
                                           operands[2], operands[3]);
9150
  enum rtx_code rc = GET_CODE (operands[1]);
9151
 
9152
  tmp1 = gen_rtx_REG (mode, CC_REGNUM);
9153
 
9154
  operands[5] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9155
  if (mode == CCFPmode || mode == CCFPEmode)
9156
    rc = reverse_condition_maybe_unordered (rc);
9157
  else
9158
    rc = reverse_condition (rc);
9159
  operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, tmp1, const0_rtx);
9160
})
9161
 
9162
;; Attempt to improve the sequence generated by the compare_scc splitters
9163
;; not to use conditional execution.
9164
(define_peephole2
9165
  [(set (reg:CC CC_REGNUM)
9166
        (compare:CC (match_operand:SI 1 "register_operand" "")
9167
                    (match_operand:SI 2 "arm_rhs_operand" "")))
9168
   (cond_exec (ne (reg:CC CC_REGNUM) (const_int 0))
9169
              (set (match_operand:SI 0 "register_operand" "") (const_int 0)))
9170
   (cond_exec (eq (reg:CC CC_REGNUM) (const_int 0))
9171
              (set (match_dup 0) (const_int 1)))
9172
   (match_scratch:SI 3 "r")]
9173
  "TARGET_32BIT"
9174
  [(parallel
9175
    [(set (reg:CC CC_REGNUM)
9176
          (compare:CC (match_dup 1) (match_dup 2)))
9177
     (set (match_dup 3) (minus:SI (match_dup 1) (match_dup 2)))])
9178
   (parallel
9179
    [(set (reg:CC CC_REGNUM)
9180
          (compare:CC (const_int 0) (match_dup 3)))
9181
     (set (match_dup 0) (minus:SI (const_int 0) (match_dup 3)))])
9182
   (parallel
9183
    [(set (match_dup 0)
9184
          (plus:SI (plus:SI (match_dup 0) (match_dup 3))
9185
                   (geu:SI (reg:CC CC_REGNUM) (const_int 0))))
9186
     (clobber (reg:CC CC_REGNUM))])])
9187
 
9188
(define_insn "*cond_move"
9189
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9190
        (if_then_else:SI (match_operator 3 "equality_operator"
9191
                          [(match_operator 4 "arm_comparison_operator"
9192
                            [(match_operand 5 "cc_register" "") (const_int 0)])
9193
                           (const_int 0)])
9194
                         (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9195
                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
9196
  "TARGET_ARM"
9197
  "*
9198
    if (GET_CODE (operands[3]) == NE)
9199
      {
9200
        if (which_alternative != 1)
9201
          output_asm_insn (\"mov%D4\\t%0, %2\", operands);
9202
        if (which_alternative != 0)
9203
          output_asm_insn (\"mov%d4\\t%0, %1\", operands);
9204
        return \"\";
9205
      }
9206
    if (which_alternative != 0)
9207
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9208
    if (which_alternative != 1)
9209
      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
9210
    return \"\";
9211
  "
9212
  [(set_attr "conds" "use")
9213
   (set_attr "insn" "mov")
9214
   (set_attr "length" "4,4,8")]
9215
)
9216
 
9217
(define_insn "*cond_arith"
9218
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9219
        (match_operator:SI 5 "shiftable_operator"
9220
         [(match_operator:SI 4 "arm_comparison_operator"
9221
           [(match_operand:SI 2 "s_register_operand" "r,r")
9222
            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9223
          (match_operand:SI 1 "s_register_operand" "0,?r")]))
9224
   (clobber (reg:CC CC_REGNUM))]
9225
  "TARGET_ARM"
9226
  "*
9227
    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
9228
      return \"%i5\\t%0, %1, %2, lsr #31\";
9229
 
9230
    output_asm_insn (\"cmp\\t%2, %3\", operands);
9231
    if (GET_CODE (operands[5]) == AND)
9232
      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
9233
    else if (GET_CODE (operands[5]) == MINUS)
9234
      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
9235
    else if (which_alternative != 0)
9236
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9237
    return \"%i5%d4\\t%0, %1, #1\";
9238
  "
9239
  [(set_attr "conds" "clob")
9240
   (set_attr "length" "12")]
9241
)
9242
 
9243
(define_insn "*cond_sub"
9244
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9245
        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
9246
                  (match_operator:SI 4 "arm_comparison_operator"
9247
                   [(match_operand:SI 2 "s_register_operand" "r,r")
9248
                    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9249
   (clobber (reg:CC CC_REGNUM))]
9250
  "TARGET_ARM"
9251
  "*
9252
    output_asm_insn (\"cmp\\t%2, %3\", operands);
9253
    if (which_alternative != 0)
9254
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
9255
    return \"sub%d4\\t%0, %1, #1\";
9256
  "
9257
  [(set_attr "conds" "clob")
9258
   (set_attr "length" "8,12")]
9259
)
9260
 
9261
(define_insn "*cmp_ite0"
9262
  [(set (match_operand 6 "dominant_cc_register" "")
9263
        (compare
9264
         (if_then_else:SI
9265
          (match_operator 4 "arm_comparison_operator"
9266
           [(match_operand:SI 0 "s_register_operand"
9267
                "l,l,l,r,r,r,r,r,r")
9268
            (match_operand:SI 1 "arm_add_operand"
9269
                "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9270
          (match_operator:SI 5 "arm_comparison_operator"
9271
           [(match_operand:SI 2 "s_register_operand"
9272
                "l,r,r,l,l,r,r,r,r")
9273
            (match_operand:SI 3 "arm_add_operand"
9274
                "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9275
          (const_int 0))
9276
         (const_int 0)))]
9277
  "TARGET_32BIT"
9278
  "*
9279
  {
9280
    static const char * const cmp1[NUM_OF_COND_CMP][2] =
9281
    {
9282
      {\"cmp%d5\\t%0, %1\",
9283
       \"cmp%d4\\t%2, %3\"},
9284
      {\"cmn%d5\\t%0, #%n1\",
9285
       \"cmp%d4\\t%2, %3\"},
9286
      {\"cmp%d5\\t%0, %1\",
9287
       \"cmn%d4\\t%2, #%n3\"},
9288
      {\"cmn%d5\\t%0, #%n1\",
9289
       \"cmn%d4\\t%2, #%n3\"}
9290
    };
9291
    static const char * const cmp2[NUM_OF_COND_CMP][2] =
9292
    {
9293
      {\"cmp\\t%2, %3\",
9294
       \"cmp\\t%0, %1\"},
9295
      {\"cmp\\t%2, %3\",
9296
       \"cmn\\t%0, #%n1\"},
9297
      {\"cmn\\t%2, #%n3\",
9298
       \"cmp\\t%0, %1\"},
9299
      {\"cmn\\t%2, #%n3\",
9300
       \"cmn\\t%0, #%n1\"}
9301
    };
9302
    static const char * const ite[2] =
9303
    {
9304
      \"it\\t%d5\",
9305
      \"it\\t%d4\"
9306
    };
9307
    static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9308
                                   CMP_CMP, CMN_CMP, CMP_CMP,
9309
                                   CMN_CMP, CMP_CMN, CMN_CMN};
9310
    int swap =
9311
      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9312
 
9313
    output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9314
    if (TARGET_THUMB2) {
9315
      output_asm_insn (ite[swap], operands);
9316
    }
9317
    output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9318
    return \"\";
9319
  }"
9320
  [(set_attr "conds" "set")
9321
   (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9322
   (set_attr_alternative "length"
9323
      [(const_int 6)
9324
       (const_int 8)
9325
       (const_int 8)
9326
       (const_int 8)
9327
       (const_int 8)
9328
       (if_then_else (eq_attr "is_thumb" "no")
9329
           (const_int 8)
9330
           (const_int 10))
9331
       (if_then_else (eq_attr "is_thumb" "no")
9332
           (const_int 8)
9333
           (const_int 10))
9334
       (if_then_else (eq_attr "is_thumb" "no")
9335
           (const_int 8)
9336
           (const_int 10))
9337
       (if_then_else (eq_attr "is_thumb" "no")
9338
           (const_int 8)
9339
           (const_int 10))])]
9340
)
9341
 
9342
(define_insn "*cmp_ite1"
9343
  [(set (match_operand 6 "dominant_cc_register" "")
9344
        (compare
9345
         (if_then_else:SI
9346
          (match_operator 4 "arm_comparison_operator"
9347
           [(match_operand:SI 0 "s_register_operand"
9348
                "l,l,l,r,r,r,r,r,r")
9349
            (match_operand:SI 1 "arm_add_operand"
9350
                "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9351
          (match_operator:SI 5 "arm_comparison_operator"
9352
           [(match_operand:SI 2 "s_register_operand"
9353
                "l,r,r,l,l,r,r,r,r")
9354
            (match_operand:SI 3 "arm_add_operand"
9355
                "lPy,rI,L,lPy,lPy,rI,rI,L,L")])
9356
          (const_int 1))
9357
         (const_int 0)))]
9358
  "TARGET_32BIT"
9359
  "*
9360
  {
9361
    static const char * const cmp1[NUM_OF_COND_CMP][2] =
9362
    {
9363
      {\"cmp\\t%0, %1\",
9364
       \"cmp\\t%2, %3\"},
9365
      {\"cmn\\t%0, #%n1\",
9366
       \"cmp\\t%2, %3\"},
9367
      {\"cmp\\t%0, %1\",
9368
       \"cmn\\t%2, #%n3\"},
9369
      {\"cmn\\t%0, #%n1\",
9370
       \"cmn\\t%2, #%n3\"}
9371
    };
9372
    static const char * const cmp2[NUM_OF_COND_CMP][2] =
9373
    {
9374
      {\"cmp%d4\\t%2, %3\",
9375
       \"cmp%D5\\t%0, %1\"},
9376
      {\"cmp%d4\\t%2, %3\",
9377
       \"cmn%D5\\t%0, #%n1\"},
9378
      {\"cmn%d4\\t%2, #%n3\",
9379
       \"cmp%D5\\t%0, %1\"},
9380
      {\"cmn%d4\\t%2, #%n3\",
9381
       \"cmn%D5\\t%0, #%n1\"}
9382
    };
9383
    static const char * const ite[2] =
9384
    {
9385
      \"it\\t%d4\",
9386
      \"it\\t%D5\"
9387
    };
9388
    static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9389
                                   CMP_CMP, CMN_CMP, CMP_CMP,
9390
                                   CMN_CMP, CMP_CMN, CMN_CMN};
9391
    int swap =
9392
      comparison_dominates_p (GET_CODE (operands[5]),
9393
                              reverse_condition (GET_CODE (operands[4])));
9394
 
9395
    output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9396
    if (TARGET_THUMB2) {
9397
      output_asm_insn (ite[swap], operands);
9398
    }
9399
    output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9400
    return \"\";
9401
  }"
9402
  [(set_attr "conds" "set")
9403
   (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9404
   (set_attr_alternative "length"
9405
      [(const_int 6)
9406
       (const_int 8)
9407
       (const_int 8)
9408
       (const_int 8)
9409
       (const_int 8)
9410
       (if_then_else (eq_attr "is_thumb" "no")
9411
           (const_int 8)
9412
           (const_int 10))
9413
       (if_then_else (eq_attr "is_thumb" "no")
9414
           (const_int 8)
9415
           (const_int 10))
9416
       (if_then_else (eq_attr "is_thumb" "no")
9417
           (const_int 8)
9418
           (const_int 10))
9419
       (if_then_else (eq_attr "is_thumb" "no")
9420
           (const_int 8)
9421
           (const_int 10))])]
9422
)
9423
 
9424
(define_insn "*cmp_and"
9425
  [(set (match_operand 6 "dominant_cc_register" "")
9426
        (compare
9427
         (and:SI
9428
          (match_operator 4 "arm_comparison_operator"
9429
           [(match_operand:SI 0 "s_register_operand"
9430
                "l,l,l,r,r,r,r,r,r")
9431
            (match_operand:SI 1 "arm_add_operand"
9432
                "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9433
          (match_operator:SI 5 "arm_comparison_operator"
9434
           [(match_operand:SI 2 "s_register_operand"
9435
                "l,r,r,l,l,r,r,r,r")
9436
            (match_operand:SI 3 "arm_add_operand"
9437
                "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9438
         (const_int 0)))]
9439
  "TARGET_32BIT"
9440
  "*
9441
  {
9442
    static const char *const cmp1[NUM_OF_COND_CMP][2] =
9443
    {
9444
      {\"cmp%d5\\t%0, %1\",
9445
       \"cmp%d4\\t%2, %3\"},
9446
      {\"cmn%d5\\t%0, #%n1\",
9447
       \"cmp%d4\\t%2, %3\"},
9448
      {\"cmp%d5\\t%0, %1\",
9449
       \"cmn%d4\\t%2, #%n3\"},
9450
      {\"cmn%d5\\t%0, #%n1\",
9451
       \"cmn%d4\\t%2, #%n3\"}
9452
    };
9453
    static const char *const cmp2[NUM_OF_COND_CMP][2] =
9454
    {
9455
      {\"cmp\\t%2, %3\",
9456
       \"cmp\\t%0, %1\"},
9457
      {\"cmp\\t%2, %3\",
9458
       \"cmn\\t%0, #%n1\"},
9459
      {\"cmn\\t%2, #%n3\",
9460
       \"cmp\\t%0, %1\"},
9461
      {\"cmn\\t%2, #%n3\",
9462
       \"cmn\\t%0, #%n1\"}
9463
    };
9464
    static const char *const ite[2] =
9465
    {
9466
      \"it\\t%d5\",
9467
      \"it\\t%d4\"
9468
    };
9469
    static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9470
                                   CMP_CMP, CMN_CMP, CMP_CMP,
9471
                                   CMN_CMP, CMP_CMN, CMN_CMN};
9472
    int swap =
9473
      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9474
 
9475
    output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9476
    if (TARGET_THUMB2) {
9477
      output_asm_insn (ite[swap], operands);
9478
    }
9479
    output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9480
    return \"\";
9481
  }"
9482
  [(set_attr "conds" "set")
9483
   (set_attr "predicable" "no")
9484
   (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9485
   (set_attr_alternative "length"
9486
      [(const_int 6)
9487
       (const_int 8)
9488
       (const_int 8)
9489
       (const_int 8)
9490
       (const_int 8)
9491
       (if_then_else (eq_attr "is_thumb" "no")
9492
           (const_int 8)
9493
           (const_int 10))
9494
       (if_then_else (eq_attr "is_thumb" "no")
9495
           (const_int 8)
9496
           (const_int 10))
9497
       (if_then_else (eq_attr "is_thumb" "no")
9498
           (const_int 8)
9499
           (const_int 10))
9500
       (if_then_else (eq_attr "is_thumb" "no")
9501
           (const_int 8)
9502
           (const_int 10))])]
9503
)
9504
 
9505
(define_insn "*cmp_ior"
9506
  [(set (match_operand 6 "dominant_cc_register" "")
9507
        (compare
9508
         (ior:SI
9509
          (match_operator 4 "arm_comparison_operator"
9510
           [(match_operand:SI 0 "s_register_operand"
9511
                "l,l,l,r,r,r,r,r,r")
9512
            (match_operand:SI 1 "arm_add_operand"
9513
                "lPy,lPy,lPy,rI,L,rI,L,rI,L")])
9514
          (match_operator:SI 5 "arm_comparison_operator"
9515
           [(match_operand:SI 2 "s_register_operand"
9516
                "l,r,r,l,l,r,r,r,r")
9517
            (match_operand:SI 3 "arm_add_operand"
9518
                "lPy,rI,L,lPy,lPy,rI,rI,L,L")]))
9519
         (const_int 0)))]
9520
  "TARGET_32BIT"
9521
  "*
9522
  {
9523
    static const char *const cmp1[NUM_OF_COND_CMP][2] =
9524
    {
9525
      {\"cmp\\t%0, %1\",
9526
       \"cmp\\t%2, %3\"},
9527
      {\"cmn\\t%0, #%n1\",
9528
       \"cmp\\t%2, %3\"},
9529
      {\"cmp\\t%0, %1\",
9530
       \"cmn\\t%2, #%n3\"},
9531
      {\"cmn\\t%0, #%n1\",
9532
       \"cmn\\t%2, #%n3\"}
9533
    };
9534
    static const char *const cmp2[NUM_OF_COND_CMP][2] =
9535
    {
9536
      {\"cmp%D4\\t%2, %3\",
9537
       \"cmp%D5\\t%0, %1\"},
9538
      {\"cmp%D4\\t%2, %3\",
9539
       \"cmn%D5\\t%0, #%n1\"},
9540
      {\"cmn%D4\\t%2, #%n3\",
9541
       \"cmp%D5\\t%0, %1\"},
9542
      {\"cmn%D4\\t%2, #%n3\",
9543
       \"cmn%D5\\t%0, #%n1\"}
9544
    };
9545
    static const char *const ite[2] =
9546
    {
9547
      \"it\\t%D4\",
9548
      \"it\\t%D5\"
9549
    };
9550
    static const int cmp_idx[9] = {CMP_CMP, CMP_CMP, CMP_CMN,
9551
                                   CMP_CMP, CMN_CMP, CMP_CMP,
9552
                                   CMN_CMP, CMP_CMN, CMN_CMN};
9553
    int swap =
9554
      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
9555
 
9556
    output_asm_insn (cmp1[cmp_idx[which_alternative]][swap], operands);
9557
    if (TARGET_THUMB2) {
9558
      output_asm_insn (ite[swap], operands);
9559
    }
9560
    output_asm_insn (cmp2[cmp_idx[which_alternative]][swap], operands);
9561
    return \"\";
9562
  }
9563
  "
9564
  [(set_attr "conds" "set")
9565
   (set_attr "arch" "t2,t2,t2,t2,t2,any,any,any,any")
9566
   (set_attr_alternative "length"
9567
      [(const_int 6)
9568
       (const_int 8)
9569
       (const_int 8)
9570
       (const_int 8)
9571
       (const_int 8)
9572
       (if_then_else (eq_attr "is_thumb" "no")
9573
           (const_int 8)
9574
           (const_int 10))
9575
       (if_then_else (eq_attr "is_thumb" "no")
9576
           (const_int 8)
9577
           (const_int 10))
9578
       (if_then_else (eq_attr "is_thumb" "no")
9579
           (const_int 8)
9580
           (const_int 10))
9581
       (if_then_else (eq_attr "is_thumb" "no")
9582
           (const_int 8)
9583
           (const_int 10))])]
9584
)
9585
 
9586
(define_insn_and_split "*ior_scc_scc"
9587
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9588
        (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9589
                 [(match_operand:SI 1 "s_register_operand" "r")
9590
                  (match_operand:SI 2 "arm_add_operand" "rIL")])
9591
                (match_operator:SI 6 "arm_comparison_operator"
9592
                 [(match_operand:SI 4 "s_register_operand" "r")
9593
                  (match_operand:SI 5 "arm_add_operand" "rIL")])))
9594
   (clobber (reg:CC CC_REGNUM))]
9595
  "TARGET_32BIT
9596
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
9597
       != CCmode)"
9598
  "#"
9599
  "TARGET_32BIT && reload_completed"
9600
  [(set (match_dup 7)
9601
        (compare
9602
         (ior:SI
9603
          (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9604
          (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9605
         (const_int 0)))
9606
   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9607
  "operands[7]
9608
     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9609
                                                  DOM_CC_X_OR_Y),
9610
                    CC_REGNUM);"
9611
  [(set_attr "conds" "clob")
9612
   (set_attr "length" "16")])
9613
 
9614
; If the above pattern is followed by a CMP insn, then the compare is
9615
; redundant, since we can rework the conditional instruction that follows.
9616
(define_insn_and_split "*ior_scc_scc_cmp"
9617
  [(set (match_operand 0 "dominant_cc_register" "")
9618
        (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
9619
                          [(match_operand:SI 1 "s_register_operand" "r")
9620
                           (match_operand:SI 2 "arm_add_operand" "rIL")])
9621
                         (match_operator:SI 6 "arm_comparison_operator"
9622
                          [(match_operand:SI 4 "s_register_operand" "r")
9623
                           (match_operand:SI 5 "arm_add_operand" "rIL")]))
9624
                 (const_int 0)))
9625
   (set (match_operand:SI 7 "s_register_operand" "=r")
9626
        (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9627
                (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9628
  "TARGET_32BIT"
9629
  "#"
9630
  "TARGET_32BIT && reload_completed"
9631
  [(set (match_dup 0)
9632
        (compare
9633
         (ior:SI
9634
          (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9635
          (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9636
         (const_int 0)))
9637
   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9638
  ""
9639
  [(set_attr "conds" "set")
9640
   (set_attr "length" "16")])
9641
 
9642
(define_insn_and_split "*and_scc_scc"
9643
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9644
        (and:SI (match_operator:SI 3 "arm_comparison_operator"
9645
                 [(match_operand:SI 1 "s_register_operand" "r")
9646
                  (match_operand:SI 2 "arm_add_operand" "rIL")])
9647
                (match_operator:SI 6 "arm_comparison_operator"
9648
                 [(match_operand:SI 4 "s_register_operand" "r")
9649
                  (match_operand:SI 5 "arm_add_operand" "rIL")])))
9650
   (clobber (reg:CC CC_REGNUM))]
9651
  "TARGET_32BIT
9652
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9653
       != CCmode)"
9654
  "#"
9655
  "TARGET_32BIT && reload_completed
9656
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9657
       != CCmode)"
9658
  [(set (match_dup 7)
9659
        (compare
9660
         (and:SI
9661
          (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9662
          (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9663
         (const_int 0)))
9664
   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
9665
  "operands[7]
9666
     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
9667
                                                  DOM_CC_X_AND_Y),
9668
                    CC_REGNUM);"
9669
  [(set_attr "conds" "clob")
9670
   (set_attr "length" "16")])
9671
 
9672
; If the above pattern is followed by a CMP insn, then the compare is
9673
; redundant, since we can rework the conditional instruction that follows.
9674
(define_insn_and_split "*and_scc_scc_cmp"
9675
  [(set (match_operand 0 "dominant_cc_register" "")
9676
        (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
9677
                          [(match_operand:SI 1 "s_register_operand" "r")
9678
                           (match_operand:SI 2 "arm_add_operand" "rIL")])
9679
                         (match_operator:SI 6 "arm_comparison_operator"
9680
                          [(match_operand:SI 4 "s_register_operand" "r")
9681
                           (match_operand:SI 5 "arm_add_operand" "rIL")]))
9682
                 (const_int 0)))
9683
   (set (match_operand:SI 7 "s_register_operand" "=r")
9684
        (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9685
                (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
9686
  "TARGET_32BIT"
9687
  "#"
9688
  "TARGET_32BIT && reload_completed"
9689
  [(set (match_dup 0)
9690
        (compare
9691
         (and:SI
9692
          (match_op_dup 3 [(match_dup 1) (match_dup 2)])
9693
          (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
9694
         (const_int 0)))
9695
   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
9696
  ""
9697
  [(set_attr "conds" "set")
9698
   (set_attr "length" "16")])
9699
 
9700
;; If there is no dominance in the comparison, then we can still save an
9701
;; instruction in the AND case, since we can know that the second compare
9702
;; need only zero the value if false (if true, then the value is already
9703
;; correct).
9704
(define_insn_and_split "*and_scc_scc_nodom"
9705
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
9706
        (and:SI (match_operator:SI 3 "arm_comparison_operator"
9707
                 [(match_operand:SI 1 "s_register_operand" "r,r,0")
9708
                  (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
9709
                (match_operator:SI 6 "arm_comparison_operator"
9710
                 [(match_operand:SI 4 "s_register_operand" "r,r,r")
9711
                  (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
9712
   (clobber (reg:CC CC_REGNUM))]
9713
  "TARGET_32BIT
9714
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
9715
       == CCmode)"
9716
  "#"
9717
  "TARGET_32BIT && reload_completed"
9718
  [(parallel [(set (match_dup 0)
9719
                   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
9720
              (clobber (reg:CC CC_REGNUM))])
9721
   (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
9722
   (set (match_dup 0)
9723
        (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
9724
                         (match_dup 0)
9725
                         (const_int 0)))]
9726
  "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
9727
                                              operands[4], operands[5]),
9728
                              CC_REGNUM);
9729
   operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
9730
                                  operands[5]);"
9731
  [(set_attr "conds" "clob")
9732
   (set_attr "length" "20")])
9733
 
9734
(define_split
9735
  [(set (reg:CC_NOOV CC_REGNUM)
9736
        (compare:CC_NOOV (ior:SI
9737
                          (and:SI (match_operand:SI 0 "s_register_operand" "")
9738
                                  (const_int 1))
9739
                          (match_operator:SI 1 "arm_comparison_operator"
9740
                           [(match_operand:SI 2 "s_register_operand" "")
9741
                            (match_operand:SI 3 "arm_add_operand" "")]))
9742
                         (const_int 0)))
9743
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
9744
  "TARGET_ARM"
9745
  [(set (match_dup 4)
9746
        (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9747
                (match_dup 0)))
9748
   (set (reg:CC_NOOV CC_REGNUM)
9749
        (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9750
                         (const_int 0)))]
9751
  "")
9752
 
9753
(define_split
9754
  [(set (reg:CC_NOOV CC_REGNUM)
9755
        (compare:CC_NOOV (ior:SI
9756
                          (match_operator:SI 1 "arm_comparison_operator"
9757
                           [(match_operand:SI 2 "s_register_operand" "")
9758
                            (match_operand:SI 3 "arm_add_operand" "")])
9759
                          (and:SI (match_operand:SI 0 "s_register_operand" "")
9760
                                  (const_int 1)))
9761
                         (const_int 0)))
9762
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
9763
  "TARGET_ARM"
9764
  [(set (match_dup 4)
9765
        (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
9766
                (match_dup 0)))
9767
   (set (reg:CC_NOOV CC_REGNUM)
9768
        (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
9769
                         (const_int 0)))]
9770
  "")
9771
;; ??? The conditional patterns above need checking for Thumb-2 usefulness
9772
 
9773
(define_insn "*negscc"
9774
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9775
        (neg:SI (match_operator 3 "arm_comparison_operator"
9776
                 [(match_operand:SI 1 "s_register_operand" "r")
9777
                  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
9778
   (clobber (reg:CC CC_REGNUM))]
9779
  "TARGET_ARM"
9780
  "*
9781
  if (GET_CODE (operands[3]) == LT && operands[2] == const0_rtx)
9782
    return \"mov\\t%0, %1, asr #31\";
9783
 
9784
  if (GET_CODE (operands[3]) == NE)
9785
    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
9786
 
9787
  output_asm_insn (\"cmp\\t%1, %2\", operands);
9788
  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
9789
  return \"mvn%d3\\t%0, #0\";
9790
  "
9791
  [(set_attr "conds" "clob")
9792
   (set_attr "length" "12")]
9793
)
9794
 
9795
(define_insn "movcond"
9796
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9797
        (if_then_else:SI
9798
         (match_operator 5 "arm_comparison_operator"
9799
          [(match_operand:SI 3 "s_register_operand" "r,r,r")
9800
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
9801
         (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
9802
         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
9803
   (clobber (reg:CC CC_REGNUM))]
9804
  "TARGET_ARM"
9805
  "*
9806
  if (GET_CODE (operands[5]) == LT
9807
      && (operands[4] == const0_rtx))
9808
    {
9809
      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9810
        {
9811
          if (operands[2] == const0_rtx)
9812
            return \"and\\t%0, %1, %3, asr #31\";
9813
          return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
9814
        }
9815
      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9816
        {
9817
          if (operands[1] == const0_rtx)
9818
            return \"bic\\t%0, %2, %3, asr #31\";
9819
          return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
9820
        }
9821
      /* The only case that falls through to here is when both ops 1 & 2
9822
         are constants.  */
9823
    }
9824
 
9825
  if (GET_CODE (operands[5]) == GE
9826
      && (operands[4] == const0_rtx))
9827
    {
9828
      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
9829
        {
9830
          if (operands[2] == const0_rtx)
9831
            return \"bic\\t%0, %1, %3, asr #31\";
9832
          return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
9833
        }
9834
      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
9835
        {
9836
          if (operands[1] == const0_rtx)
9837
            return \"and\\t%0, %2, %3, asr #31\";
9838
          return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
9839
        }
9840
      /* The only case that falls through to here is when both ops 1 & 2
9841
         are constants.  */
9842
    }
9843
  if (GET_CODE (operands[4]) == CONST_INT
9844
      && !const_ok_for_arm (INTVAL (operands[4])))
9845
    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
9846
  else
9847
    output_asm_insn (\"cmp\\t%3, %4\", operands);
9848
  if (which_alternative != 0)
9849
    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
9850
  if (which_alternative != 1)
9851
    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
9852
  return \"\";
9853
  "
9854
  [(set_attr "conds" "clob")
9855
   (set_attr "length" "8,8,12")]
9856
)
9857
 
9858
;; ??? The patterns below need checking for Thumb-2 usefulness.
9859
 
9860
(define_insn "*ifcompare_plus_move"
9861
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9862
        (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9863
                          [(match_operand:SI 4 "s_register_operand" "r,r")
9864
                           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9865
                         (plus:SI
9866
                          (match_operand:SI 2 "s_register_operand" "r,r")
9867
                          (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
9868
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9869
   (clobber (reg:CC CC_REGNUM))]
9870
  "TARGET_ARM"
9871
  "#"
9872
  [(set_attr "conds" "clob")
9873
   (set_attr "length" "8,12")]
9874
)
9875
 
9876
(define_insn "*if_plus_move"
9877
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9878
        (if_then_else:SI
9879
         (match_operator 4 "arm_comparison_operator"
9880
          [(match_operand 5 "cc_register" "") (const_int 0)])
9881
         (plus:SI
9882
          (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9883
          (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
9884
         (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
9885
  "TARGET_ARM"
9886
  "@
9887
   add%d4\\t%0, %2, %3
9888
   sub%d4\\t%0, %2, #%n3
9889
   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
9890
   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
9891
  [(set_attr "conds" "use")
9892
   (set_attr "length" "4,4,8,8")
9893
   (set_attr "type" "*,*,*,*")]
9894
)
9895
 
9896
(define_insn "*ifcompare_move_plus"
9897
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9898
        (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9899
                          [(match_operand:SI 4 "s_register_operand" "r,r")
9900
                           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9901
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9902
                         (plus:SI
9903
                          (match_operand:SI 2 "s_register_operand" "r,r")
9904
                          (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
9905
   (clobber (reg:CC CC_REGNUM))]
9906
  "TARGET_ARM"
9907
  "#"
9908
  [(set_attr "conds" "clob")
9909
   (set_attr "length" "8,12")]
9910
)
9911
 
9912
(define_insn "*if_move_plus"
9913
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
9914
        (if_then_else:SI
9915
         (match_operator 4 "arm_comparison_operator"
9916
          [(match_operand 5 "cc_register" "") (const_int 0)])
9917
         (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
9918
         (plus:SI
9919
          (match_operand:SI 2 "s_register_operand" "r,r,r,r")
9920
          (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
9921
  "TARGET_ARM"
9922
  "@
9923
   add%D4\\t%0, %2, %3
9924
   sub%D4\\t%0, %2, #%n3
9925
   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
9926
   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
9927
  [(set_attr "conds" "use")
9928
   (set_attr "length" "4,4,8,8")
9929
   (set_attr "type" "*,*,*,*")]
9930
)
9931
 
9932
(define_insn "*ifcompare_arith_arith"
9933
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9934
        (if_then_else:SI (match_operator 9 "arm_comparison_operator"
9935
                          [(match_operand:SI 5 "s_register_operand" "r")
9936
                           (match_operand:SI 6 "arm_add_operand" "rIL")])
9937
                         (match_operator:SI 8 "shiftable_operator"
9938
                          [(match_operand:SI 1 "s_register_operand" "r")
9939
                           (match_operand:SI 2 "arm_rhs_operand" "rI")])
9940
                         (match_operator:SI 7 "shiftable_operator"
9941
                          [(match_operand:SI 3 "s_register_operand" "r")
9942
                           (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9943
   (clobber (reg:CC CC_REGNUM))]
9944
  "TARGET_ARM"
9945
  "#"
9946
  [(set_attr "conds" "clob")
9947
   (set_attr "length" "12")]
9948
)
9949
 
9950
(define_insn "*if_arith_arith"
9951
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9952
        (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9953
                          [(match_operand 8 "cc_register" "") (const_int 0)])
9954
                         (match_operator:SI 6 "shiftable_operator"
9955
                          [(match_operand:SI 1 "s_register_operand" "r")
9956
                           (match_operand:SI 2 "arm_rhs_operand" "rI")])
9957
                         (match_operator:SI 7 "shiftable_operator"
9958
                          [(match_operand:SI 3 "s_register_operand" "r")
9959
                           (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9960
  "TARGET_ARM"
9961
  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9962
  [(set_attr "conds" "use")
9963
   (set_attr "length" "8")]
9964
)
9965
 
9966
(define_insn "*ifcompare_arith_move"
9967
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9968
        (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9969
                          [(match_operand:SI 2 "s_register_operand" "r,r")
9970
                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9971
                         (match_operator:SI 7 "shiftable_operator"
9972
                          [(match_operand:SI 4 "s_register_operand" "r,r")
9973
                           (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9974
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9975
   (clobber (reg:CC CC_REGNUM))]
9976
  "TARGET_ARM"
9977
  "*
9978
  /* If we have an operation where (op x 0) is the identity operation and
9979
     the conditional operator is LT or GE and we are comparing against zero and
9980
     everything is in registers then we can do this in two instructions.  */
9981
  if (operands[3] == const0_rtx
9982
      && GET_CODE (operands[7]) != AND
9983
      && GET_CODE (operands[5]) == REG
9984
      && GET_CODE (operands[1]) == REG
9985
      && REGNO (operands[1]) == REGNO (operands[4])
9986
      && REGNO (operands[4]) != REGNO (operands[0]))
9987
    {
9988
      if (GET_CODE (operands[6]) == LT)
9989
        return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9990
      else if (GET_CODE (operands[6]) == GE)
9991
        return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9992
    }
9993
  if (GET_CODE (operands[3]) == CONST_INT
9994
      && !const_ok_for_arm (INTVAL (operands[3])))
9995
    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9996
  else
9997
    output_asm_insn (\"cmp\\t%2, %3\", operands);
9998
  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9999
  if (which_alternative != 0)
10000
    return \"mov%D6\\t%0, %1\";
10001
  return \"\";
10002
  "
10003
  [(set_attr "conds" "clob")
10004
   (set_attr "length" "8,12")]
10005
)
10006
 
10007
(define_insn "*if_arith_move"
10008
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10009
        (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10010
                          [(match_operand 6 "cc_register" "") (const_int 0)])
10011
                         (match_operator:SI 5 "shiftable_operator"
10012
                          [(match_operand:SI 2 "s_register_operand" "r,r")
10013
                           (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
10014
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
10015
  "TARGET_ARM"
10016
  "@
10017
   %I5%d4\\t%0, %2, %3
10018
   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
10019
  [(set_attr "conds" "use")
10020
   (set_attr "length" "4,8")
10021
   (set_attr "type" "*,*")]
10022
)
10023
 
10024
(define_insn "*ifcompare_move_arith"
10025
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10026
        (if_then_else:SI (match_operator 6 "arm_comparison_operator"
10027
                          [(match_operand:SI 4 "s_register_operand" "r,r")
10028
                           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10029
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10030
                         (match_operator:SI 7 "shiftable_operator"
10031
                          [(match_operand:SI 2 "s_register_operand" "r,r")
10032
                           (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
10033
   (clobber (reg:CC CC_REGNUM))]
10034
  "TARGET_ARM"
10035
  "*
10036
  /* If we have an operation where (op x 0) is the identity operation and
10037
     the conditional operator is LT or GE and we are comparing against zero and
10038
     everything is in registers then we can do this in two instructions */
10039
  if (operands[5] == const0_rtx
10040
      && GET_CODE (operands[7]) != AND
10041
      && GET_CODE (operands[3]) == REG
10042
      && GET_CODE (operands[1]) == REG
10043
      && REGNO (operands[1]) == REGNO (operands[2])
10044
      && REGNO (operands[2]) != REGNO (operands[0]))
10045
    {
10046
      if (GET_CODE (operands[6]) == GE)
10047
        return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10048
      else if (GET_CODE (operands[6]) == LT)
10049
        return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
10050
    }
10051
 
10052
  if (GET_CODE (operands[5]) == CONST_INT
10053
      && !const_ok_for_arm (INTVAL (operands[5])))
10054
    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
10055
  else
10056
    output_asm_insn (\"cmp\\t%4, %5\", operands);
10057
 
10058
  if (which_alternative != 0)
10059
    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
10060
  return \"%I7%D6\\t%0, %2, %3\";
10061
  "
10062
  [(set_attr "conds" "clob")
10063
   (set_attr "length" "8,12")]
10064
)
10065
 
10066
(define_insn "*if_move_arith"
10067
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10068
        (if_then_else:SI
10069
         (match_operator 4 "arm_comparison_operator"
10070
          [(match_operand 6 "cc_register" "") (const_int 0)])
10071
         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10072
         (match_operator:SI 5 "shiftable_operator"
10073
          [(match_operand:SI 2 "s_register_operand" "r,r")
10074
           (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
10075
  "TARGET_ARM"
10076
  "@
10077
   %I5%D4\\t%0, %2, %3
10078
   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
10079
  [(set_attr "conds" "use")
10080
   (set_attr "length" "4,8")
10081
   (set_attr "type" "*,*")]
10082
)
10083
 
10084
(define_insn "*ifcompare_move_not"
10085
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10086
        (if_then_else:SI
10087
         (match_operator 5 "arm_comparison_operator"
10088
          [(match_operand:SI 3 "s_register_operand" "r,r")
10089
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10090
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10091
         (not:SI
10092
          (match_operand:SI 2 "s_register_operand" "r,r"))))
10093
   (clobber (reg:CC CC_REGNUM))]
10094
  "TARGET_ARM"
10095
  "#"
10096
  [(set_attr "conds" "clob")
10097
   (set_attr "length" "8,12")]
10098
)
10099
 
10100
(define_insn "*if_move_not"
10101
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10102
        (if_then_else:SI
10103
         (match_operator 4 "arm_comparison_operator"
10104
          [(match_operand 3 "cc_register" "") (const_int 0)])
10105
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10106
         (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10107
  "TARGET_ARM"
10108
  "@
10109
   mvn%D4\\t%0, %2
10110
   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
10111
   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
10112
  [(set_attr "conds" "use")
10113
   (set_attr "insn" "mvn")
10114
   (set_attr "length" "4,8,8")]
10115
)
10116
 
10117
(define_insn "*ifcompare_not_move"
10118
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10119
        (if_then_else:SI
10120
         (match_operator 5 "arm_comparison_operator"
10121
          [(match_operand:SI 3 "s_register_operand" "r,r")
10122
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10123
         (not:SI
10124
          (match_operand:SI 2 "s_register_operand" "r,r"))
10125
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10126
   (clobber (reg:CC CC_REGNUM))]
10127
  "TARGET_ARM"
10128
  "#"
10129
  [(set_attr "conds" "clob")
10130
   (set_attr "length" "8,12")]
10131
)
10132
 
10133
(define_insn "*if_not_move"
10134
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10135
        (if_then_else:SI
10136
         (match_operator 4 "arm_comparison_operator"
10137
          [(match_operand 3 "cc_register" "") (const_int 0)])
10138
         (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10139
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10140
  "TARGET_ARM"
10141
  "@
10142
   mvn%d4\\t%0, %2
10143
   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
10144
   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
10145
  [(set_attr "conds" "use")
10146
   (set_attr "insn" "mvn")
10147
   (set_attr "length" "4,8,8")]
10148
)
10149
 
10150
(define_insn "*ifcompare_shift_move"
10151
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10152
        (if_then_else:SI
10153
         (match_operator 6 "arm_comparison_operator"
10154
          [(match_operand:SI 4 "s_register_operand" "r,r")
10155
           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10156
         (match_operator:SI 7 "shift_operator"
10157
          [(match_operand:SI 2 "s_register_operand" "r,r")
10158
           (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
10159
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10160
   (clobber (reg:CC CC_REGNUM))]
10161
  "TARGET_ARM"
10162
  "#"
10163
  [(set_attr "conds" "clob")
10164
   (set_attr "length" "8,12")]
10165
)
10166
 
10167
(define_insn "*if_shift_move"
10168
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10169
        (if_then_else:SI
10170
         (match_operator 5 "arm_comparison_operator"
10171
          [(match_operand 6 "cc_register" "") (const_int 0)])
10172
         (match_operator:SI 4 "shift_operator"
10173
          [(match_operand:SI 2 "s_register_operand" "r,r,r")
10174
           (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
10175
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10176
  "TARGET_ARM"
10177
  "@
10178
   mov%d5\\t%0, %2%S4
10179
   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
10180
   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
10181
  [(set_attr "conds" "use")
10182
   (set_attr "shift" "2")
10183
   (set_attr "length" "4,8,8")
10184
   (set_attr "insn" "mov")
10185
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10186
                      (const_string "alu_shift")
10187
                      (const_string "alu_shift_reg")))]
10188
)
10189
 
10190
(define_insn "*ifcompare_move_shift"
10191
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10192
        (if_then_else:SI
10193
         (match_operator 6 "arm_comparison_operator"
10194
          [(match_operand:SI 4 "s_register_operand" "r,r")
10195
           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
10196
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10197
         (match_operator:SI 7 "shift_operator"
10198
          [(match_operand:SI 2 "s_register_operand" "r,r")
10199
           (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
10200
   (clobber (reg:CC CC_REGNUM))]
10201
  "TARGET_ARM"
10202
  "#"
10203
  [(set_attr "conds" "clob")
10204
   (set_attr "length" "8,12")]
10205
)
10206
 
10207
(define_insn "*if_move_shift"
10208
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10209
        (if_then_else:SI
10210
         (match_operator 5 "arm_comparison_operator"
10211
          [(match_operand 6 "cc_register" "") (const_int 0)])
10212
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10213
         (match_operator:SI 4 "shift_operator"
10214
          [(match_operand:SI 2 "s_register_operand" "r,r,r")
10215
           (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
10216
  "TARGET_ARM"
10217
  "@
10218
   mov%D5\\t%0, %2%S4
10219
   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
10220
   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
10221
  [(set_attr "conds" "use")
10222
   (set_attr "shift" "2")
10223
   (set_attr "length" "4,8,8")
10224
   (set_attr "insn" "mov")
10225
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
10226
                      (const_string "alu_shift")
10227
                      (const_string "alu_shift_reg")))]
10228
)
10229
 
10230
(define_insn "*ifcompare_shift_shift"
10231
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10232
        (if_then_else:SI
10233
         (match_operator 7 "arm_comparison_operator"
10234
          [(match_operand:SI 5 "s_register_operand" "r")
10235
           (match_operand:SI 6 "arm_add_operand" "rIL")])
10236
         (match_operator:SI 8 "shift_operator"
10237
          [(match_operand:SI 1 "s_register_operand" "r")
10238
           (match_operand:SI 2 "arm_rhs_operand" "rM")])
10239
         (match_operator:SI 9 "shift_operator"
10240
          [(match_operand:SI 3 "s_register_operand" "r")
10241
           (match_operand:SI 4 "arm_rhs_operand" "rM")])))
10242
   (clobber (reg:CC CC_REGNUM))]
10243
  "TARGET_ARM"
10244
  "#"
10245
  [(set_attr "conds" "clob")
10246
   (set_attr "length" "12")]
10247
)
10248
 
10249
(define_insn "*if_shift_shift"
10250
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10251
        (if_then_else:SI
10252
         (match_operator 5 "arm_comparison_operator"
10253
          [(match_operand 8 "cc_register" "") (const_int 0)])
10254
         (match_operator:SI 6 "shift_operator"
10255
          [(match_operand:SI 1 "s_register_operand" "r")
10256
           (match_operand:SI 2 "arm_rhs_operand" "rM")])
10257
         (match_operator:SI 7 "shift_operator"
10258
          [(match_operand:SI 3 "s_register_operand" "r")
10259
           (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
10260
  "TARGET_ARM"
10261
  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
10262
  [(set_attr "conds" "use")
10263
   (set_attr "shift" "1")
10264
   (set_attr "length" "8")
10265
   (set_attr "insn" "mov")
10266
   (set (attr "type") (if_then_else
10267
                        (and (match_operand 2 "const_int_operand" "")
10268
                             (match_operand 4 "const_int_operand" ""))
10269
                      (const_string "alu_shift")
10270
                      (const_string "alu_shift_reg")))]
10271
)
10272
 
10273
(define_insn "*ifcompare_not_arith"
10274
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10275
        (if_then_else:SI
10276
         (match_operator 6 "arm_comparison_operator"
10277
          [(match_operand:SI 4 "s_register_operand" "r")
10278
           (match_operand:SI 5 "arm_add_operand" "rIL")])
10279
         (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10280
         (match_operator:SI 7 "shiftable_operator"
10281
          [(match_operand:SI 2 "s_register_operand" "r")
10282
           (match_operand:SI 3 "arm_rhs_operand" "rI")])))
10283
   (clobber (reg:CC CC_REGNUM))]
10284
  "TARGET_ARM"
10285
  "#"
10286
  [(set_attr "conds" "clob")
10287
   (set_attr "length" "12")]
10288
)
10289
 
10290
(define_insn "*if_not_arith"
10291
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10292
        (if_then_else:SI
10293
         (match_operator 5 "arm_comparison_operator"
10294
          [(match_operand 4 "cc_register" "") (const_int 0)])
10295
         (not:SI (match_operand:SI 1 "s_register_operand" "r"))
10296
         (match_operator:SI 6 "shiftable_operator"
10297
          [(match_operand:SI 2 "s_register_operand" "r")
10298
           (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
10299
  "TARGET_ARM"
10300
  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
10301
  [(set_attr "conds" "use")
10302
   (set_attr "insn" "mvn")
10303
   (set_attr "length" "8")]
10304
)
10305
 
10306
(define_insn "*ifcompare_arith_not"
10307
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10308
        (if_then_else:SI
10309
         (match_operator 6 "arm_comparison_operator"
10310
          [(match_operand:SI 4 "s_register_operand" "r")
10311
           (match_operand:SI 5 "arm_add_operand" "rIL")])
10312
         (match_operator:SI 7 "shiftable_operator"
10313
          [(match_operand:SI 2 "s_register_operand" "r")
10314
           (match_operand:SI 3 "arm_rhs_operand" "rI")])
10315
         (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
10316
   (clobber (reg:CC CC_REGNUM))]
10317
  "TARGET_ARM"
10318
  "#"
10319
  [(set_attr "conds" "clob")
10320
   (set_attr "length" "12")]
10321
)
10322
 
10323
(define_insn "*if_arith_not"
10324
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10325
        (if_then_else:SI
10326
         (match_operator 5 "arm_comparison_operator"
10327
          [(match_operand 4 "cc_register" "") (const_int 0)])
10328
         (match_operator:SI 6 "shiftable_operator"
10329
          [(match_operand:SI 2 "s_register_operand" "r")
10330
           (match_operand:SI 3 "arm_rhs_operand" "rI")])
10331
         (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
10332
  "TARGET_ARM"
10333
  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
10334
  [(set_attr "conds" "use")
10335
   (set_attr "insn" "mvn")
10336
   (set_attr "length" "8")]
10337
)
10338
 
10339
(define_insn "*ifcompare_neg_move"
10340
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10341
        (if_then_else:SI
10342
         (match_operator 5 "arm_comparison_operator"
10343
          [(match_operand:SI 3 "s_register_operand" "r,r")
10344
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10345
         (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
10346
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
10347
   (clobber (reg:CC CC_REGNUM))]
10348
  "TARGET_ARM"
10349
  "#"
10350
  [(set_attr "conds" "clob")
10351
   (set_attr "length" "8,12")]
10352
)
10353
 
10354
(define_insn "*if_neg_move"
10355
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10356
        (if_then_else:SI
10357
         (match_operator 4 "arm_comparison_operator"
10358
          [(match_operand 3 "cc_register" "") (const_int 0)])
10359
         (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
10360
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
10361
  "TARGET_ARM"
10362
  "@
10363
   rsb%d4\\t%0, %2, #0
10364
   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
10365
   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
10366
  [(set_attr "conds" "use")
10367
   (set_attr "length" "4,8,8")]
10368
)
10369
 
10370
(define_insn "*ifcompare_move_neg"
10371
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10372
        (if_then_else:SI
10373
         (match_operator 5 "arm_comparison_operator"
10374
          [(match_operand:SI 3 "s_register_operand" "r,r")
10375
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
10376
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")
10377
         (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
10378
   (clobber (reg:CC CC_REGNUM))]
10379
  "TARGET_ARM"
10380
  "#"
10381
  [(set_attr "conds" "clob")
10382
   (set_attr "length" "8,12")]
10383
)
10384
 
10385
(define_insn "*if_move_neg"
10386
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
10387
        (if_then_else:SI
10388
         (match_operator 4 "arm_comparison_operator"
10389
          [(match_operand 3 "cc_register" "") (const_int 0)])
10390
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
10391
         (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
10392
  "TARGET_ARM"
10393
  "@
10394
   rsb%D4\\t%0, %2, #0
10395
   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
10396
   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
10397
  [(set_attr "conds" "use")
10398
   (set_attr "length" "4,8,8")]
10399
)
10400
 
10401
(define_insn "*arith_adjacentmem"
10402
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10403
        (match_operator:SI 1 "shiftable_operator"
10404
         [(match_operand:SI 2 "memory_operand" "m")
10405
          (match_operand:SI 3 "memory_operand" "m")]))
10406
   (clobber (match_scratch:SI 4 "=r"))]
10407
  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
10408
  "*
10409
  {
10410
    rtx ldm[3];
10411
    rtx arith[4];
10412
    rtx base_reg;
10413
    HOST_WIDE_INT val1 = 0, val2 = 0;
10414
 
10415
    if (REGNO (operands[0]) > REGNO (operands[4]))
10416
      {
10417
        ldm[1] = operands[4];
10418
        ldm[2] = operands[0];
10419
      }
10420
    else
10421
      {
10422
        ldm[1] = operands[0];
10423
        ldm[2] = operands[4];
10424
      }
10425
 
10426
    base_reg = XEXP (operands[2], 0);
10427
 
10428
    if (!REG_P (base_reg))
10429
      {
10430
        val1 = INTVAL (XEXP (base_reg, 1));
10431
        base_reg = XEXP (base_reg, 0);
10432
      }
10433
 
10434
    if (!REG_P (XEXP (operands[3], 0)))
10435
      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
10436
 
10437
    arith[0] = operands[0];
10438
    arith[3] = operands[1];
10439
 
10440
    if (val1 < val2)
10441
      {
10442
        arith[1] = ldm[1];
10443
        arith[2] = ldm[2];
10444
      }
10445
    else
10446
      {
10447
        arith[1] = ldm[2];
10448
        arith[2] = ldm[1];
10449
      }
10450
 
10451
    ldm[0] = base_reg;
10452
    if (val1 !=0 && val2 != 0)
10453
      {
10454
        rtx ops[3];
10455
 
10456
        if (val1 == 4 || val2 == 4)
10457
          /* Other val must be 8, since we know they are adjacent and neither
10458
             is zero.  */
10459
          output_asm_insn (\"ldm%(ib%)\\t%0, {%1, %2}\", ldm);
10460
        else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
10461
          {
10462
            ldm[0] = ops[0] = operands[4];
10463
            ops[1] = base_reg;
10464
            ops[2] = GEN_INT (val1);
10465
            output_add_immediate (ops);
10466
            if (val1 < val2)
10467
              output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10468
            else
10469
              output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10470
          }
10471
        else
10472
          {
10473
            /* Offset is out of range for a single add, so use two ldr.  */
10474
            ops[0] = ldm[1];
10475
            ops[1] = base_reg;
10476
            ops[2] = GEN_INT (val1);
10477
            output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10478
            ops[0] = ldm[2];
10479
            ops[2] = GEN_INT (val2);
10480
            output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
10481
          }
10482
      }
10483
    else if (val1 != 0)
10484
      {
10485
        if (val1 < val2)
10486
          output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10487
        else
10488
          output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10489
      }
10490
    else
10491
      {
10492
        if (val1 < val2)
10493
          output_asm_insn (\"ldm%(ia%)\\t%0, {%1, %2}\", ldm);
10494
        else
10495
          output_asm_insn (\"ldm%(da%)\\t%0, {%1, %2}\", ldm);
10496
      }
10497
    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
10498
    return \"\";
10499
  }"
10500
  [(set_attr "length" "12")
10501
   (set_attr "predicable" "yes")
10502
   (set_attr "type" "load1")]
10503
)
10504
 
10505
; This pattern is never tried by combine, so do it as a peephole
10506
 
10507
(define_peephole2
10508
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
10509
        (match_operand:SI 1 "arm_general_register_operand" ""))
10510
   (set (reg:CC CC_REGNUM)
10511
        (compare:CC (match_dup 1) (const_int 0)))]
10512
  "TARGET_ARM"
10513
  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
10514
              (set (match_dup 0) (match_dup 1))])]
10515
  ""
10516
)
10517
 
10518
(define_split
10519
  [(set (match_operand:SI 0 "s_register_operand" "")
10520
        (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
10521
                       (const_int 0))
10522
                (neg:SI (match_operator:SI 2 "arm_comparison_operator"
10523
                         [(match_operand:SI 3 "s_register_operand" "")
10524
                          (match_operand:SI 4 "arm_rhs_operand" "")]))))
10525
   (clobber (match_operand:SI 5 "s_register_operand" ""))]
10526
  "TARGET_ARM"
10527
  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
10528
   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
10529
                              (match_dup 5)))]
10530
  ""
10531
)
10532
 
10533
;; This split can be used because CC_Z mode implies that the following
10534
;; branch will be an equality, or an unsigned inequality, so the sign
10535
;; extension is not needed.
10536
 
10537
(define_split
10538
  [(set (reg:CC_Z CC_REGNUM)
10539
        (compare:CC_Z
10540
         (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
10541
                    (const_int 24))
10542
         (match_operand 1 "const_int_operand" "")))
10543
   (clobber (match_scratch:SI 2 ""))]
10544
  "TARGET_ARM
10545
   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
10546
       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
10547
  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
10548
   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
10549
  "
10550
  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
10551
  "
10552
)
10553
;; ??? Check the patterns above for Thumb-2 usefulness
10554
 
10555
(define_expand "prologue"
10556
  [(clobber (const_int 0))]
10557
  "TARGET_EITHER"
10558
  "if (TARGET_32BIT)
10559
     arm_expand_prologue ();
10560
   else
10561
     thumb1_expand_prologue ();
10562
  DONE;
10563
  "
10564
)
10565
 
10566
(define_expand "epilogue"
10567
  [(clobber (const_int 0))]
10568
  "TARGET_EITHER"
10569
  "
10570
  if (crtl->calls_eh_return)
10571
    emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
10572
  if (TARGET_THUMB1)
10573
    thumb1_expand_epilogue ();
10574
  else if (USE_RETURN_INSN (FALSE))
10575
    {
10576
      emit_jump_insn (gen_return ());
10577
      DONE;
10578
    }
10579
  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
10580
        gen_rtvec (1, ret_rtx), VUNSPEC_EPILOGUE));
10581
  DONE;
10582
  "
10583
)
10584
 
10585
(define_insn "prologue_thumb1_interwork"
10586
  [(unspec_volatile [(const_int 0)] VUNSPEC_THUMB1_INTERWORK)]
10587
  "TARGET_THUMB1"
10588
  "* return thumb1_output_interwork ();"
10589
  [(set_attr "length" "8")]
10590
)
10591
 
10592
;; Note - although unspec_volatile's USE all hard registers,
10593
;; USEs are ignored after relaod has completed.  Thus we need
10594
;; to add an unspec of the link register to ensure that flow
10595
;; does not think that it is unused by the sibcall branch that
10596
;; will replace the standard function epilogue.
10597
(define_insn "sibcall_epilogue"
10598
  [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
10599
              (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
10600
  "TARGET_32BIT"
10601
  "*
10602
  if (use_return_insn (FALSE, next_nonnote_insn (insn)))
10603
    return output_return_instruction (const_true_rtx, FALSE, FALSE);
10604
  return arm_output_epilogue (next_nonnote_insn (insn));
10605
  "
10606
;; Length is absolute worst case
10607
  [(set_attr "length" "44")
10608
   (set_attr "type" "block")
10609
   ;; We don't clobber the conditions, but the potential length of this
10610
   ;; operation is sufficient to make conditionalizing the sequence
10611
   ;; unlikely to be profitable.
10612
   (set_attr "conds" "clob")]
10613
)
10614
 
10615
(define_insn "*epilogue_insns"
10616
  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
10617
  "TARGET_EITHER"
10618
  "*
10619
  if (TARGET_32BIT)
10620
    return arm_output_epilogue (NULL);
10621
  else /* TARGET_THUMB1 */
10622
    return thumb_unexpanded_epilogue ();
10623
  "
10624
  ; Length is absolute worst case
10625
  [(set_attr "length" "44")
10626
   (set_attr "type" "block")
10627
   ;; We don't clobber the conditions, but the potential length of this
10628
   ;; operation is sufficient to make conditionalizing the sequence
10629
   ;; unlikely to be profitable.
10630
   (set_attr "conds" "clob")]
10631
)
10632
 
10633
(define_expand "eh_epilogue"
10634
  [(use (match_operand:SI 0 "register_operand" ""))
10635
   (use (match_operand:SI 1 "register_operand" ""))
10636
   (use (match_operand:SI 2 "register_operand" ""))]
10637
  "TARGET_EITHER"
10638
  "
10639
  {
10640
    cfun->machine->eh_epilogue_sp_ofs = operands[1];
10641
    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
10642
      {
10643
        rtx ra = gen_rtx_REG (Pmode, 2);
10644
 
10645
        emit_move_insn (ra, operands[2]);
10646
        operands[2] = ra;
10647
      }
10648
    /* This is a hack -- we may have crystalized the function type too
10649
       early.  */
10650
    cfun->machine->func_type = 0;
10651
  }"
10652
)
10653
 
10654
;; This split is only used during output to reduce the number of patterns
10655
;; that need assembler instructions adding to them.  We allowed the setting
10656
;; of the conditions to be implicit during rtl generation so that
10657
;; the conditional compare patterns would work.  However this conflicts to
10658
;; some extent with the conditional data operations, so we have to split them
10659
;; up again here.
10660
 
10661
;; ??? Need to audit these splitters for Thumb-2.  Why isn't normal
10662
;; conditional execution sufficient?
10663
 
10664
(define_split
10665
  [(set (match_operand:SI 0 "s_register_operand" "")
10666
        (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10667
                          [(match_operand 2 "" "") (match_operand 3 "" "")])
10668
                         (match_dup 0)
10669
                         (match_operand 4 "" "")))
10670
   (clobber (reg:CC CC_REGNUM))]
10671
  "TARGET_ARM && reload_completed"
10672
  [(set (match_dup 5) (match_dup 6))
10673
   (cond_exec (match_dup 7)
10674
              (set (match_dup 0) (match_dup 4)))]
10675
  "
10676
  {
10677
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10678
                                             operands[2], operands[3]);
10679
    enum rtx_code rc = GET_CODE (operands[1]);
10680
 
10681
    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10682
    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10683
    if (mode == CCFPmode || mode == CCFPEmode)
10684
      rc = reverse_condition_maybe_unordered (rc);
10685
    else
10686
      rc = reverse_condition (rc);
10687
 
10688
    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
10689
  }"
10690
)
10691
 
10692
(define_split
10693
  [(set (match_operand:SI 0 "s_register_operand" "")
10694
        (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10695
                          [(match_operand 2 "" "") (match_operand 3 "" "")])
10696
                         (match_operand 4 "" "")
10697
                         (match_dup 0)))
10698
   (clobber (reg:CC CC_REGNUM))]
10699
  "TARGET_ARM && reload_completed"
10700
  [(set (match_dup 5) (match_dup 6))
10701
   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
10702
              (set (match_dup 0) (match_dup 4)))]
10703
  "
10704
  {
10705
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10706
                                             operands[2], operands[3]);
10707
 
10708
    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
10709
    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10710
  }"
10711
)
10712
 
10713
(define_split
10714
  [(set (match_operand:SI 0 "s_register_operand" "")
10715
        (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10716
                          [(match_operand 2 "" "") (match_operand 3 "" "")])
10717
                         (match_operand 4 "" "")
10718
                         (match_operand 5 "" "")))
10719
   (clobber (reg:CC CC_REGNUM))]
10720
  "TARGET_ARM && reload_completed"
10721
  [(set (match_dup 6) (match_dup 7))
10722
   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10723
              (set (match_dup 0) (match_dup 4)))
10724
   (cond_exec (match_dup 8)
10725
              (set (match_dup 0) (match_dup 5)))]
10726
  "
10727
  {
10728
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10729
                                             operands[2], operands[3]);
10730
    enum rtx_code rc = GET_CODE (operands[1]);
10731
 
10732
    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10733
    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10734
    if (mode == CCFPmode || mode == CCFPEmode)
10735
      rc = reverse_condition_maybe_unordered (rc);
10736
    else
10737
      rc = reverse_condition (rc);
10738
 
10739
    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10740
  }"
10741
)
10742
 
10743
(define_split
10744
  [(set (match_operand:SI 0 "s_register_operand" "")
10745
        (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10746
                          [(match_operand:SI 2 "s_register_operand" "")
10747
                           (match_operand:SI 3 "arm_add_operand" "")])
10748
                         (match_operand:SI 4 "arm_rhs_operand" "")
10749
                         (not:SI
10750
                          (match_operand:SI 5 "s_register_operand" ""))))
10751
   (clobber (reg:CC CC_REGNUM))]
10752
  "TARGET_ARM && reload_completed"
10753
  [(set (match_dup 6) (match_dup 7))
10754
   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10755
              (set (match_dup 0) (match_dup 4)))
10756
   (cond_exec (match_dup 8)
10757
              (set (match_dup 0) (not:SI (match_dup 5))))]
10758
  "
10759
  {
10760
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10761
                                             operands[2], operands[3]);
10762
    enum rtx_code rc = GET_CODE (operands[1]);
10763
 
10764
    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10765
    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10766
    if (mode == CCFPmode || mode == CCFPEmode)
10767
      rc = reverse_condition_maybe_unordered (rc);
10768
    else
10769
      rc = reverse_condition (rc);
10770
 
10771
    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10772
  }"
10773
)
10774
 
10775
(define_insn "*cond_move_not"
10776
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10777
        (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10778
                          [(match_operand 3 "cc_register" "") (const_int 0)])
10779
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10780
                         (not:SI
10781
                          (match_operand:SI 2 "s_register_operand" "r,r"))))]
10782
  "TARGET_ARM"
10783
  "@
10784
   mvn%D4\\t%0, %2
10785
   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10786
  [(set_attr "conds" "use")
10787
   (set_attr "insn" "mvn")
10788
   (set_attr "length" "4,8")]
10789
)
10790
 
10791
;; The next two patterns occur when an AND operation is followed by a
10792
;; scc insn sequence
10793
 
10794
(define_insn "*sign_extract_onebit"
10795
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10796
        (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10797
                         (const_int 1)
10798
                         (match_operand:SI 2 "const_int_operand" "n")))
10799
    (clobber (reg:CC CC_REGNUM))]
10800
  "TARGET_ARM"
10801
  "*
10802
    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10803
    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10804
    return \"mvnne\\t%0, #0\";
10805
  "
10806
  [(set_attr "conds" "clob")
10807
   (set_attr "length" "8")]
10808
)
10809
 
10810
(define_insn "*not_signextract_onebit"
10811
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10812
        (not:SI
10813
         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10814
                          (const_int 1)
10815
                          (match_operand:SI 2 "const_int_operand" "n"))))
10816
   (clobber (reg:CC CC_REGNUM))]
10817
  "TARGET_ARM"
10818
  "*
10819
    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10820
    output_asm_insn (\"tst\\t%1, %2\", operands);
10821
    output_asm_insn (\"mvneq\\t%0, #0\", operands);
10822
    return \"movne\\t%0, #0\";
10823
  "
10824
  [(set_attr "conds" "clob")
10825
   (set_attr "length" "12")]
10826
)
10827
;; ??? The above patterns need auditing for Thumb-2
10828
 
10829
;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10830
;; expressions.  For simplicity, the first register is also in the unspec
10831
;; part.
10832
;; To avoid the usage of GNU extension, the length attribute is computed
10833
;; in a C function arm_attr_length_push_multi.
10834
(define_insn "*push_multi"
10835
  [(match_parallel 2 "multi_register_push"
10836
    [(set (match_operand:BLK 0 "push_mult_memory_operand" "")
10837
          (unspec:BLK [(match_operand:SI 1 "s_register_operand" "")]
10838
                      UNSPEC_PUSH_MULT))])]
10839
  ""
10840
  "*
10841
  {
10842
    int num_saves = XVECLEN (operands[2], 0);
10843
 
10844
    /* For the StrongARM at least it is faster to
10845
       use STR to store only a single register.
10846
       In Thumb mode always use push, and the assembler will pick
10847
       something appropriate.  */
10848
    if (num_saves == 1 && TARGET_ARM)
10849
      output_asm_insn (\"str%?\\t%1, [%m0, #-4]!\", operands);
10850
    else
10851
      {
10852
        int i;
10853
        char pattern[100];
10854
 
10855
        if (TARGET_ARM)
10856
            strcpy (pattern, \"stm%(fd%)\\t%m0!, {%1\");
10857
        else if (TARGET_THUMB2)
10858
            strcpy (pattern, \"push%?\\t{%1\");
10859
        else
10860
            strcpy (pattern, \"push\\t{%1\");
10861
 
10862
        for (i = 1; i < num_saves; i++)
10863
          {
10864
            strcat (pattern, \", %|\");
10865
            strcat (pattern,
10866
                    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10867
          }
10868
 
10869
        strcat (pattern, \"}\");
10870
        output_asm_insn (pattern, operands);
10871
      }
10872
 
10873
    return \"\";
10874
  }"
10875
  [(set_attr "type" "store4")
10876
   (set (attr "length")
10877
        (symbol_ref "arm_attr_length_push_multi (operands[2], operands[1])"))]
10878
)
10879
 
10880
(define_insn "stack_tie"
10881
  [(set (mem:BLK (scratch))
10882
        (unspec:BLK [(match_operand:SI 0 "s_register_operand" "rk")
10883
                     (match_operand:SI 1 "s_register_operand" "rk")]
10884
                    UNSPEC_PRLG_STK))]
10885
  ""
10886
  ""
10887
  [(set_attr "length" "0")]
10888
)
10889
 
10890
;; Similarly for the floating point registers
10891
(define_insn "*push_fp_multi"
10892
  [(match_parallel 2 "multi_register_push"
10893
    [(set (match_operand:BLK 0 "memory_operand" "=m")
10894
          (unspec:BLK [(match_operand:XF 1 "f_register_operand" "")]
10895
                      UNSPEC_PUSH_MULT))])]
10896
  "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FPA"
10897
  "*
10898
  {
10899
    char pattern[100];
10900
 
10901
    sprintf (pattern, \"sfm%%(fd%%)\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10902
    output_asm_insn (pattern, operands);
10903
    return \"\";
10904
  }"
10905
  [(set_attr "type" "f_fpa_store")]
10906
)
10907
 
10908
;; Special patterns for dealing with the constant pool
10909
 
10910
(define_insn "align_4"
10911
  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10912
  "TARGET_EITHER"
10913
  "*
10914
  assemble_align (32);
10915
  return \"\";
10916
  "
10917
)
10918
 
10919
(define_insn "align_8"
10920
  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10921
  "TARGET_EITHER"
10922
  "*
10923
  assemble_align (64);
10924
  return \"\";
10925
  "
10926
)
10927
 
10928
(define_insn "consttable_end"
10929
  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10930
  "TARGET_EITHER"
10931
  "*
10932
  making_const_table = FALSE;
10933
  return \"\";
10934
  "
10935
)
10936
 
10937
(define_insn "consttable_1"
10938
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10939
  "TARGET_THUMB1"
10940
  "*
10941
  making_const_table = TRUE;
10942
  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10943
  assemble_zeros (3);
10944
  return \"\";
10945
  "
10946
  [(set_attr "length" "4")]
10947
)
10948
 
10949
(define_insn "consttable_2"
10950
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10951
  "TARGET_THUMB1"
10952
  "*
10953
  making_const_table = TRUE;
10954
  gcc_assert (GET_MODE_CLASS (GET_MODE (operands[0])) != MODE_FLOAT);
10955
  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10956
  assemble_zeros (2);
10957
  return \"\";
10958
  "
10959
  [(set_attr "length" "4")]
10960
)
10961
 
10962
(define_insn "consttable_4"
10963
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10964
  "TARGET_EITHER"
10965
  "*
10966
  {
10967
    rtx x = operands[0];
10968
    making_const_table = TRUE;
10969
    switch (GET_MODE_CLASS (GET_MODE (x)))
10970
      {
10971
      case MODE_FLOAT:
10972
        if (GET_MODE (x) == HFmode)
10973
          arm_emit_fp16_const (x);
10974
        else
10975
          {
10976
            REAL_VALUE_TYPE r;
10977
            REAL_VALUE_FROM_CONST_DOUBLE (r, x);
10978
            assemble_real (r, GET_MODE (x), BITS_PER_WORD);
10979
          }
10980
        break;
10981
      default:
10982
        /* XXX: Sometimes gcc does something really dumb and ends up with
10983
           a HIGH in a constant pool entry, usually because it's trying to
10984
           load into a VFP register.  We know this will always be used in
10985
           combination with a LO_SUM which ignores the high bits, so just
10986
           strip off the HIGH.  */
10987
        if (GET_CODE (x) == HIGH)
10988
          x = XEXP (x, 0);
10989
        assemble_integer (x, 4, BITS_PER_WORD, 1);
10990
        mark_symbol_refs_as_used (x);
10991
        break;
10992
      }
10993
    return \"\";
10994
  }"
10995
  [(set_attr "length" "4")]
10996
)
10997
 
10998
(define_insn "consttable_8"
10999
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
11000
  "TARGET_EITHER"
11001
  "*
11002
  {
11003
    making_const_table = TRUE;
11004
    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11005
      {
11006
       case MODE_FLOAT:
11007
        {
11008
          REAL_VALUE_TYPE r;
11009
          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11010
          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11011
          break;
11012
        }
11013
      default:
11014
        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
11015
        break;
11016
      }
11017
    return \"\";
11018
  }"
11019
  [(set_attr "length" "8")]
11020
)
11021
 
11022
(define_insn "consttable_16"
11023
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
11024
  "TARGET_EITHER"
11025
  "*
11026
  {
11027
    making_const_table = TRUE;
11028
    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
11029
      {
11030
       case MODE_FLOAT:
11031
        {
11032
          REAL_VALUE_TYPE r;
11033
          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
11034
          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
11035
          break;
11036
        }
11037
      default:
11038
        assemble_integer (operands[0], 16, BITS_PER_WORD, 1);
11039
        break;
11040
      }
11041
    return \"\";
11042
  }"
11043
  [(set_attr "length" "16")]
11044
)
11045
 
11046
;; Miscellaneous Thumb patterns
11047
 
11048
(define_expand "tablejump"
11049
  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
11050
              (use (label_ref (match_operand 1 "" "")))])]
11051
  "TARGET_THUMB1"
11052
  "
11053
  if (flag_pic)
11054
    {
11055
      /* Hopefully, CSE will eliminate this copy.  */
11056
      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
11057
      rtx reg2 = gen_reg_rtx (SImode);
11058
 
11059
      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
11060
      operands[0] = reg2;
11061
    }
11062
  "
11063
)
11064
 
11065
;; NB never uses BX.
11066
(define_insn "*thumb1_tablejump"
11067
  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
11068
   (use (label_ref (match_operand 1 "" "")))]
11069
  "TARGET_THUMB1"
11070
  "mov\\t%|pc, %0"
11071
  [(set_attr "length" "2")]
11072
)
11073
 
11074
;; V5 Instructions,
11075
 
11076
(define_insn "clzsi2"
11077
  [(set (match_operand:SI 0 "s_register_operand" "=r")
11078
        (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
11079
  "TARGET_32BIT && arm_arch5"
11080
  "clz%?\\t%0, %1"
11081
  [(set_attr "predicable" "yes")
11082
   (set_attr "insn" "clz")])
11083
 
11084
(define_insn "rbitsi2"
11085
  [(set (match_operand:SI 0 "s_register_operand" "=r")
11086
        (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] UNSPEC_RBIT))]
11087
  "TARGET_32BIT && arm_arch_thumb2"
11088
  "rbit%?\\t%0, %1"
11089
  [(set_attr "predicable" "yes")
11090
   (set_attr "insn" "clz")])
11091
 
11092
(define_expand "ctzsi2"
11093
 [(set (match_operand:SI           0 "s_register_operand" "")
11094
       (ctz:SI (match_operand:SI  1 "s_register_operand" "")))]
11095
  "TARGET_32BIT && arm_arch_thumb2"
11096
  "
11097
   {
11098
     rtx tmp = gen_reg_rtx (SImode);
11099
     emit_insn (gen_rbitsi2 (tmp, operands[1]));
11100
     emit_insn (gen_clzsi2 (operands[0], tmp));
11101
   }
11102
   DONE;
11103
  "
11104
)
11105
 
11106
;; V5E instructions.
11107
 
11108
(define_insn "prefetch"
11109
  [(prefetch (match_operand:SI 0 "address_operand" "p")
11110
             (match_operand:SI 1 "" "")
11111
             (match_operand:SI 2 "" ""))]
11112
  "TARGET_32BIT && arm_arch5e"
11113
  "pld\\t%a0")
11114
 
11115
;; General predication pattern
11116
 
11117
(define_cond_exec
11118
  [(match_operator 0 "arm_comparison_operator"
11119
    [(match_operand 1 "cc_register" "")
11120
     (const_int 0)])]
11121
  "TARGET_32BIT"
11122
  ""
11123
)
11124
 
11125
(define_insn "prologue_use"
11126
  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
11127
  ""
11128
  "%@ %0 needed for prologue"
11129
  [(set_attr "length" "0")]
11130
)
11131
 
11132
 
11133
;; Patterns for exception handling
11134
 
11135
(define_expand "eh_return"
11136
  [(use (match_operand 0 "general_operand" ""))]
11137
  "TARGET_EITHER"
11138
  "
11139
  {
11140
    if (TARGET_32BIT)
11141
      emit_insn (gen_arm_eh_return (operands[0]));
11142
    else
11143
      emit_insn (gen_thumb_eh_return (operands[0]));
11144
    DONE;
11145
  }"
11146
)
11147
 
11148
;; We can't expand this before we know where the link register is stored.
11149
(define_insn_and_split "arm_eh_return"
11150
  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
11151
                    VUNSPEC_EH_RETURN)
11152
   (clobber (match_scratch:SI 1 "=&r"))]
11153
  "TARGET_ARM"
11154
  "#"
11155
  "&& reload_completed"
11156
  [(const_int 0)]
11157
  "
11158
  {
11159
    arm_set_return_address (operands[0], operands[1]);
11160
    DONE;
11161
  }"
11162
)
11163
 
11164
(define_insn_and_split "thumb_eh_return"
11165
  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
11166
                    VUNSPEC_EH_RETURN)
11167
   (clobber (match_scratch:SI 1 "=&l"))]
11168
  "TARGET_THUMB1"
11169
  "#"
11170
  "&& reload_completed"
11171
  [(const_int 0)]
11172
  "
11173
  {
11174
    thumb_set_return_address (operands[0], operands[1]);
11175
    DONE;
11176
  }"
11177
)
11178
 
11179
 
11180
;; TLS support
11181
 
11182
(define_insn "load_tp_hard"
11183
  [(set (match_operand:SI 0 "register_operand" "=r")
11184
        (unspec:SI [(const_int 0)] UNSPEC_TLS))]
11185
  "TARGET_HARD_TP"
11186
  "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
11187
  [(set_attr "predicable" "yes")]
11188
)
11189
 
11190
;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
11191
(define_insn "load_tp_soft"
11192
  [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
11193
   (clobber (reg:SI LR_REGNUM))
11194
   (clobber (reg:SI IP_REGNUM))
11195
   (clobber (reg:CC CC_REGNUM))]
11196
  "TARGET_SOFT_TP"
11197
  "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
11198
  [(set_attr "conds" "clob")]
11199
)
11200
 
11201
;; tls descriptor call
11202
(define_insn "tlscall"
11203
  [(set (reg:SI R0_REGNUM)
11204
        (unspec:SI [(reg:SI R0_REGNUM)
11205
                    (match_operand:SI 0 "" "X")
11206
                    (match_operand 1 "" "")] UNSPEC_TLS))
11207
   (clobber (reg:SI R1_REGNUM))
11208
   (clobber (reg:SI LR_REGNUM))
11209
   (clobber (reg:SI CC_REGNUM))]
11210
  "TARGET_GNU2_TLS"
11211
  {
11212
    targetm.asm_out.internal_label (asm_out_file, "LPIC",
11213
                                    INTVAL (operands[1]));
11214
    return "bl\\t%c0(tlscall)";
11215
  }
11216
  [(set_attr "conds" "clob")
11217
   (set_attr "length" "4")]
11218
)
11219
 
11220
;;
11221
 
11222
;; We only care about the lower 16 bits of the constant
11223
;; being inserted into the upper 16 bits of the register.
11224
(define_insn "*arm_movtas_ze"
11225
  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
11226
                   (const_int 16)
11227
                   (const_int 16))
11228
        (match_operand:SI 1 "const_int_operand" ""))]
11229
  "arm_arch_thumb2"
11230
  "movt%?\t%0, %L1"
11231
 [(set_attr "predicable" "yes")
11232
   (set_attr "length" "4")]
11233
)
11234
 
11235
(define_insn "*arm_rev"
11236
  [(set (match_operand:SI 0 "s_register_operand" "=r")
11237
        (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11238
  "TARGET_32BIT && arm_arch6"
11239
  "rev%?\t%0, %1"
11240
  [(set_attr "predicable" "yes")
11241
   (set_attr "length" "4")]
11242
)
11243
 
11244
(define_insn "*thumb1_rev"
11245
  [(set (match_operand:SI 0 "s_register_operand" "=l")
11246
        (bswap:SI (match_operand:SI 1 "s_register_operand" "l")))]
11247
  "TARGET_THUMB1 && arm_arch6"
11248
   "rev\t%0, %1"
11249
  [(set_attr "length" "2")]
11250
)
11251
 
11252
(define_expand "arm_legacy_rev"
11253
  [(set (match_operand:SI 2 "s_register_operand" "")
11254
        (xor:SI (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
11255
                             (const_int 16))
11256
                (match_dup 1)))
11257
   (set (match_dup 2)
11258
        (lshiftrt:SI (match_dup 2)
11259
                     (const_int 8)))
11260
   (set (match_operand:SI 3 "s_register_operand" "")
11261
        (rotatert:SI (match_dup 1)
11262
                     (const_int 8)))
11263
   (set (match_dup 2)
11264
        (and:SI (match_dup 2)
11265
                (const_int -65281)))
11266
   (set (match_operand:SI 0 "s_register_operand" "")
11267
        (xor:SI (match_dup 3)
11268
                (match_dup 2)))]
11269
  "TARGET_32BIT"
11270
  ""
11271
)
11272
 
11273
;; Reuse temporaries to keep register pressure down.
11274
(define_expand "thumb_legacy_rev"
11275
  [(set (match_operand:SI 2 "s_register_operand" "")
11276
     (ashift:SI (match_operand:SI 1 "s_register_operand" "")
11277
                (const_int 24)))
11278
   (set (match_operand:SI 3 "s_register_operand" "")
11279
     (lshiftrt:SI (match_dup 1)
11280
                  (const_int 24)))
11281
   (set (match_dup 3)
11282
     (ior:SI (match_dup 3)
11283
             (match_dup 2)))
11284
   (set (match_operand:SI 4 "s_register_operand" "")
11285
     (const_int 16))
11286
   (set (match_operand:SI 5 "s_register_operand" "")
11287
     (rotatert:SI (match_dup 1)
11288
                  (match_dup 4)))
11289
   (set (match_dup 2)
11290
     (ashift:SI (match_dup 5)
11291
                (const_int 24)))
11292
   (set (match_dup 5)
11293
     (lshiftrt:SI (match_dup 5)
11294
                  (const_int 24)))
11295
   (set (match_dup 5)
11296
     (ior:SI (match_dup 5)
11297
             (match_dup 2)))
11298
   (set (match_dup 5)
11299
     (rotatert:SI (match_dup 5)
11300
                  (match_dup 4)))
11301
   (set (match_operand:SI 0 "s_register_operand" "")
11302
     (ior:SI (match_dup 5)
11303
             (match_dup 3)))]
11304
  "TARGET_THUMB"
11305
  ""
11306
)
11307
 
11308
(define_expand "bswapsi2"
11309
  [(set (match_operand:SI 0 "s_register_operand" "=r")
11310
        (bswap:SI (match_operand:SI 1 "s_register_operand" "r")))]
11311
"TARGET_EITHER && (arm_arch6 || !optimize_size)"
11312
"
11313
    if (!arm_arch6)
11314
      {
11315
        rtx op2 = gen_reg_rtx (SImode);
11316
        rtx op3 = gen_reg_rtx (SImode);
11317
 
11318
        if (TARGET_THUMB)
11319
          {
11320
            rtx op4 = gen_reg_rtx (SImode);
11321
            rtx op5 = gen_reg_rtx (SImode);
11322
 
11323
            emit_insn (gen_thumb_legacy_rev (operands[0], operands[1],
11324
                                             op2, op3, op4, op5));
11325
          }
11326
        else
11327
          {
11328
            emit_insn (gen_arm_legacy_rev (operands[0], operands[1],
11329
                                           op2, op3));
11330
          }
11331
 
11332
        DONE;
11333
      }
11334
  "
11335
)
11336
 
11337
;; Load the load/store multiple patterns
11338
(include "ldmstm.md")
11339
;; Load the FPA co-processor patterns
11340
(include "fpa.md")
11341
;; Load the Maverick co-processor patterns
11342
(include "cirrus.md")
11343
;; Vector bits common to IWMMXT and Neon
11344
(include "vec-common.md")
11345
;; Load the Intel Wireless Multimedia Extension patterns
11346
(include "iwmmxt.md")
11347
;; Load the VFP co-processor patterns
11348
(include "vfp.md")
11349
;; Thumb-2 patterns
11350
(include "thumb2.md")
11351
;; Neon patterns
11352
(include "neon.md")
11353
;; Synchronization Primitives
11354
(include "sync.md")
11355
;; Fixed-point patterns
11356
(include "arm-fixed.md")

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.