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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [arm/] [arm.md] - Blame information for rev 825

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

Line No. Rev Author Line
1 38 julius
;;- 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  Free Software Foundation, Inc.
4
;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5
;;  and Martin Simmons (@harleqn.co.uk).
6
;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
 
8
;; This file is part of GCC.
9
 
10
;; GCC is free software; you can redistribute it and/or modify it
11
;; under the terms of the GNU General Public License as published
12
;; by the Free Software Foundation; either version 3, or (at your
13
;; option) any later version.
14
 
15
;; GCC is distributed in the hope that it will be useful, but WITHOUT
16
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17
;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18
;; License for more details.
19
 
20
;; You should have received a copy of the GNU General Public License
21
;; along with GCC; see the file COPYING3.  If not see
22
;; .
23
 
24
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25
 
26
 
27
;;---------------------------------------------------------------------------
28
;; Constants
29
 
30
;; Register numbers
31
(define_constants
32
  [(R0_REGNUM        0)         ; First CORE register
33
   (IP_REGNUM       12)         ; Scratch register
34
   (SP_REGNUM       13)         ; Stack pointer
35
   (LR_REGNUM       14)         ; Return address register
36
   (PC_REGNUM       15)         ; Program counter
37
   (CC_REGNUM       24)         ; Condition code pseudo register
38
   (LAST_ARM_REGNUM 15)         ;
39
   (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
40
   (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
41
  ]
42
)
43
;; 3rd operand to select_dominance_cc_mode
44
(define_constants
45
  [(DOM_CC_X_AND_Y  0)
46
   (DOM_CC_NX_OR_Y  1)
47
   (DOM_CC_X_OR_Y   2)
48
  ]
49
)
50
 
51
;; UNSPEC Usage:
52
;; Note: sin and cos are no-longer used.
53
 
54
(define_constants
55
  [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
56
                        ;   operand 0 is the result,
57
                        ;   operand 1 the parameter.
58
   (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
59
                        ;   operand 0 is the result,
60
                        ;   operand 1 the parameter.
61
   (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
62
                        ;   operand 0 is the first register,
63
                        ;   subsequent registers are in parallel (use ...)
64
                        ;   expressions.
65
   (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
66
                        ;   usage, that is, we will add the pic_register
67
                        ;   value to it before trying to dereference it.
68
   (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
69
                        ;   GLOBAL_OFFSET_TABLE.  The operation is fully
70
                        ;   described by the RTL but must be wrapped to
71
                        ;   prevent combine from trying to rip it apart.
72
   (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses
73
                        ;   being scheduled before the stack adjustment insn.
74
   (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
75
                        ; this unspec is used to prevent the deletion of
76
                        ; instructions setting registers for EH handling
77
                        ; and stack frame generation.  Operand 0 is the
78
                        ; register to "use".
79
   (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
80
   (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
81
   (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
82
   (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
83
   (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
84
   (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
85
   (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
86
   (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
87
   (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
88
   (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
89
   (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
90
   (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
91
   (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
92
   (UNSPEC_TLS      20) ; A symbol that has been treated properly for TLS usage.
93
   (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
94
                         ; instruction stream.
95
  ]
96
)
97
 
98
;; UNSPEC_VOLATILE Usage:
99
 
100
(define_constants
101
  [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
102
                        ;   insn in the code.
103
   (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
104
                        ;   instruction epilogue sequence that isn't expanded
105
                        ;   into normal RTL.  Used for both normal and sibcall
106
                        ;   epilogues.
107
   (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table
108
                        ;   for inlined constants.
109
   (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
110
                        ;   table.
111
   (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
112
                        ;   an 8-bit object.
113
   (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
114
                        ;   a 16-bit object.
115
   (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
116
                        ;   a 32-bit object.
117
   (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
118
                        ;   a 64-bit object.
119
   (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
120
   (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
121
   (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
122
   (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
123
   (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
124
   (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
125
   (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
126
                         ; handling.
127
  ]
128
)
129
 
130
;;---------------------------------------------------------------------------
131
;; Attributes
132
 
133
; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
134
; generating ARM code.  This is used to control the length of some insn
135
; patterns that share the same RTL in both ARM and Thumb code.
136
(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
137
 
138
; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
139
; scheduling decisions for the load unit and the multiplier.
140
(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
141
 
142
; IS_XSCALE is set to 'yes' when compiling for XScale.
143
(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
144
 
145
;; Operand number of an input operand that is shifted.  Zero if the
146
;; given instruction does not shift one of its input operands.
147
(define_attr "shift" "" (const_int 0))
148
 
149
; Floating Point Unit.  If we only have floating point emulation, then there
150
; is no point in scheduling the floating point insns.  (Well, for best
151
; performance we should try and group them together).
152
(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
153
  (const (symbol_ref "arm_fpu_attr")))
154
 
155
; LENGTH of an instruction (in bytes)
156
(define_attr "length" "" (const_int 4))
157
 
158
; POOL_RANGE is how far away from a constant pool entry that this insn
159
; can be placed.  If the distance is zero, then this insn will never
160
; reference the pool.
161
; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
162
; before its address.
163
(define_attr "pool_range" "" (const_int 0))
164
(define_attr "neg_pool_range" "" (const_int 0))
165
 
166
; An assembler sequence may clobber the condition codes without us knowing.
167
; If such an insn references the pool, then we have no way of knowing how,
168
; so use the most conservative value for pool_range.
169
(define_asm_attributes
170
 [(set_attr "conds" "clob")
171
  (set_attr "length" "4")
172
  (set_attr "pool_range" "250")])
173
 
174
;; The instruction used to implement a particular pattern.  This
175
;; information is used by pipeline descriptions to provide accurate
176
;; scheduling information.
177
 
178
(define_attr "insn"
179
        "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,other"
180
        (const_string "other"))
181
 
182
; TYPE attribute is used to detect floating point instructions which, if
183
; running on a co-processor can run in parallel with other, basic instructions
184
; If write-buffer scheduling is enabled then it can also be used in the
185
; scheduling of writes.
186
 
187
; Classification of each insn
188
; alu           any alu  instruction that doesn't hit memory or fp
189
;               regs or have a shifted source operand
190
; alu_shift     any data instruction that doesn't hit memory or fp
191
;               regs, but has a source operand shifted by a constant
192
; alu_shift_reg any data instruction that doesn't hit memory or fp
193
;               regs, but has a source operand shifted by a register value
194
; mult          a multiply instruction
195
; block         blockage insn, this blocks all functional units
196
; float         a floating point arithmetic operation (subject to expansion)
197
; fdivd         DFmode floating point division
198
; fdivs         SFmode floating point division
199
; fmul          Floating point multiply
200
; ffmul         Fast floating point multiply
201
; farith        Floating point arithmetic (4 cycle)
202
; ffarith       Fast floating point arithmetic (2 cycle)
203
; float_em      a floating point arithmetic operation that is normally emulated
204
;               even on a machine with an fpa.
205
; f_load        a floating point load from memory
206
; f_store       a floating point store to memory
207
; f_load[sd]    single/double load from memory
208
; f_store[sd]   single/double store to memory
209
; f_flag        a transfer of co-processor flags to the CPSR
210
; f_mem_r       a transfer of a floating point register to a real reg via mem
211
; r_mem_f       the reverse of f_mem_r
212
; f_2_r         fast transfer float to arm (no memory needed)
213
; r_2_f         fast transfer arm to float
214
; f_cvt         convert floating<->integral
215
; branch        a branch
216
; call          a subroutine call
217
; load_byte     load byte(s) from memory to arm registers
218
; load1         load 1 word from memory to arm registers
219
; load2         load 2 words from memory to arm registers
220
; load3         load 3 words from memory to arm registers
221
; load4         load 4 words from memory to arm registers
222
; store         store 1 word to memory from arm registers
223
; store2        store 2 words
224
; store3        store 3 words
225
; store4        store 4 (or more) words
226
;  Additions for Cirrus Maverick co-processor:
227
; mav_farith    Floating point arithmetic (4 cycle)
228
; mav_dmult     Double multiplies (7 cycle)
229
;
230
(define_attr "type"
231
        "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_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"
232
        (if_then_else
233
         (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
234
         (const_string "mult")
235
         (const_string "alu")))
236
 
237
; Load scheduling, set from the arm_ld_sched variable
238
; initialized by arm_override_options()
239
(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
240
 
241
; condition codes: this one is used by final_prescan_insn to speed up
242
; conditionalizing instructions.  It saves having to scan the rtl to see if
243
; it uses or alters the condition codes.
244
;
245
; USE means that the condition codes are used by the insn in the process of
246
;   outputting code, this means (at present) that we can't use the insn in
247
;   inlined branches
248
;
249
; SET means that the purpose of the insn is to set the condition codes in a
250
;   well defined manner.
251
;
252
; CLOB means that the condition codes are altered in an undefined manner, if
253
;   they are altered at all
254
;
255
; JUMP_CLOB is used when the condition cannot be represented by a single
256
;   instruction (UNEQ and LTGT).  These cannot be predicated.
257
;
258
; NOCOND means that the condition codes are neither altered nor affect the
259
;   output of this insn
260
 
261
(define_attr "conds" "use,set,clob,jump_clob,nocond"
262
        (if_then_else (eq_attr "type" "call")
263
         (const_string "clob")
264
         (const_string "nocond")))
265
 
266
; Predicable means that the insn can be conditionally executed based on
267
; an automatically added predicate (additional patterns are generated by
268
; gen...).  We default to 'no' because no Thumb patterns match this rule
269
; and not all ARM patterns do.
270
(define_attr "predicable" "no,yes" (const_string "no"))
271
 
272
; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
273
; have one.  Later ones, such as StrongARM, have write-back caches, so don't
274
; suffer blockages enough to warrant modelling this (and it can adversely
275
; affect the schedule).
276
(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
277
 
278
; WRITE_CONFLICT implies that a read following an unrelated write is likely
279
; to stall the processor.  Used with model_wbuf above.
280
(define_attr "write_conflict" "no,yes"
281
  (if_then_else (eq_attr "type"
282
                 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
283
                (const_string "yes")
284
                (const_string "no")))
285
 
286
; Classify the insns into those that take one cycle and those that take more
287
; than one on the main cpu execution unit.
288
(define_attr "core_cycles" "single,multi"
289
  (if_then_else (eq_attr "type"
290
                 "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
291
                (const_string "single")
292
                (const_string "multi")))
293
 
294
;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
295
;; distant label.  Only applicable to Thumb code.
296
(define_attr "far_jump" "yes,no" (const_string "no"))
297
 
298
 
299
;;---------------------------------------------------------------------------
300
;; Mode macros
301
 
302
; A list of modes that are exactly 64 bits in size.  We use this to expand
303
; some splits that are the same for all modes when operating on ARM
304
; registers.
305
(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
306
 
307
;;---------------------------------------------------------------------------
308
;; Predicates
309
 
310
(include "predicates.md")
311
(include "constraints.md")
312
 
313
;;---------------------------------------------------------------------------
314
;; Pipeline descriptions
315
 
316
;; Processor type.  This is created automatically from arm-cores.def.
317
(include "arm-tune.md")
318
 
319
;; True if the generic scheduling description should be used.
320
 
321
(define_attr "generic_sched" "yes,no"
322
  (const (if_then_else
323
          (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
324
          (const_string "no")
325
          (const_string "yes"))))
326
 
327
(define_attr "generic_vfp" "yes,no"
328
  (const (if_then_else
329
          (and (eq_attr "fpu" "vfp")
330
               (eq_attr "tune" "!arm1020e,arm1022e"))
331
          (const_string "yes")
332
          (const_string "no"))))
333
 
334
(include "arm-generic.md")
335
(include "arm926ejs.md")
336
(include "arm1020e.md")
337
(include "arm1026ejs.md")
338
(include "arm1136jfs.md")
339
 
340
 
341
;;---------------------------------------------------------------------------
342
;; Insn patterns
343
;;
344
;; Addition insns.
345
 
346
;; Note: For DImode insns, there is normally no reason why operands should
347
;; not be in the same register, what we don't want is for something being
348
;; written to partially overlap something that is an input.
349
;; Cirrus 64bit additions should not be split because we have a native
350
;; 64bit addition instructions.
351
 
352
(define_expand "adddi3"
353
 [(parallel
354
   [(set (match_operand:DI           0 "s_register_operand" "")
355
          (plus:DI (match_operand:DI 1 "s_register_operand" "")
356
                   (match_operand:DI 2 "s_register_operand" "")))
357
    (clobber (reg:CC CC_REGNUM))])]
358
  "TARGET_EITHER"
359
  "
360
  if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
361
    {
362
      if (!cirrus_fp_register (operands[0], DImode))
363
        operands[0] = force_reg (DImode, operands[0]);
364
      if (!cirrus_fp_register (operands[1], DImode))
365
        operands[1] = force_reg (DImode, operands[1]);
366
      emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
367
      DONE;
368
    }
369
 
370
  if (TARGET_THUMB)
371
    {
372
      if (GET_CODE (operands[1]) != REG)
373
        operands[1] = force_reg (SImode, operands[1]);
374
      if (GET_CODE (operands[2]) != REG)
375
        operands[2] = force_reg (SImode, operands[2]);
376
     }
377
  "
378
)
379
 
380
(define_insn "*thumb_adddi3"
381
  [(set (match_operand:DI          0 "register_operand" "=l")
382
        (plus:DI (match_operand:DI 1 "register_operand" "%0")
383
                 (match_operand:DI 2 "register_operand" "l")))
384
   (clobber (reg:CC CC_REGNUM))
385
  ]
386
  "TARGET_THUMB"
387
  "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388
  [(set_attr "length" "4")]
389
)
390
 
391
(define_insn_and_split "*arm_adddi3"
392
  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
393
        (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394
                 (match_operand:DI 2 "s_register_operand" "r,  0")))
395
   (clobber (reg:CC CC_REGNUM))]
396
  "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
397
  "#"
398
  "TARGET_ARM && reload_completed"
399
  [(parallel [(set (reg:CC_C CC_REGNUM)
400
                   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
401
                                 (match_dup 1)))
402
              (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403
   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404
                               (plus:SI (match_dup 4) (match_dup 5))))]
405
  "
406
  {
407
    operands[3] = gen_highpart (SImode, operands[0]);
408
    operands[0] = gen_lowpart (SImode, operands[0]);
409
    operands[4] = gen_highpart (SImode, operands[1]);
410
    operands[1] = gen_lowpart (SImode, operands[1]);
411
    operands[5] = gen_highpart (SImode, operands[2]);
412
    operands[2] = gen_lowpart (SImode, operands[2]);
413
  }"
414
  [(set_attr "conds" "clob")
415
   (set_attr "length" "8")]
416
)
417
 
418
(define_insn_and_split "*adddi_sesidi_di"
419
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420
        (plus:DI (sign_extend:DI
421
                  (match_operand:SI 2 "s_register_operand" "r,r"))
422
                 (match_operand:DI 1 "s_register_operand" "r,0")))
423
   (clobber (reg:CC CC_REGNUM))]
424
  "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
425
  "#"
426
  "TARGET_ARM && reload_completed"
427
  [(parallel [(set (reg:CC_C CC_REGNUM)
428
                   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
429
                                 (match_dup 1)))
430
              (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431
   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432
                               (plus:SI (ashiftrt:SI (match_dup 2)
433
                                                     (const_int 31))
434
                                        (match_dup 4))))]
435
  "
436
  {
437
    operands[3] = gen_highpart (SImode, operands[0]);
438
    operands[0] = gen_lowpart (SImode, operands[0]);
439
    operands[4] = gen_highpart (SImode, operands[1]);
440
    operands[1] = gen_lowpart (SImode, operands[1]);
441
    operands[2] = gen_lowpart (SImode, operands[2]);
442
  }"
443
  [(set_attr "conds" "clob")
444
   (set_attr "length" "8")]
445
)
446
 
447
(define_insn_and_split "*adddi_zesidi_di"
448
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449
        (plus:DI (zero_extend:DI
450
                  (match_operand:SI 2 "s_register_operand" "r,r"))
451
                 (match_operand:DI 1 "s_register_operand" "r,0")))
452
   (clobber (reg:CC CC_REGNUM))]
453
  "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
454
  "#"
455
  "TARGET_ARM && reload_completed"
456
  [(parallel [(set (reg:CC_C CC_REGNUM)
457
                   (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
458
                                 (match_dup 1)))
459
              (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460
   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461
                               (plus:SI (match_dup 4) (const_int 0))))]
462
  "
463
  {
464
    operands[3] = gen_highpart (SImode, operands[0]);
465
    operands[0] = gen_lowpart (SImode, operands[0]);
466
    operands[4] = gen_highpart (SImode, operands[1]);
467
    operands[1] = gen_lowpart (SImode, operands[1]);
468
    operands[2] = gen_lowpart (SImode, operands[2]);
469
  }"
470
  [(set_attr "conds" "clob")
471
   (set_attr "length" "8")]
472
)
473
 
474
(define_expand "addsi3"
475
  [(set (match_operand:SI          0 "s_register_operand" "")
476
        (plus:SI (match_operand:SI 1 "s_register_operand" "")
477
                 (match_operand:SI 2 "reg_or_int_operand" "")))]
478
  "TARGET_EITHER"
479
  "
480
  if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
481
    {
482
      arm_split_constant (PLUS, SImode, NULL_RTX,
483
                          INTVAL (operands[2]), operands[0], operands[1],
484
                          optimize && !no_new_pseudos);
485
      DONE;
486
    }
487
  "
488
)
489
 
490
; If there is a scratch available, this will be faster than synthesizing the
491
; addition.
492
(define_peephole2
493
  [(match_scratch:SI 3 "r")
494
   (set (match_operand:SI          0 "arm_general_register_operand" "")
495
        (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
496
                 (match_operand:SI 2 "const_int_operand"  "")))]
497
  "TARGET_ARM &&
498
   !(const_ok_for_arm (INTVAL (operands[2]))
499
     || const_ok_for_arm (-INTVAL (operands[2])))
500
    && const_ok_for_arm (~INTVAL (operands[2]))"
501
  [(set (match_dup 3) (match_dup 2))
502
   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503
  ""
504
)
505
 
506
(define_insn_and_split "*arm_addsi3"
507
  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
508
        (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509
                 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
510
  "TARGET_ARM"
511
  "@
512
   add%?\\t%0, %1, %2
513
   sub%?\\t%0, %1, #%n2
514
   #"
515
  "TARGET_ARM &&
516
   GET_CODE (operands[2]) == CONST_INT
517
   && !(const_ok_for_arm (INTVAL (operands[2]))
518
        || const_ok_for_arm (-INTVAL (operands[2])))"
519
  [(clobber (const_int 0))]
520
  "
521
  arm_split_constant (PLUS, SImode, curr_insn,
522
                      INTVAL (operands[2]), operands[0],
523
                      operands[1], 0);
524
  DONE;
525
  "
526
  [(set_attr "length" "4,4,16")
527
   (set_attr "predicable" "yes")]
528
)
529
 
530
;; Register group 'k' is a single register group containing only the stack
531
;; register.  Trying to reload it will always fail catastrophically,
532
;; so never allow those alternatives to match if reloading is needed.
533
 
534
(define_insn "*thumb_addsi3"
535
  [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
536
        (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537
                 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
538
  "TARGET_THUMB"
539
  "*
540
   static const char * const asms[] =
541
   {
542
     \"add\\t%0, %0, %2\",
543
     \"sub\\t%0, %0, #%n2\",
544
     \"add\\t%0, %1, %2\",
545
     \"add\\t%0, %0, %2\",
546
     \"add\\t%0, %0, %2\",
547
     \"add\\t%0, %1, %2\",
548
     \"add\\t%0, %1, %2\"
549
   };
550
   if ((which_alternative == 2 || which_alternative == 6)
551
       && GET_CODE (operands[2]) == CONST_INT
552
       && INTVAL (operands[2]) < 0)
553
     return \"sub\\t%0, %1, #%n2\";
554
   return asms[which_alternative];
555
  "
556
  [(set_attr "length" "2")]
557
)
558
 
559
;; Reloading and elimination of the frame pointer can
560
;; sometimes cause this optimization to be missed.
561
(define_peephole2
562
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
563
        (match_operand:SI 1 "const_int_operand" ""))
564
   (set (match_dup 0)
565
        (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
566
  "TARGET_THUMB
567
   && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568
   && (INTVAL (operands[1]) & 3) == 0"
569
  [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
570
  ""
571
)
572
 
573
(define_insn "*addsi3_compare0"
574
  [(set (reg:CC_NOOV CC_REGNUM)
575
        (compare:CC_NOOV
576
         (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577
                  (match_operand:SI 2 "arm_add_operand"    "rI,L"))
578
         (const_int 0)))
579
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
580
        (plus:SI (match_dup 1) (match_dup 2)))]
581
  "TARGET_ARM"
582
  "@
583
   add%?s\\t%0, %1, %2
584
   sub%?s\\t%0, %1, #%n2"
585
  [(set_attr "conds" "set")]
586
)
587
 
588
(define_insn "*addsi3_compare0_scratch"
589
  [(set (reg:CC_NOOV CC_REGNUM)
590
        (compare:CC_NOOV
591
         (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592
                  (match_operand:SI 1 "arm_add_operand"    "rI,L"))
593
         (const_int 0)))]
594
  "TARGET_ARM"
595
  "@
596
   cmn%?\\t%0, %1
597
   cmp%?\\t%0, #%n1"
598
  [(set_attr "conds" "set")]
599
)
600
 
601
(define_insn "*compare_negsi_si"
602
  [(set (reg:CC_Z CC_REGNUM)
603
        (compare:CC_Z
604
         (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605
         (match_operand:SI 1 "s_register_operand" "r")))]
606
  "TARGET_ARM"
607
  "cmn%?\\t%1, %0"
608
  [(set_attr "conds" "set")]
609
)
610
 
611
;; This is the canonicalization of addsi3_compare0_for_combiner when the
612
;; addend is a constant.
613
(define_insn "*cmpsi2_addneg"
614
  [(set (reg:CC CC_REGNUM)
615
        (compare:CC
616
         (match_operand:SI 1 "s_register_operand" "r,r")
617
         (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
619
        (plus:SI (match_dup 1)
620
                 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621
  "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
622
  "@
623
   sub%?s\\t%0, %1, %2
624
   add%?s\\t%0, %1, #%n2"
625
  [(set_attr "conds" "set")]
626
)
627
 
628
;; Convert the sequence
629
;;  sub  rd, rn, #1
630
;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
631
;;  bne  dest
632
;; into
633
;;  subs rd, rn, #1
634
;;  bcs  dest   ((unsigned)rn >= 1)
635
;; similarly for the beq variant using bcc.
636
;; This is a common looping idiom (while (n--))
637
(define_peephole2
638
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
639
        (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
640
                 (const_int -1)))
641
   (set (match_operand 2 "cc_register" "")
642
        (compare (match_dup 0) (const_int -1)))
643
   (set (pc)
644
        (if_then_else (match_operator 3 "equality_operator"
645
                       [(match_dup 2) (const_int 0)])
646
                      (match_operand 4 "" "")
647
                      (match_operand 5 "" "")))]
648
  "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
649
  [(parallel[
650
    (set (match_dup 2)
651
         (compare:CC
652
          (match_dup 1) (const_int 1)))
653
    (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
654
   (set (pc)
655
        (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
656
                      (match_dup 4)
657
                      (match_dup 5)))]
658
  "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659
   operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
660
                                  ? GEU : LTU),
661
                                 VOIDmode,
662
                                 operands[2], const0_rtx);"
663
)
664
 
665
;; The next four insns work because they compare the result with one of
666
;; the operands, and we know that the use of the condition code is
667
;; either GEU or LTU, so we can use the carry flag from the addition
668
;; instead of doing the compare a second time.
669
(define_insn "*addsi3_compare_op1"
670
  [(set (reg:CC_C CC_REGNUM)
671
        (compare:CC_C
672
         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673
                  (match_operand:SI 2 "arm_add_operand" "rI,L"))
674
         (match_dup 1)))
675
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
676
        (plus:SI (match_dup 1) (match_dup 2)))]
677
  "TARGET_ARM"
678
  "@
679
   add%?s\\t%0, %1, %2
680
   sub%?s\\t%0, %1, #%n2"
681
  [(set_attr "conds" "set")]
682
)
683
 
684
(define_insn "*addsi3_compare_op2"
685
  [(set (reg:CC_C CC_REGNUM)
686
        (compare:CC_C
687
         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688
                  (match_operand:SI 2 "arm_add_operand" "rI,L"))
689
         (match_dup 2)))
690
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
691
        (plus:SI (match_dup 1) (match_dup 2)))]
692
  "TARGET_ARM"
693
  "@
694
   add%?s\\t%0, %1, %2
695
   sub%?s\\t%0, %1, #%n2"
696
  [(set_attr "conds" "set")]
697
)
698
 
699
(define_insn "*compare_addsi2_op0"
700
  [(set (reg:CC_C CC_REGNUM)
701
        (compare:CC_C
702
         (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703
                  (match_operand:SI 1 "arm_add_operand" "rI,L"))
704
         (match_dup 0)))]
705
  "TARGET_ARM"
706
  "@
707
   cmn%?\\t%0, %1
708
   cmp%?\\t%0, #%n1"
709
  [(set_attr "conds" "set")]
710
)
711
 
712
(define_insn "*compare_addsi2_op1"
713
  [(set (reg:CC_C CC_REGNUM)
714
        (compare:CC_C
715
         (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716
                  (match_operand:SI 1 "arm_add_operand" "rI,L"))
717
         (match_dup 1)))]
718
  "TARGET_ARM"
719
  "@
720
   cmn%?\\t%0, %1
721
   cmp%?\\t%0, #%n1"
722
  [(set_attr "conds" "set")]
723
)
724
 
725
(define_insn "*addsi3_carryin"
726
  [(set (match_operand:SI 0 "s_register_operand" "=r")
727
        (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728
                 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729
                          (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
730
  "TARGET_ARM"
731
  "adc%?\\t%0, %1, %2"
732
  [(set_attr "conds" "use")]
733
)
734
 
735
(define_insn "*addsi3_carryin_shift"
736
  [(set (match_operand:SI 0 "s_register_operand" "=r")
737
        (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
738
                 (plus:SI
739
                   (match_operator:SI 2 "shift_operator"
740
                      [(match_operand:SI 3 "s_register_operand" "r")
741
                       (match_operand:SI 4 "reg_or_int_operand" "rM")])
742
                    (match_operand:SI 1 "s_register_operand" "r"))))]
743
  "TARGET_ARM"
744
  "adc%?\\t%0, %1, %3%S2"
745
  [(set_attr "conds" "use")
746
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747
                      (const_string "alu_shift")
748
                      (const_string "alu_shift_reg")))]
749
)
750
 
751
(define_insn "*addsi3_carryin_alt1"
752
  [(set (match_operand:SI 0 "s_register_operand" "=r")
753
        (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754
                          (match_operand:SI 2 "arm_rhs_operand" "rI"))
755
                 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
756
  "TARGET_ARM"
757
  "adc%?\\t%0, %1, %2"
758
  [(set_attr "conds" "use")]
759
)
760
 
761
(define_insn "*addsi3_carryin_alt2"
762
  [(set (match_operand:SI 0 "s_register_operand" "=r")
763
        (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764
                          (match_operand:SI 1 "s_register_operand" "r"))
765
                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
766
  "TARGET_ARM"
767
  "adc%?\\t%0, %1, %2"
768
  [(set_attr "conds" "use")]
769
)
770
 
771
(define_insn "*addsi3_carryin_alt3"
772
  [(set (match_operand:SI 0 "s_register_operand" "=r")
773
        (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774
                          (match_operand:SI 2 "arm_rhs_operand" "rI"))
775
                 (match_operand:SI 1 "s_register_operand" "r")))]
776
  "TARGET_ARM"
777
  "adc%?\\t%0, %1, %2"
778
  [(set_attr "conds" "use")]
779
)
780
 
781
(define_insn "incscc"
782
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783
        (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784
                    [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785
                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
786
  "TARGET_ARM"
787
  "@
788
  add%d2\\t%0, %1, #1
789
  mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790
  [(set_attr "conds" "use")
791
   (set_attr "length" "4,8")]
792
)
793
 
794
; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
795
(define_split
796
  [(set (match_operand:SI 0 "s_register_operand" "")
797
        (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798
                            (match_operand:SI 2 "s_register_operand" ""))
799
                 (const_int -1)))
800
   (clobber (match_operand:SI 3 "s_register_operand" ""))]
801
  "TARGET_ARM"
802
  [(set (match_dup 3) (match_dup 1))
803
   (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
804
  "
805
  operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
806
")
807
 
808
(define_expand "addsf3"
809
  [(set (match_operand:SF          0 "s_register_operand" "")
810
        (plus:SF (match_operand:SF 1 "s_register_operand" "")
811
                 (match_operand:SF 2 "arm_float_add_operand" "")))]
812
  "TARGET_ARM && TARGET_HARD_FLOAT"
813
  "
814
  if (TARGET_MAVERICK
815
      && !cirrus_fp_register (operands[2], SFmode))
816
    operands[2] = force_reg (SFmode, operands[2]);
817
")
818
 
819
(define_expand "adddf3"
820
  [(set (match_operand:DF          0 "s_register_operand" "")
821
        (plus:DF (match_operand:DF 1 "s_register_operand" "")
822
                 (match_operand:DF 2 "arm_float_add_operand" "")))]
823
  "TARGET_ARM && TARGET_HARD_FLOAT"
824
  "
825
  if (TARGET_MAVERICK
826
      && !cirrus_fp_register (operands[2], DFmode))
827
    operands[2] = force_reg (DFmode, operands[2]);
828
")
829
 
830
(define_expand "subdi3"
831
 [(parallel
832
   [(set (match_operand:DI            0 "s_register_operand" "")
833
          (minus:DI (match_operand:DI 1 "s_register_operand" "")
834
                    (match_operand:DI 2 "s_register_operand" "")))
835
    (clobber (reg:CC CC_REGNUM))])]
836
  "TARGET_EITHER"
837
  "
838
  if (TARGET_HARD_FLOAT && TARGET_MAVERICK
839
      && TARGET_ARM
840
      && cirrus_fp_register (operands[0], DImode)
841
      && cirrus_fp_register (operands[1], DImode))
842
    {
843
      emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
844
      DONE;
845
    }
846
 
847
  if (TARGET_THUMB)
848
    {
849
      if (GET_CODE (operands[1]) != REG)
850
        operands[1] = force_reg (SImode, operands[1]);
851
      if (GET_CODE (operands[2]) != REG)
852
        operands[2] = force_reg (SImode, operands[2]);
853
     }
854
  "
855
)
856
 
857
(define_insn "*arm_subdi3"
858
  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
859
        (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860
                  (match_operand:DI 2 "s_register_operand" "r,0,0")))
861
   (clobber (reg:CC CC_REGNUM))]
862
  "TARGET_ARM"
863
  "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
864
  [(set_attr "conds" "clob")
865
   (set_attr "length" "8")]
866
)
867
 
868
(define_insn "*thumb_subdi3"
869
  [(set (match_operand:DI           0 "register_operand" "=l")
870
        (minus:DI (match_operand:DI 1 "register_operand"  "0")
871
                  (match_operand:DI 2 "register_operand"  "l")))
872
   (clobber (reg:CC CC_REGNUM))]
873
  "TARGET_THUMB"
874
  "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875
  [(set_attr "length" "4")]
876
)
877
 
878
(define_insn "*subdi_di_zesidi"
879
  [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
880
        (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
881
                  (zero_extend:DI
882
                   (match_operand:SI 2 "s_register_operand"  "r,r"))))
883
   (clobber (reg:CC CC_REGNUM))]
884
  "TARGET_ARM"
885
  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
886
  [(set_attr "conds" "clob")
887
   (set_attr "length" "8")]
888
)
889
 
890
(define_insn "*subdi_di_sesidi"
891
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
892
        (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
893
                  (sign_extend:DI
894
                   (match_operand:SI 2 "s_register_operand"  "r,r"))))
895
   (clobber (reg:CC CC_REGNUM))]
896
  "TARGET_ARM"
897
  "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
898
  [(set_attr "conds" "clob")
899
   (set_attr "length" "8")]
900
)
901
 
902
(define_insn "*subdi_zesidi_di"
903
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
904
        (minus:DI (zero_extend:DI
905
                   (match_operand:SI 2 "s_register_operand"  "r,r"))
906
                  (match_operand:DI  1 "s_register_operand" "?r,0")))
907
   (clobber (reg:CC CC_REGNUM))]
908
  "TARGET_ARM"
909
  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
910
  [(set_attr "conds" "clob")
911
   (set_attr "length" "8")]
912
)
913
 
914
(define_insn "*subdi_sesidi_di"
915
  [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
916
        (minus:DI (sign_extend:DI
917
                   (match_operand:SI 2 "s_register_operand"   "r,r"))
918
                  (match_operand:DI  1 "s_register_operand"  "?r,0")))
919
   (clobber (reg:CC CC_REGNUM))]
920
  "TARGET_ARM"
921
  "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
922
  [(set_attr "conds" "clob")
923
   (set_attr "length" "8")]
924
)
925
 
926
(define_insn "*subdi_zesidi_zesidi"
927
  [(set (match_operand:DI            0 "s_register_operand" "=r")
928
        (minus:DI (zero_extend:DI
929
                   (match_operand:SI 1 "s_register_operand"  "r"))
930
                  (zero_extend:DI
931
                   (match_operand:SI 2 "s_register_operand"  "r"))))
932
   (clobber (reg:CC CC_REGNUM))]
933
  "TARGET_ARM"
934
  "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
935
  [(set_attr "conds" "clob")
936
   (set_attr "length" "8")]
937
)
938
 
939
(define_expand "subsi3"
940
  [(set (match_operand:SI           0 "s_register_operand" "")
941
        (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942
                  (match_operand:SI 2 "s_register_operand" "")))]
943
  "TARGET_EITHER"
944
  "
945
  if (GET_CODE (operands[1]) == CONST_INT)
946
    {
947
      if (TARGET_ARM)
948
        {
949
          arm_split_constant (MINUS, SImode, NULL_RTX,
950
                              INTVAL (operands[1]), operands[0],
951
                              operands[2], optimize && !no_new_pseudos);
952
          DONE;
953
        }
954
      else /* TARGET_THUMB */
955
        operands[1] = force_reg (SImode, operands[1]);
956
    }
957
  "
958
)
959
 
960
(define_insn "*thumb_subsi3_insn"
961
  [(set (match_operand:SI           0 "register_operand" "=l")
962
        (minus:SI (match_operand:SI 1 "register_operand" "l")
963
                  (match_operand:SI 2 "register_operand" "l")))]
964
  "TARGET_THUMB"
965
  "sub\\t%0, %1, %2"
966
  [(set_attr "length" "2")]
967
)
968
 
969
(define_insn_and_split "*arm_subsi3_insn"
970
  [(set (match_operand:SI           0 "s_register_operand" "=r,r")
971
        (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972
                  (match_operand:SI 2 "s_register_operand" "r,r")))]
973
  "TARGET_ARM"
974
  "@
975
   rsb%?\\t%0, %2, %1
976
   #"
977
  "TARGET_ARM
978
   && GET_CODE (operands[1]) == CONST_INT
979
   && !const_ok_for_arm (INTVAL (operands[1]))"
980
  [(clobber (const_int 0))]
981
  "
982
  arm_split_constant (MINUS, SImode, curr_insn,
983
                      INTVAL (operands[1]), operands[0], operands[2], 0);
984
  DONE;
985
  "
986
  [(set_attr "length" "4,16")
987
   (set_attr "predicable" "yes")]
988
)
989
 
990
(define_peephole2
991
  [(match_scratch:SI 3 "r")
992
   (set (match_operand:SI 0 "arm_general_register_operand" "")
993
        (minus:SI (match_operand:SI 1 "const_int_operand" "")
994
                  (match_operand:SI 2 "arm_general_register_operand" "")))]
995
  "TARGET_ARM
996
   && !const_ok_for_arm (INTVAL (operands[1]))
997
   && const_ok_for_arm (~INTVAL (operands[1]))"
998
  [(set (match_dup 3) (match_dup 1))
999
   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1000
  ""
1001
)
1002
 
1003
(define_insn "*subsi3_compare0"
1004
  [(set (reg:CC_NOOV CC_REGNUM)
1005
        (compare:CC_NOOV
1006
         (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007
                   (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1008
         (const_int 0)))
1009
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010
        (minus:SI (match_dup 1) (match_dup 2)))]
1011
  "TARGET_ARM"
1012
  "@
1013
   sub%?s\\t%0, %1, %2
1014
   rsb%?s\\t%0, %2, %1"
1015
  [(set_attr "conds" "set")]
1016
)
1017
 
1018
(define_insn "decscc"
1019
  [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1020
        (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1021
                  (match_operator:SI 2 "arm_comparison_operator"
1022
                   [(match_operand   3 "cc_register" "") (const_int 0)])))]
1023
  "TARGET_ARM"
1024
  "@
1025
   sub%d2\\t%0, %1, #1
1026
   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1027
  [(set_attr "conds" "use")
1028
   (set_attr "length" "*,8")]
1029
)
1030
 
1031
(define_expand "subsf3"
1032
  [(set (match_operand:SF           0 "s_register_operand" "")
1033
        (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034
                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035
  "TARGET_ARM && TARGET_HARD_FLOAT"
1036
  "
1037
  if (TARGET_MAVERICK)
1038
    {
1039
      if (!cirrus_fp_register (operands[1], SFmode))
1040
        operands[1] = force_reg (SFmode, operands[1]);
1041
      if (!cirrus_fp_register (operands[2], SFmode))
1042
        operands[2] = force_reg (SFmode, operands[2]);
1043
    }
1044
")
1045
 
1046
(define_expand "subdf3"
1047
  [(set (match_operand:DF           0 "s_register_operand" "")
1048
        (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049
                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050
  "TARGET_ARM && TARGET_HARD_FLOAT"
1051
  "
1052
  if (TARGET_MAVERICK)
1053
    {
1054
       if (!cirrus_fp_register (operands[1], DFmode))
1055
         operands[1] = force_reg (DFmode, operands[1]);
1056
       if (!cirrus_fp_register (operands[2], DFmode))
1057
         operands[2] = force_reg (DFmode, operands[2]);
1058
    }
1059
")
1060
 
1061
 
1062
;; Multiplication insns
1063
 
1064
(define_expand "mulsi3"
1065
  [(set (match_operand:SI          0 "s_register_operand" "")
1066
        (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067
                 (match_operand:SI 1 "s_register_operand" "")))]
1068
  "TARGET_EITHER"
1069
  ""
1070
)
1071
 
1072
;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1073
(define_insn "*arm_mulsi3"
1074
  [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1075
        (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076
                 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1077
  "TARGET_ARM"
1078
  "mul%?\\t%0, %2, %1"
1079
  [(set_attr "insn" "mul")
1080
   (set_attr "predicable" "yes")]
1081
)
1082
 
1083
; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1084
; 1 and 2; are the same, because reload will make operand 0 match
1085
; operand 1 without realizing that this conflicts with operand 2.  We fix
1086
; this by adding another alternative to match this case, and then `reload'
1087
; it ourselves.  This alternative must come first.
1088
(define_insn "*thumb_mulsi3"
1089
  [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1090
        (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091
                 (match_operand:SI 2 "register_operand" "l,l,l")))]
1092
  "TARGET_THUMB"
1093
  "*
1094
  if (which_alternative < 2)
1095
    return \"mov\\t%0, %1\;mul\\t%0, %2\";
1096
  else
1097
    return \"mul\\t%0, %2\";
1098
  "
1099
  [(set_attr "length" "4,4,2")
1100
   (set_attr "insn" "mul")]
1101
)
1102
 
1103
(define_insn "*mulsi3_compare0"
1104
  [(set (reg:CC_NOOV CC_REGNUM)
1105
        (compare:CC_NOOV (mult:SI
1106
                          (match_operand:SI 2 "s_register_operand" "r,r")
1107
                          (match_operand:SI 1 "s_register_operand" "%?r,0"))
1108
                         (const_int 0)))
1109
   (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110
        (mult:SI (match_dup 2) (match_dup 1)))]
1111
  "TARGET_ARM"
1112
  "mul%?s\\t%0, %2, %1"
1113
  [(set_attr "conds" "set")
1114
   (set_attr "insn" "muls")]
1115
)
1116
 
1117
(define_insn "*mulsi_compare0_scratch"
1118
  [(set (reg:CC_NOOV CC_REGNUM)
1119
        (compare:CC_NOOV (mult:SI
1120
                          (match_operand:SI 2 "s_register_operand" "r,r")
1121
                          (match_operand:SI 1 "s_register_operand" "%?r,0"))
1122
                         (const_int 0)))
1123
   (clobber (match_scratch:SI 0 "=&r,&r"))]
1124
  "TARGET_ARM"
1125
  "mul%?s\\t%0, %2, %1"
1126
  [(set_attr "conds" "set")
1127
   (set_attr "insn" "muls")]
1128
)
1129
 
1130
;; Unnamed templates to match MLA instruction.
1131
 
1132
(define_insn "*mulsi3addsi"
1133
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1134
        (plus:SI
1135
          (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136
                   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137
          (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1138
  "TARGET_ARM"
1139
  "mla%?\\t%0, %2, %1, %3"
1140
  [(set_attr "insn" "mla")
1141
   (set_attr "predicable" "yes")]
1142
)
1143
 
1144
(define_insn "*mulsi3addsi_compare0"
1145
  [(set (reg:CC_NOOV CC_REGNUM)
1146
        (compare:CC_NOOV
1147
         (plus:SI (mult:SI
1148
                   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149
                   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150
                  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1151
         (const_int 0)))
1152
   (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153
        (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1154
                 (match_dup 3)))]
1155
  "TARGET_ARM"
1156
  "mla%?s\\t%0, %2, %1, %3"
1157
  [(set_attr "conds" "set")
1158
   (set_attr "insn" "mlas")]
1159
)
1160
 
1161
(define_insn "*mulsi3addsi_compare0_scratch"
1162
  [(set (reg:CC_NOOV CC_REGNUM)
1163
        (compare:CC_NOOV
1164
         (plus:SI (mult:SI
1165
                   (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166
                   (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167
                  (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1168
         (const_int 0)))
1169
   (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1170
  "TARGET_ARM"
1171
  "mla%?s\\t%0, %2, %1, %3"
1172
  [(set_attr "conds" "set")
1173
   (set_attr "insn" "mlas")]
1174
)
1175
 
1176
;; Unnamed template to match long long multiply-accumulate (smlal)
1177
 
1178
(define_insn "*mulsidi3adddi"
1179
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1180
        (plus:DI
1181
         (mult:DI
1182
          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183
          (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184
         (match_operand:DI 1 "s_register_operand" "0")))]
1185
  "TARGET_ARM && arm_arch3m"
1186
  "smlal%?\\t%Q0, %R0, %3, %2"
1187
  [(set_attr "insn" "smlal")
1188
   (set_attr "predicable" "yes")]
1189
)
1190
 
1191
(define_insn "mulsidi3"
1192
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193
        (mult:DI
1194
         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195
         (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196
  "TARGET_ARM && arm_arch3m"
1197
  "smull%?\\t%Q0, %R0, %1, %2"
1198
  [(set_attr "insn" "smull")
1199
   (set_attr "predicable" "yes")]
1200
)
1201
 
1202
(define_insn "umulsidi3"
1203
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1204
        (mult:DI
1205
         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206
         (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1207
  "TARGET_ARM && arm_arch3m"
1208
  "umull%?\\t%Q0, %R0, %1, %2"
1209
  [(set_attr "insn" "umull")
1210
   (set_attr "predicable" "yes")]
1211
)
1212
 
1213
;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1214
 
1215
(define_insn "*umulsidi3adddi"
1216
  [(set (match_operand:DI 0 "s_register_operand" "=&r")
1217
        (plus:DI
1218
         (mult:DI
1219
          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220
          (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221
         (match_operand:DI 1 "s_register_operand" "0")))]
1222
  "TARGET_ARM && arm_arch3m"
1223
  "umlal%?\\t%Q0, %R0, %3, %2"
1224
  [(set_attr "insn" "umlal")
1225
   (set_attr "predicable" "yes")]
1226
)
1227
 
1228
(define_insn "smulsi3_highpart"
1229
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230
        (truncate:SI
1231
         (lshiftrt:DI
1232
          (mult:DI
1233
           (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234
           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1235
          (const_int 32))))
1236
   (clobber (match_scratch:SI 3 "=&r,&r"))]
1237
  "TARGET_ARM && arm_arch3m"
1238
  "smull%?\\t%3, %0, %2, %1"
1239
  [(set_attr "insn" "smull")
1240
   (set_attr "predicable" "yes")]
1241
)
1242
 
1243
(define_insn "umulsi3_highpart"
1244
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1245
        (truncate:SI
1246
         (lshiftrt:DI
1247
          (mult:DI
1248
           (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249
           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1250
          (const_int 32))))
1251
   (clobber (match_scratch:SI 3 "=&r,&r"))]
1252
  "TARGET_ARM && arm_arch3m"
1253
  "umull%?\\t%3, %0, %2, %1"
1254
  [(set_attr "insn" "umull")
1255
   (set_attr "predicable" "yes")]
1256
)
1257
 
1258
(define_insn "mulhisi3"
1259
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1260
        (mult:SI (sign_extend:SI
1261
                  (match_operand:HI 1 "s_register_operand" "%r"))
1262
                 (sign_extend:SI
1263
                  (match_operand:HI 2 "s_register_operand" "r"))))]
1264
  "TARGET_ARM && arm_arch5e"
1265
  "smulbb%?\\t%0, %1, %2"
1266
  [(set_attr "insn" "smulxy")
1267
   (set_attr "predicable" "yes")]
1268
)
1269
 
1270
(define_insn "*mulhisi3tb"
1271
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1272
        (mult:SI (ashiftrt:SI
1273
                  (match_operand:SI 1 "s_register_operand" "r")
1274
                  (const_int 16))
1275
                 (sign_extend:SI
1276
                  (match_operand:HI 2 "s_register_operand" "r"))))]
1277
  "TARGET_ARM && arm_arch5e"
1278
  "smultb%?\\t%0, %1, %2"
1279
  [(set_attr "insn" "smulxy")
1280
   (set_attr "predicable" "yes")]
1281
)
1282
 
1283
(define_insn "*mulhisi3bt"
1284
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1285
        (mult:SI (sign_extend:SI
1286
                  (match_operand:HI 1 "s_register_operand" "r"))
1287
                 (ashiftrt:SI
1288
                  (match_operand:SI 2 "s_register_operand" "r")
1289
                  (const_int 16))))]
1290
  "TARGET_ARM && arm_arch5e"
1291
  "smulbt%?\\t%0, %1, %2"
1292
  [(set_attr "insn" "smulxy")
1293
   (set_attr "predicable" "yes")]
1294
)
1295
 
1296
(define_insn "*mulhisi3tt"
1297
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1298
        (mult:SI (ashiftrt:SI
1299
                  (match_operand:SI 1 "s_register_operand" "r")
1300
                  (const_int 16))
1301
                 (ashiftrt:SI
1302
                  (match_operand:SI 2 "s_register_operand" "r")
1303
                  (const_int 16))))]
1304
  "TARGET_ARM && arm_arch5e"
1305
  "smultt%?\\t%0, %1, %2"
1306
  [(set_attr "insn" "smulxy")
1307
   (set_attr "predicable" "yes")]
1308
)
1309
 
1310
(define_insn "*mulhisi3addsi"
1311
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1312
        (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313
                 (mult:SI (sign_extend:SI
1314
                           (match_operand:HI 2 "s_register_operand" "%r"))
1315
                          (sign_extend:SI
1316
                           (match_operand:HI 3 "s_register_operand" "r")))))]
1317
  "TARGET_ARM && arm_arch5e"
1318
  "smlabb%?\\t%0, %2, %3, %1"
1319
  [(set_attr "insn" "smlaxy")
1320
   (set_attr "predicable" "yes")]
1321
)
1322
 
1323
(define_insn "*mulhidi3adddi"
1324
  [(set (match_operand:DI 0 "s_register_operand" "=r")
1325
        (plus:DI
1326
          (match_operand:DI 1 "s_register_operand" "0")
1327
          (mult:DI (sign_extend:DI
1328
                    (match_operand:HI 2 "s_register_operand" "%r"))
1329
                   (sign_extend:DI
1330
                    (match_operand:HI 3 "s_register_operand" "r")))))]
1331
  "TARGET_ARM && arm_arch5e"
1332
  "smlalbb%?\\t%Q0, %R0, %2, %3"
1333
  [(set_attr "insn" "smlalxy")
1334
   (set_attr "predicable" "yes")])
1335
 
1336
(define_expand "mulsf3"
1337
  [(set (match_operand:SF          0 "s_register_operand" "")
1338
        (mult:SF (match_operand:SF 1 "s_register_operand" "")
1339
                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340
  "TARGET_ARM && TARGET_HARD_FLOAT"
1341
  "
1342
  if (TARGET_MAVERICK
1343
      && !cirrus_fp_register (operands[2], SFmode))
1344
    operands[2] = force_reg (SFmode, operands[2]);
1345
")
1346
 
1347
(define_expand "muldf3"
1348
  [(set (match_operand:DF          0 "s_register_operand" "")
1349
        (mult:DF (match_operand:DF 1 "s_register_operand" "")
1350
                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351
  "TARGET_ARM && TARGET_HARD_FLOAT"
1352
  "
1353
  if (TARGET_MAVERICK
1354
      && !cirrus_fp_register (operands[2], DFmode))
1355
    operands[2] = force_reg (DFmode, operands[2]);
1356
")
1357
 
1358
;; Division insns
1359
 
1360
(define_expand "divsf3"
1361
  [(set (match_operand:SF 0 "s_register_operand" "")
1362
        (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363
                (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1365
  "")
1366
 
1367
(define_expand "divdf3"
1368
  [(set (match_operand:DF 0 "s_register_operand" "")
1369
        (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370
                (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1372
  "")
1373
 
1374
;; Modulo insns
1375
 
1376
(define_expand "modsf3"
1377
  [(set (match_operand:SF 0 "s_register_operand" "")
1378
        (mod:SF (match_operand:SF 1 "s_register_operand" "")
1379
                (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1381
  "")
1382
 
1383
(define_expand "moddf3"
1384
  [(set (match_operand:DF 0 "s_register_operand" "")
1385
        (mod:DF (match_operand:DF 1 "s_register_operand" "")
1386
                (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1388
  "")
1389
 
1390
;; Boolean and,ior,xor insns
1391
 
1392
;; Split up double word logical operations
1393
 
1394
;; Split up simple DImode logical operations.  Simply perform the logical
1395
;; operation on the upper and lower halves of the registers.
1396
(define_split
1397
  [(set (match_operand:DI 0 "s_register_operand" "")
1398
        (match_operator:DI 6 "logical_binary_operator"
1399
          [(match_operand:DI 1 "s_register_operand" "")
1400
           (match_operand:DI 2 "s_register_operand" "")]))]
1401
  "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1402
  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403
   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1404
  "
1405
  {
1406
    operands[3] = gen_highpart (SImode, operands[0]);
1407
    operands[0] = gen_lowpart (SImode, operands[0]);
1408
    operands[4] = gen_highpart (SImode, operands[1]);
1409
    operands[1] = gen_lowpart (SImode, operands[1]);
1410
    operands[5] = gen_highpart (SImode, operands[2]);
1411
    operands[2] = gen_lowpart (SImode, operands[2]);
1412
  }"
1413
)
1414
 
1415
(define_split
1416
  [(set (match_operand:DI 0 "s_register_operand" "")
1417
        (match_operator:DI 6 "logical_binary_operator"
1418
          [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419
           (match_operand:DI 1 "s_register_operand" "")]))]
1420
  "TARGET_ARM && reload_completed"
1421
  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422
   (set (match_dup 3) (match_op_dup:SI 6
1423
                        [(ashiftrt:SI (match_dup 2) (const_int 31))
1424
                         (match_dup 4)]))]
1425
  "
1426
  {
1427
    operands[3] = gen_highpart (SImode, operands[0]);
1428
    operands[0] = gen_lowpart (SImode, operands[0]);
1429
    operands[4] = gen_highpart (SImode, operands[1]);
1430
    operands[1] = gen_lowpart (SImode, operands[1]);
1431
    operands[5] = gen_highpart (SImode, operands[2]);
1432
    operands[2] = gen_lowpart (SImode, operands[2]);
1433
  }"
1434
)
1435
 
1436
;; The zero extend of operand 2 means we can just copy the high part of
1437
;; operand1 into operand0.
1438
(define_split
1439
  [(set (match_operand:DI 0 "s_register_operand" "")
1440
        (ior:DI
1441
          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442
          (match_operand:DI 1 "s_register_operand" "")))]
1443
  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1444
  [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445
   (set (match_dup 3) (match_dup 4))]
1446
  "
1447
  {
1448
    operands[4] = gen_highpart (SImode, operands[1]);
1449
    operands[3] = gen_highpart (SImode, operands[0]);
1450
    operands[0] = gen_lowpart (SImode, operands[0]);
1451
    operands[1] = gen_lowpart (SImode, operands[1]);
1452
  }"
1453
)
1454
 
1455
;; The zero extend of operand 2 means we can just copy the high part of
1456
;; operand1 into operand0.
1457
(define_split
1458
  [(set (match_operand:DI 0 "s_register_operand" "")
1459
        (xor:DI
1460
          (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461
          (match_operand:DI 1 "s_register_operand" "")))]
1462
  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1463
  [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464
   (set (match_dup 3) (match_dup 4))]
1465
  "
1466
  {
1467
    operands[4] = gen_highpart (SImode, operands[1]);
1468
    operands[3] = gen_highpart (SImode, operands[0]);
1469
    operands[0] = gen_lowpart (SImode, operands[0]);
1470
    operands[1] = gen_lowpart (SImode, operands[1]);
1471
  }"
1472
)
1473
 
1474
(define_insn "anddi3"
1475
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1476
        (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1477
                (match_operand:DI 2 "s_register_operand"   "r,r")))]
1478
  "TARGET_ARM && ! TARGET_IWMMXT"
1479
  "#"
1480
  [(set_attr "length" "8")]
1481
)
1482
 
1483
(define_insn_and_split "*anddi_zesidi_di"
1484
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485
        (and:DI (zero_extend:DI
1486
                 (match_operand:SI 2 "s_register_operand" "r,r"))
1487
                (match_operand:DI 1 "s_register_operand" "?r,0")))]
1488
  "TARGET_ARM"
1489
  "#"
1490
  "TARGET_ARM && reload_completed"
1491
  ; The zero extend of operand 2 clears the high word of the output
1492
  ; operand.
1493
  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494
   (set (match_dup 3) (const_int 0))]
1495
  "
1496
  {
1497
    operands[3] = gen_highpart (SImode, operands[0]);
1498
    operands[0] = gen_lowpart (SImode, operands[0]);
1499
    operands[1] = gen_lowpart (SImode, operands[1]);
1500
  }"
1501
  [(set_attr "length" "8")]
1502
)
1503
 
1504
(define_insn "*anddi_sesdi_di"
1505
  [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1506
        (and:DI (sign_extend:DI
1507
                 (match_operand:SI 2 "s_register_operand" "r,r"))
1508
                (match_operand:DI  1 "s_register_operand" "?r,0")))]
1509
  "TARGET_ARM"
1510
  "#"
1511
  [(set_attr "length" "8")]
1512
)
1513
 
1514
(define_expand "andsi3"
1515
  [(set (match_operand:SI         0 "s_register_operand" "")
1516
        (and:SI (match_operand:SI 1 "s_register_operand" "")
1517
                (match_operand:SI 2 "reg_or_int_operand" "")))]
1518
  "TARGET_EITHER"
1519
  "
1520
  if (TARGET_ARM)
1521
    {
1522
      if (GET_CODE (operands[2]) == CONST_INT)
1523
        {
1524
          arm_split_constant (AND, SImode, NULL_RTX,
1525
                              INTVAL (operands[2]), operands[0],
1526
                              operands[1], optimize && !no_new_pseudos);
1527
 
1528
          DONE;
1529
        }
1530
    }
1531
  else /* TARGET_THUMB */
1532
    {
1533
      if (GET_CODE (operands[2]) != CONST_INT)
1534
        operands[2] = force_reg (SImode, operands[2]);
1535
      else
1536
        {
1537
          int i;
1538
 
1539
          if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1540
            {
1541
              operands[2] = force_reg (SImode,
1542
                                       GEN_INT (~INTVAL (operands[2])));
1543
 
1544
              emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1545
 
1546
              DONE;
1547
            }
1548
 
1549
          for (i = 9; i <= 31; i++)
1550
            {
1551
              if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1552
                {
1553
                  emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1554
                                        const0_rtx));
1555
                  DONE;
1556
                }
1557
              else if ((((HOST_WIDE_INT) 1) << i) - 1
1558
                       == ~INTVAL (operands[2]))
1559
                {
1560
                  rtx shift = GEN_INT (i);
1561
                  rtx reg = gen_reg_rtx (SImode);
1562
 
1563
                  emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564
                  emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1565
 
1566
                  DONE;
1567
                }
1568
            }
1569
 
1570
          operands[2] = force_reg (SImode, operands[2]);
1571
        }
1572
    }
1573
  "
1574
)
1575
 
1576
(define_insn_and_split "*arm_andsi3_insn"
1577
  [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1578
        (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579
                (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1580
  "TARGET_ARM"
1581
  "@
1582
   and%?\\t%0, %1, %2
1583
   bic%?\\t%0, %1, #%B2
1584
   #"
1585
  "TARGET_ARM
1586
   && GET_CODE (operands[2]) == CONST_INT
1587
   && !(const_ok_for_arm (INTVAL (operands[2]))
1588
        || const_ok_for_arm (~INTVAL (operands[2])))"
1589
  [(clobber (const_int 0))]
1590
  "
1591
  arm_split_constant  (AND, SImode, curr_insn,
1592
                       INTVAL (operands[2]), operands[0], operands[1], 0);
1593
  DONE;
1594
  "
1595
  [(set_attr "length" "4,4,16")
1596
   (set_attr "predicable" "yes")]
1597
)
1598
 
1599
(define_insn "*thumb_andsi3_insn"
1600
  [(set (match_operand:SI         0 "register_operand" "=l")
1601
        (and:SI (match_operand:SI 1 "register_operand" "%0")
1602
                (match_operand:SI 2 "register_operand" "l")))]
1603
  "TARGET_THUMB"
1604
  "and\\t%0, %0, %2"
1605
  [(set_attr "length" "2")]
1606
)
1607
 
1608
(define_insn "*andsi3_compare0"
1609
  [(set (reg:CC_NOOV CC_REGNUM)
1610
        (compare:CC_NOOV
1611
         (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612
                 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1613
         (const_int 0)))
1614
   (set (match_operand:SI          0 "s_register_operand" "=r,r")
1615
        (and:SI (match_dup 1) (match_dup 2)))]
1616
  "TARGET_ARM"
1617
  "@
1618
   and%?s\\t%0, %1, %2
1619
   bic%?s\\t%0, %1, #%B2"
1620
  [(set_attr "conds" "set")]
1621
)
1622
 
1623
(define_insn "*andsi3_compare0_scratch"
1624
  [(set (reg:CC_NOOV CC_REGNUM)
1625
        (compare:CC_NOOV
1626
         (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627
                 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1628
         (const_int 0)))
1629
   (clobber (match_scratch:SI 2 "=X,r"))]
1630
  "TARGET_ARM"
1631
  "@
1632
   tst%?\\t%0, %1
1633
   bic%?s\\t%2, %0, #%B1"
1634
  [(set_attr "conds" "set")]
1635
)
1636
 
1637
(define_insn "*zeroextractsi_compare0_scratch"
1638
  [(set (reg:CC_NOOV CC_REGNUM)
1639
        (compare:CC_NOOV (zero_extract:SI
1640
                          (match_operand:SI 0 "s_register_operand" "r")
1641
                          (match_operand 1 "const_int_operand" "n")
1642
                          (match_operand 2 "const_int_operand" "n"))
1643
                         (const_int 0)))]
1644
  "TARGET_ARM
1645
  && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646
      && INTVAL (operands[1]) > 0
1647
      && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648
      && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1649
  "*
1650
  operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651
                         << INTVAL (operands[2]));
1652
  output_asm_insn (\"tst%?\\t%0, %1\", operands);
1653
  return \"\";
1654
  "
1655
  [(set_attr "conds" "set")]
1656
)
1657
 
1658
(define_insn_and_split "*ne_zeroextractsi"
1659
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1660
        (ne:SI (zero_extract:SI
1661
                (match_operand:SI 1 "s_register_operand" "r")
1662
                (match_operand:SI 2 "const_int_operand" "n")
1663
                (match_operand:SI 3 "const_int_operand" "n"))
1664
               (const_int 0)))
1665
   (clobber (reg:CC CC_REGNUM))]
1666
  "TARGET_ARM
1667
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668
       && INTVAL (operands[2]) > 0
1669
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1671
  "#"
1672
  "TARGET_ARM
1673
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674
       && INTVAL (operands[2]) > 0
1675
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678
                   (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1679
                                    (const_int 0)))
1680
              (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1681
   (set (match_dup 0)
1682
        (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683
                         (match_dup 0) (const_int 1)))]
1684
  "
1685
  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686
                         << INTVAL (operands[3]));
1687
  "
1688
  [(set_attr "conds" "clob")
1689
   (set_attr "length" "8")]
1690
)
1691
 
1692
(define_insn_and_split "*ne_zeroextractsi_shifted"
1693
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1694
        (ne:SI (zero_extract:SI
1695
                (match_operand:SI 1 "s_register_operand" "r")
1696
                (match_operand:SI 2 "const_int_operand" "n")
1697
                (const_int 0))
1698
               (const_int 0)))
1699
   (clobber (reg:CC CC_REGNUM))]
1700
  "TARGET_ARM"
1701
  "#"
1702
  "TARGET_ARM"
1703
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704
                   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1705
                                    (const_int 0)))
1706
              (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1707
   (set (match_dup 0)
1708
        (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709
                         (match_dup 0) (const_int 1)))]
1710
  "
1711
  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1712
  "
1713
  [(set_attr "conds" "clob")
1714
   (set_attr "length" "8")]
1715
)
1716
 
1717
(define_insn_and_split "*ite_ne_zeroextractsi"
1718
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1719
        (if_then_else:SI (ne (zero_extract:SI
1720
                              (match_operand:SI 1 "s_register_operand" "r")
1721
                              (match_operand:SI 2 "const_int_operand" "n")
1722
                              (match_operand:SI 3 "const_int_operand" "n"))
1723
                             (const_int 0))
1724
                         (match_operand:SI 4 "arm_not_operand" "rIK")
1725
                         (const_int 0)))
1726
   (clobber (reg:CC CC_REGNUM))]
1727
  "TARGET_ARM
1728
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729
       && INTVAL (operands[2]) > 0
1730
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1731
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732
   && !reg_overlap_mentioned_p (operands[0], operands[4])"
1733
  "#"
1734
  "TARGET_ARM
1735
   && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736
       && INTVAL (operands[2]) > 0
1737
       && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1738
       && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739
   && !reg_overlap_mentioned_p (operands[0], operands[4])"
1740
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741
                   (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1742
                                    (const_int 0)))
1743
              (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1744
   (set (match_dup 0)
1745
        (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746
                         (match_dup 0) (match_dup 4)))]
1747
  "
1748
  operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1749
                         << INTVAL (operands[3]));
1750
  "
1751
  [(set_attr "conds" "clob")
1752
   (set_attr "length" "8")]
1753
)
1754
 
1755
(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756
  [(set (match_operand:SI 0 "s_register_operand" "=r")
1757
        (if_then_else:SI (ne (zero_extract:SI
1758
                              (match_operand:SI 1 "s_register_operand" "r")
1759
                              (match_operand:SI 2 "const_int_operand" "n")
1760
                              (const_int 0))
1761
                             (const_int 0))
1762
                         (match_operand:SI 3 "arm_not_operand" "rIK")
1763
                         (const_int 0)))
1764
   (clobber (reg:CC CC_REGNUM))]
1765
  "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1766
  "#"
1767
  "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1768
  [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769
                   (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1770
                                    (const_int 0)))
1771
              (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1772
   (set (match_dup 0)
1773
        (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774
                         (match_dup 0) (match_dup 3)))]
1775
  "
1776
  operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1777
  "
1778
  [(set_attr "conds" "clob")
1779
   (set_attr "length" "8")]
1780
)
1781
 
1782
(define_split
1783
  [(set (match_operand:SI 0 "s_register_operand" "")
1784
        (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785
                         (match_operand:SI 2 "const_int_operand" "")
1786
                         (match_operand:SI 3 "const_int_operand" "")))
1787
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
1788
  "TARGET_THUMB"
1789
  [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790
   (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1791
  "{
1792
     HOST_WIDE_INT temp = INTVAL (operands[2]);
1793
 
1794
     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795
     operands[3] = GEN_INT (32 - temp);
1796
   }"
1797
)
1798
 
1799
(define_split
1800
  [(set (match_operand:SI 0 "s_register_operand" "")
1801
        (match_operator:SI 1 "shiftable_operator"
1802
         [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803
                           (match_operand:SI 3 "const_int_operand" "")
1804
                           (match_operand:SI 4 "const_int_operand" ""))
1805
          (match_operand:SI 5 "s_register_operand" "")]))
1806
   (clobber (match_operand:SI 6 "s_register_operand" ""))]
1807
  "TARGET_ARM"
1808
  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1809
   (set (match_dup 0)
1810
        (match_op_dup 1
1811
         [(lshiftrt:SI (match_dup 6) (match_dup 4))
1812
          (match_dup 5)]))]
1813
  "{
1814
     HOST_WIDE_INT temp = INTVAL (operands[3]);
1815
 
1816
     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817
     operands[4] = GEN_INT (32 - temp);
1818
   }"
1819
)
1820
 
1821
(define_split
1822
  [(set (match_operand:SI 0 "s_register_operand" "")
1823
        (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824
                         (match_operand:SI 2 "const_int_operand" "")
1825
                         (match_operand:SI 3 "const_int_operand" "")))]
1826
  "TARGET_THUMB"
1827
  [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828
   (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1829
  "{
1830
     HOST_WIDE_INT temp = INTVAL (operands[2]);
1831
 
1832
     operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833
     operands[3] = GEN_INT (32 - temp);
1834
   }"
1835
)
1836
 
1837
(define_split
1838
  [(set (match_operand:SI 0 "s_register_operand" "")
1839
        (match_operator:SI 1 "shiftable_operator"
1840
         [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841
                           (match_operand:SI 3 "const_int_operand" "")
1842
                           (match_operand:SI 4 "const_int_operand" ""))
1843
          (match_operand:SI 5 "s_register_operand" "")]))
1844
   (clobber (match_operand:SI 6 "s_register_operand" ""))]
1845
  "TARGET_ARM"
1846
  [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1847
   (set (match_dup 0)
1848
        (match_op_dup 1
1849
         [(ashiftrt:SI (match_dup 6) (match_dup 4))
1850
          (match_dup 5)]))]
1851
  "{
1852
     HOST_WIDE_INT temp = INTVAL (operands[3]);
1853
 
1854
     operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855
     operands[4] = GEN_INT (32 - temp);
1856
   }"
1857
)
1858
 
1859
;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1860
;;; represented by the bitfield, then this will produce incorrect results.
1861
;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1862
;;; which have a real bit-field insert instruction, the truncation happens
1863
;;; in the bit-field insert instruction itself.  Since arm does not have a
1864
;;; bit-field insert instruction, we would have to emit code here to truncate
1865
;;; the value before we insert.  This loses some of the advantage of having
1866
;;; this insv pattern, so this pattern needs to be reevalutated.
1867
 
1868
(define_expand "insv"
1869
  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870
                         (match_operand:SI 1 "general_operand" "")
1871
                         (match_operand:SI 2 "general_operand" ""))
1872
        (match_operand:SI 3 "reg_or_int_operand" ""))]
1873
  "TARGET_ARM"
1874
  "
1875
  {
1876
    int start_bit = INTVAL (operands[2]);
1877
    int width = INTVAL (operands[1]);
1878
    HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879
    rtx target, subtarget;
1880
 
1881
    target = operands[0];
1882
    /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1883
       subreg as the final target.  */
1884
    if (GET_CODE (target) == SUBREG)
1885
      {
1886
        subtarget = gen_reg_rtx (SImode);
1887
        if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888
            < GET_MODE_SIZE (SImode))
1889
          target = SUBREG_REG (target);
1890
      }
1891
    else
1892
      subtarget = target;
1893
 
1894
    if (GET_CODE (operands[3]) == CONST_INT)
1895
      {
1896
        /* Since we are inserting a known constant, we may be able to
1897
           reduce the number of bits that we have to clear so that
1898
           the mask becomes simple.  */
1899
        /* ??? This code does not check to see if the new mask is actually
1900
           simpler.  It may not be.  */
1901
        rtx op1 = gen_reg_rtx (SImode);
1902
        /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1903
           start of this pattern.  */
1904
        HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905
        HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1906
 
1907
        emit_insn (gen_andsi3 (op1, operands[0],
1908
                               gen_int_mode (~mask2, SImode)));
1909
        emit_insn (gen_iorsi3 (subtarget, op1,
1910
                               gen_int_mode (op3_value << start_bit, SImode)));
1911
      }
1912
    else if (start_bit == 0
1913
             && !(const_ok_for_arm (mask)
1914
                  || const_ok_for_arm (~mask)))
1915
      {
1916
        /* A Trick, since we are setting the bottom bits in the word,
1917
           we can shift operand[3] up, operand[0] down, OR them together
1918
           and rotate the result back again.  This takes 3 insns, and
1919
           the third might be mergeable into another op.  */
1920
        /* The shift up copes with the possibility that operand[3] is
1921
           wider than the bitfield.  */
1922
        rtx op0 = gen_reg_rtx (SImode);
1923
        rtx op1 = gen_reg_rtx (SImode);
1924
 
1925
        emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926
        emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1927
        emit_insn (gen_iorsi3  (op1, op1, op0));
1928
        emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1929
      }
1930
    else if ((width + start_bit == 32)
1931
             && !(const_ok_for_arm (mask)
1932
                  || const_ok_for_arm (~mask)))
1933
      {
1934
        /* Similar trick, but slightly less efficient.  */
1935
 
1936
        rtx op0 = gen_reg_rtx (SImode);
1937
        rtx op1 = gen_reg_rtx (SImode);
1938
 
1939
        emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940
        emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941
        emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942
        emit_insn (gen_iorsi3 (subtarget, op1, op0));
1943
      }
1944
    else
1945
      {
1946
        rtx op0 = gen_int_mode (mask, SImode);
1947
        rtx op1 = gen_reg_rtx (SImode);
1948
        rtx op2 = gen_reg_rtx (SImode);
1949
 
1950
        if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1951
          {
1952
            rtx tmp = gen_reg_rtx (SImode);
1953
 
1954
            emit_insn (gen_movsi (tmp, op0));
1955
            op0 = tmp;
1956
          }
1957
 
1958
        /* Mask out any bits in operand[3] that are not needed.  */
1959
           emit_insn (gen_andsi3 (op1, operands[3], op0));
1960
 
1961
        if (GET_CODE (op0) == CONST_INT
1962
            && (const_ok_for_arm (mask << start_bit)
1963
                || const_ok_for_arm (~(mask << start_bit))))
1964
          {
1965
            op0 = gen_int_mode (~(mask << start_bit), SImode);
1966
            emit_insn (gen_andsi3 (op2, operands[0], op0));
1967
          }
1968
        else
1969
          {
1970
            if (GET_CODE (op0) == CONST_INT)
1971
              {
1972
                rtx tmp = gen_reg_rtx (SImode);
1973
 
1974
                emit_insn (gen_movsi (tmp, op0));
1975
                op0 = tmp;
1976
              }
1977
 
1978
            if (start_bit != 0)
1979
              emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1980
 
1981
            emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1982
          }
1983
 
1984
        if (start_bit != 0)
1985
          emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1986
 
1987
        emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988
      }
1989
 
1990
    if (subtarget != target)
1991
      {
1992
        /* If TARGET is still a SUBREG, then it must be wider than a word,
1993
           so we must be careful only to set the subword we were asked to.  */
1994
        if (GET_CODE (target) == SUBREG)
1995
          emit_move_insn (target, subtarget);
1996
        else
1997
          emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1998
      }
1999
 
2000
    DONE;
2001
  }"
2002
)
2003
 
2004
; constants for op 2 will never be given to these patterns.
2005
(define_insn_and_split "*anddi_notdi_di"
2006
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2007
        (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008
                (match_operand:DI 2 "s_register_operand" "0,r")))]
2009
  "TARGET_ARM"
2010
  "#"
2011
  "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2012
  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013
   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014
  "
2015
  {
2016
    operands[3] = gen_highpart (SImode, operands[0]);
2017
    operands[0] = gen_lowpart (SImode, operands[0]);
2018
    operands[4] = gen_highpart (SImode, operands[1]);
2019
    operands[1] = gen_lowpart (SImode, operands[1]);
2020
    operands[5] = gen_highpart (SImode, operands[2]);
2021
    operands[2] = gen_lowpart (SImode, operands[2]);
2022
  }"
2023
  [(set_attr "length" "8")
2024
   (set_attr "predicable" "yes")]
2025
)
2026
 
2027
(define_insn_and_split "*anddi_notzesidi_di"
2028
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029
        (and:DI (not:DI (zero_extend:DI
2030
                         (match_operand:SI 2 "s_register_operand" "r,r")))
2031
                (match_operand:DI 1 "s_register_operand" "0,?r")))]
2032
  "TARGET_ARM"
2033
  "@
2034
   bic%?\\t%Q0, %Q1, %2
2035
   #"
2036
  ; (not (zero_extend ...)) allows us to just copy the high word from
2037
  ; operand1 to operand0.
2038
  "TARGET_ARM
2039
   && reload_completed
2040
   && operands[0] != operands[1]"
2041
  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2042
   (set (match_dup 3) (match_dup 4))]
2043
  "
2044
  {
2045
    operands[3] = gen_highpart (SImode, operands[0]);
2046
    operands[0] = gen_lowpart (SImode, operands[0]);
2047
    operands[4] = gen_highpart (SImode, operands[1]);
2048
    operands[1] = gen_lowpart (SImode, operands[1]);
2049
  }"
2050
  [(set_attr "length" "4,8")
2051
   (set_attr "predicable" "yes")]
2052
)
2053
 
2054
(define_insn_and_split "*anddi_notsesidi_di"
2055
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056
        (and:DI (not:DI (sign_extend:DI
2057
                         (match_operand:SI 2 "s_register_operand" "r,r")))
2058
                (match_operand:DI 1 "s_register_operand" "0,r")))]
2059
  "TARGET_ARM"
2060
  "#"
2061
  "TARGET_ARM && reload_completed"
2062
  [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2063
   (set (match_dup 3) (and:SI (not:SI
2064
                                (ashiftrt:SI (match_dup 2) (const_int 31)))
2065
                               (match_dup 4)))]
2066
  "
2067
  {
2068
    operands[3] = gen_highpart (SImode, operands[0]);
2069
    operands[0] = gen_lowpart (SImode, operands[0]);
2070
    operands[4] = gen_highpart (SImode, operands[1]);
2071
    operands[1] = gen_lowpart (SImode, operands[1]);
2072
  }"
2073
  [(set_attr "length" "8")
2074
   (set_attr "predicable" "yes")]
2075
)
2076
 
2077
(define_insn "andsi_notsi_si"
2078
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2079
        (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080
                (match_operand:SI 1 "s_register_operand" "r")))]
2081
  "TARGET_ARM"
2082
  "bic%?\\t%0, %1, %2"
2083
  [(set_attr "predicable" "yes")]
2084
)
2085
 
2086
(define_insn "bicsi3"
2087
  [(set (match_operand:SI                 0 "register_operand" "=l")
2088
        (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089
                (match_operand:SI         2 "register_operand" "0")))]
2090
  "TARGET_THUMB"
2091
  "bic\\t%0, %0, %1"
2092
  [(set_attr "length" "2")]
2093
)
2094
 
2095
(define_insn "andsi_not_shiftsi_si"
2096
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2097
        (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098
                         [(match_operand:SI 2 "s_register_operand" "r")
2099
                          (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100
                (match_operand:SI 1 "s_register_operand" "r")))]
2101
  "TARGET_ARM"
2102
  "bic%?\\t%0, %1, %2%S4"
2103
  [(set_attr "predicable" "yes")
2104
   (set_attr "shift" "2")
2105
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106
                      (const_string "alu_shift")
2107
                      (const_string "alu_shift_reg")))]
2108
)
2109
 
2110
(define_insn "*andsi_notsi_si_compare0"
2111
  [(set (reg:CC_NOOV CC_REGNUM)
2112
        (compare:CC_NOOV
2113
         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114
                 (match_operand:SI 1 "s_register_operand" "r"))
2115
         (const_int 0)))
2116
   (set (match_operand:SI 0 "s_register_operand" "=r")
2117
        (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2118
  "TARGET_ARM"
2119
  "bic%?s\\t%0, %1, %2"
2120
  [(set_attr "conds" "set")]
2121
)
2122
 
2123
(define_insn "*andsi_notsi_si_compare0_scratch"
2124
  [(set (reg:CC_NOOV CC_REGNUM)
2125
        (compare:CC_NOOV
2126
         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127
                 (match_operand:SI 1 "s_register_operand" "r"))
2128
         (const_int 0)))
2129
   (clobber (match_scratch:SI 0 "=r"))]
2130
  "TARGET_ARM"
2131
  "bic%?s\\t%0, %1, %2"
2132
  [(set_attr "conds" "set")]
2133
)
2134
 
2135
(define_insn "iordi3"
2136
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2137
        (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2138
                (match_operand:DI 2 "s_register_operand"   "r,r")))]
2139
  "TARGET_ARM && ! TARGET_IWMMXT"
2140
  "#"
2141
  [(set_attr "length" "8")
2142
   (set_attr "predicable" "yes")]
2143
)
2144
 
2145
(define_insn "*iordi_zesidi_di"
2146
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147
        (ior:DI (zero_extend:DI
2148
                 (match_operand:SI 2 "s_register_operand" "r,r"))
2149
                (match_operand:DI 1 "s_register_operand" "0,?r")))]
2150
  "TARGET_ARM"
2151
  "@
2152
   orr%?\\t%Q0, %Q1, %2
2153
   #"
2154
  [(set_attr "length" "4,8")
2155
   (set_attr "predicable" "yes")]
2156
)
2157
 
2158
(define_insn "*iordi_sesidi_di"
2159
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160
        (ior:DI (sign_extend:DI
2161
                 (match_operand:SI 2 "s_register_operand" "r,r"))
2162
                (match_operand:DI 1 "s_register_operand" "?r,0")))]
2163
  "TARGET_ARM"
2164
  "#"
2165
  [(set_attr "length" "8")
2166
   (set_attr "predicable" "yes")]
2167
)
2168
 
2169
(define_expand "iorsi3"
2170
  [(set (match_operand:SI         0 "s_register_operand" "")
2171
        (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172
                (match_operand:SI 2 "reg_or_int_operand" "")))]
2173
  "TARGET_EITHER"
2174
  "
2175
  if (GET_CODE (operands[2]) == CONST_INT)
2176
    {
2177
      if (TARGET_ARM)
2178
        {
2179
          arm_split_constant (IOR, SImode, NULL_RTX,
2180
                              INTVAL (operands[2]), operands[0], operands[1],
2181
                              optimize && !no_new_pseudos);
2182
          DONE;
2183
        }
2184
      else /* TARGET_THUMB */
2185
        operands [2] = force_reg (SImode, operands [2]);
2186
    }
2187
  "
2188
)
2189
 
2190
(define_insn_and_split "*arm_iorsi3"
2191
  [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2192
        (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193
                (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2194
  "TARGET_ARM"
2195
  "@
2196
   orr%?\\t%0, %1, %2
2197
   #"
2198
  "TARGET_ARM
2199
   && GET_CODE (operands[2]) == CONST_INT
2200
   && !const_ok_for_arm (INTVAL (operands[2]))"
2201
  [(clobber (const_int 0))]
2202
  "
2203
  arm_split_constant (IOR, SImode, curr_insn,
2204
                      INTVAL (operands[2]), operands[0], operands[1], 0);
2205
  DONE;
2206
  "
2207
  [(set_attr "length" "4,16")
2208
   (set_attr "predicable" "yes")]
2209
)
2210
 
2211
(define_insn "*thumb_iorsi3"
2212
  [(set (match_operand:SI         0 "register_operand" "=l")
2213
        (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214
                (match_operand:SI 2 "register_operand" "l")))]
2215
  "TARGET_THUMB"
2216
  "orr\\t%0, %0, %2"
2217
  [(set_attr "length" "2")]
2218
)
2219
 
2220
(define_peephole2
2221
  [(match_scratch:SI 3 "r")
2222
   (set (match_operand:SI 0 "arm_general_register_operand" "")
2223
        (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2224
                (match_operand:SI 2 "const_int_operand" "")))]
2225
  "TARGET_ARM
2226
   && !const_ok_for_arm (INTVAL (operands[2]))
2227
   && const_ok_for_arm (~INTVAL (operands[2]))"
2228
  [(set (match_dup 3) (match_dup 2))
2229
   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2230
  ""
2231
)
2232
 
2233
(define_insn "*iorsi3_compare0"
2234
  [(set (reg:CC_NOOV CC_REGNUM)
2235
        (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236
                                 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237
                         (const_int 0)))
2238
   (set (match_operand:SI 0 "s_register_operand" "=r")
2239
        (ior:SI (match_dup 1) (match_dup 2)))]
2240
  "TARGET_ARM"
2241
  "orr%?s\\t%0, %1, %2"
2242
  [(set_attr "conds" "set")]
2243
)
2244
 
2245
(define_insn "*iorsi3_compare0_scratch"
2246
  [(set (reg:CC_NOOV CC_REGNUM)
2247
        (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248
                                 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2249
                         (const_int 0)))
2250
   (clobber (match_scratch:SI 0 "=r"))]
2251
  "TARGET_ARM"
2252
  "orr%?s\\t%0, %1, %2"
2253
  [(set_attr "conds" "set")]
2254
)
2255
 
2256
(define_insn "xordi3"
2257
  [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2258
        (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2259
                (match_operand:DI 2 "s_register_operand"   "r,r")))]
2260
  "TARGET_ARM && !TARGET_IWMMXT"
2261
  "#"
2262
  [(set_attr "length" "8")
2263
   (set_attr "predicable" "yes")]
2264
)
2265
 
2266
(define_insn "*xordi_zesidi_di"
2267
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268
        (xor:DI (zero_extend:DI
2269
                 (match_operand:SI 2 "s_register_operand" "r,r"))
2270
                (match_operand:DI 1 "s_register_operand" "0,?r")))]
2271
  "TARGET_ARM"
2272
  "@
2273
   eor%?\\t%Q0, %Q1, %2
2274
   #"
2275
  [(set_attr "length" "4,8")
2276
   (set_attr "predicable" "yes")]
2277
)
2278
 
2279
(define_insn "*xordi_sesidi_di"
2280
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281
        (xor:DI (sign_extend:DI
2282
                 (match_operand:SI 2 "s_register_operand" "r,r"))
2283
                (match_operand:DI 1 "s_register_operand" "?r,0")))]
2284
  "TARGET_ARM"
2285
  "#"
2286
  [(set_attr "length" "8")
2287
   (set_attr "predicable" "yes")]
2288
)
2289
 
2290
(define_expand "xorsi3"
2291
  [(set (match_operand:SI         0 "s_register_operand" "")
2292
        (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293
                (match_operand:SI 2 "arm_rhs_operand"  "")))]
2294
  "TARGET_EITHER"
2295
  "if (TARGET_THUMB)
2296
     if (GET_CODE (operands[2]) == CONST_INT)
2297
       operands[2] = force_reg (SImode, operands[2]);
2298
  "
2299
)
2300
 
2301
(define_insn "*arm_xorsi3"
2302
  [(set (match_operand:SI         0 "s_register_operand" "=r")
2303
        (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304
                (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2305
  "TARGET_ARM"
2306
  "eor%?\\t%0, %1, %2"
2307
  [(set_attr "predicable" "yes")]
2308
)
2309
 
2310
(define_insn "*thumb_xorsi3"
2311
  [(set (match_operand:SI         0 "register_operand" "=l")
2312
        (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313
                (match_operand:SI 2 "register_operand" "l")))]
2314
  "TARGET_THUMB"
2315
  "eor\\t%0, %0, %2"
2316
  [(set_attr "length" "2")]
2317
)
2318
 
2319
(define_insn "*xorsi3_compare0"
2320
  [(set (reg:CC_NOOV CC_REGNUM)
2321
        (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322
                                 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2323
                         (const_int 0)))
2324
   (set (match_operand:SI 0 "s_register_operand" "=r")
2325
        (xor:SI (match_dup 1) (match_dup 2)))]
2326
  "TARGET_ARM"
2327
  "eor%?s\\t%0, %1, %2"
2328
  [(set_attr "conds" "set")]
2329
)
2330
 
2331
(define_insn "*xorsi3_compare0_scratch"
2332
  [(set (reg:CC_NOOV CC_REGNUM)
2333
        (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334
                                 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2335
                         (const_int 0)))]
2336
  "TARGET_ARM"
2337
  "teq%?\\t%0, %1"
2338
  [(set_attr "conds" "set")]
2339
)
2340
 
2341
; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2342
; (NOT D) we can sometimes merge the final NOT into one of the following
2343
; insns.
2344
 
2345
(define_split
2346
  [(set (match_operand:SI 0 "s_register_operand" "")
2347
        (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348
                        (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349
                (match_operand:SI 3 "arm_rhs_operand" "")))
2350
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
2351
  "TARGET_ARM"
2352
  [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353
                              (not:SI (match_dup 3))))
2354
   (set (match_dup 0) (not:SI (match_dup 4)))]
2355
  ""
2356
)
2357
 
2358
(define_insn "*andsi_iorsi3_notsi"
2359
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360
        (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361
                        (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362
                (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2363
  "TARGET_ARM"
2364
  "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2365
  [(set_attr "length" "8")
2366
   (set_attr "predicable" "yes")]
2367
)
2368
 
2369
(define_split
2370
  [(set (match_operand:SI 0 "s_register_operand" "")
2371
        (match_operator:SI 1 "logical_binary_operator"
2372
         [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373
                           (match_operand:SI 3 "const_int_operand" "")
2374
                           (match_operand:SI 4 "const_int_operand" ""))
2375
          (match_operator:SI 9 "logical_binary_operator"
2376
           [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377
                         (match_operand:SI 6 "const_int_operand" ""))
2378
            (match_operand:SI 7 "s_register_operand" "")])]))
2379
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2380
  "TARGET_ARM
2381
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2383
  [(set (match_dup 8)
2384
        (match_op_dup 1
2385
         [(ashift:SI (match_dup 2) (match_dup 4))
2386
          (match_dup 5)]))
2387
   (set (match_dup 0)
2388
        (match_op_dup 1
2389
         [(lshiftrt:SI (match_dup 8) (match_dup 6))
2390
          (match_dup 7)]))]
2391
  "
2392
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2393
")
2394
 
2395
(define_split
2396
  [(set (match_operand:SI 0 "s_register_operand" "")
2397
        (match_operator:SI 1 "logical_binary_operator"
2398
         [(match_operator:SI 9 "logical_binary_operator"
2399
           [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400
                         (match_operand:SI 6 "const_int_operand" ""))
2401
            (match_operand:SI 7 "s_register_operand" "")])
2402
          (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403
                           (match_operand:SI 3 "const_int_operand" "")
2404
                           (match_operand:SI 4 "const_int_operand" ""))]))
2405
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2406
  "TARGET_ARM
2407
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2409
  [(set (match_dup 8)
2410
        (match_op_dup 1
2411
         [(ashift:SI (match_dup 2) (match_dup 4))
2412
          (match_dup 5)]))
2413
   (set (match_dup 0)
2414
        (match_op_dup 1
2415
         [(lshiftrt:SI (match_dup 8) (match_dup 6))
2416
          (match_dup 7)]))]
2417
  "
2418
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2419
")
2420
 
2421
(define_split
2422
  [(set (match_operand:SI 0 "s_register_operand" "")
2423
        (match_operator:SI 1 "logical_binary_operator"
2424
         [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425
                           (match_operand:SI 3 "const_int_operand" "")
2426
                           (match_operand:SI 4 "const_int_operand" ""))
2427
          (match_operator:SI 9 "logical_binary_operator"
2428
           [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429
                         (match_operand:SI 6 "const_int_operand" ""))
2430
            (match_operand:SI 7 "s_register_operand" "")])]))
2431
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2432
  "TARGET_ARM
2433
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2435
  [(set (match_dup 8)
2436
        (match_op_dup 1
2437
         [(ashift:SI (match_dup 2) (match_dup 4))
2438
          (match_dup 5)]))
2439
   (set (match_dup 0)
2440
        (match_op_dup 1
2441
         [(ashiftrt:SI (match_dup 8) (match_dup 6))
2442
          (match_dup 7)]))]
2443
  "
2444
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2445
")
2446
 
2447
(define_split
2448
  [(set (match_operand:SI 0 "s_register_operand" "")
2449
        (match_operator:SI 1 "logical_binary_operator"
2450
         [(match_operator:SI 9 "logical_binary_operator"
2451
           [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452
                         (match_operand:SI 6 "const_int_operand" ""))
2453
            (match_operand:SI 7 "s_register_operand" "")])
2454
          (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455
                           (match_operand:SI 3 "const_int_operand" "")
2456
                           (match_operand:SI 4 "const_int_operand" ""))]))
2457
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
2458
  "TARGET_ARM
2459
   && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460
   && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2461
  [(set (match_dup 8)
2462
        (match_op_dup 1
2463
         [(ashift:SI (match_dup 2) (match_dup 4))
2464
          (match_dup 5)]))
2465
   (set (match_dup 0)
2466
        (match_op_dup 1
2467
         [(ashiftrt:SI (match_dup 8) (match_dup 6))
2468
          (match_dup 7)]))]
2469
  "
2470
  operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2471
")
2472
 
2473
 
2474
;; Minimum and maximum insns
2475
 
2476
(define_expand "smaxsi3"
2477
  [(parallel [
2478
    (set (match_operand:SI 0 "s_register_operand" "")
2479
         (smax:SI (match_operand:SI 1 "s_register_operand" "")
2480
                  (match_operand:SI 2 "arm_rhs_operand" "")))
2481
    (clobber (reg:CC CC_REGNUM))])]
2482
  "TARGET_ARM"
2483
  "
2484
  if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2485
    {
2486
      /* No need for a clobber of the condition code register here.  */
2487
      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2488
                              gen_rtx_SMAX (SImode, operands[1],
2489
                                            operands[2])));
2490
      DONE;
2491
    }
2492
")
2493
 
2494
(define_insn "*smax_0"
2495
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2496
        (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2497
                 (const_int 0)))]
2498
  "TARGET_ARM"
2499
  "bic%?\\t%0, %1, %1, asr #31"
2500
  [(set_attr "predicable" "yes")]
2501
)
2502
 
2503
(define_insn "*smax_m1"
2504
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2505
        (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2506
                 (const_int -1)))]
2507
  "TARGET_ARM"
2508
  "orr%?\\t%0, %1, %1, asr #31"
2509
  [(set_attr "predicable" "yes")]
2510
)
2511
 
2512
(define_insn "*smax_insn"
2513
  [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2514
        (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2515
                 (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2516
   (clobber (reg:CC CC_REGNUM))]
2517
  "TARGET_ARM"
2518
  "@
2519
   cmp\\t%1, %2\;movlt\\t%0, %2
2520
   cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2521
  [(set_attr "conds" "clob")
2522
   (set_attr "length" "8,12")]
2523
)
2524
 
2525
(define_expand "sminsi3"
2526
  [(parallel [
2527
    (set (match_operand:SI 0 "s_register_operand" "")
2528
         (smin:SI (match_operand:SI 1 "s_register_operand" "")
2529
                  (match_operand:SI 2 "arm_rhs_operand" "")))
2530
    (clobber (reg:CC CC_REGNUM))])]
2531
  "TARGET_ARM"
2532
  "
2533
  if (operands[2] == const0_rtx)
2534
    {
2535
      /* No need for a clobber of the condition code register here.  */
2536
      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2537
                              gen_rtx_SMIN (SImode, operands[1],
2538
                                            operands[2])));
2539
      DONE;
2540
    }
2541
")
2542
 
2543
(define_insn "*smin_0"
2544
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2545
        (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2546
                 (const_int 0)))]
2547
  "TARGET_ARM"
2548
  "and%?\\t%0, %1, %1, asr #31"
2549
  [(set_attr "predicable" "yes")]
2550
)
2551
 
2552
(define_insn "*smin_insn"
2553
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2554
        (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2555
                 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2556
   (clobber (reg:CC CC_REGNUM))]
2557
  "TARGET_ARM"
2558
  "@
2559
   cmp\\t%1, %2\;movge\\t%0, %2
2560
   cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2561
  [(set_attr "conds" "clob")
2562
   (set_attr "length" "8,12")]
2563
)
2564
 
2565
(define_insn "umaxsi3"
2566
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2567
        (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2568
                 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2569
   (clobber (reg:CC CC_REGNUM))]
2570
  "TARGET_ARM"
2571
  "@
2572
   cmp\\t%1, %2\;movcc\\t%0, %2
2573
   cmp\\t%1, %2\;movcs\\t%0, %1
2574
   cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2575
  [(set_attr "conds" "clob")
2576
   (set_attr "length" "8,8,12")]
2577
)
2578
 
2579
(define_insn "uminsi3"
2580
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2581
        (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2582
                 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2583
   (clobber (reg:CC CC_REGNUM))]
2584
  "TARGET_ARM"
2585
  "@
2586
   cmp\\t%1, %2\;movcs\\t%0, %2
2587
   cmp\\t%1, %2\;movcc\\t%0, %1
2588
   cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2589
  [(set_attr "conds" "clob")
2590
   (set_attr "length" "8,8,12")]
2591
)
2592
 
2593
(define_insn "*store_minmaxsi"
2594
  [(set (match_operand:SI 0 "memory_operand" "=m")
2595
        (match_operator:SI 3 "minmax_operator"
2596
         [(match_operand:SI 1 "s_register_operand" "r")
2597
          (match_operand:SI 2 "s_register_operand" "r")]))
2598
   (clobber (reg:CC CC_REGNUM))]
2599
  "TARGET_ARM"
2600
  "*
2601
  operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2602
                                operands[1], operands[2]);
2603
  output_asm_insn (\"cmp\\t%1, %2\", operands);
2604
  output_asm_insn (\"str%d3\\t%1, %0\", operands);
2605
  output_asm_insn (\"str%D3\\t%2, %0\", operands);
2606
  return \"\";
2607
  "
2608
  [(set_attr "conds" "clob")
2609
   (set_attr "length" "12")
2610
   (set_attr "type" "store1")]
2611
)
2612
 
2613
; Reject the frame pointer in operand[1], since reloading this after
2614
; it has been eliminated can cause carnage.
2615
(define_insn "*minmax_arithsi"
2616
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2617
        (match_operator:SI 4 "shiftable_operator"
2618
         [(match_operator:SI 5 "minmax_operator"
2619
           [(match_operand:SI 2 "s_register_operand" "r,r")
2620
            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2621
          (match_operand:SI 1 "s_register_operand" "0,?r")]))
2622
   (clobber (reg:CC CC_REGNUM))]
2623
  "TARGET_ARM && !arm_eliminable_register (operands[1])"
2624
  "*
2625
  {
2626
    enum rtx_code code = GET_CODE (operands[4]);
2627
 
2628
    operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2629
                                  operands[2], operands[3]);
2630
    output_asm_insn (\"cmp\\t%2, %3\", operands);
2631
    output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2632
    if (which_alternative != 0 || operands[3] != const0_rtx
2633
        || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2634
      output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2635
    return \"\";
2636
  }"
2637
  [(set_attr "conds" "clob")
2638
   (set_attr "length" "12")]
2639
)
2640
 
2641
 
2642
;; Shift and rotation insns
2643
 
2644
(define_expand "ashldi3"
2645
  [(set (match_operand:DI            0 "s_register_operand" "")
2646
        (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2647
                   (match_operand:SI 2 "reg_or_int_operand" "")))]
2648
  "TARGET_ARM"
2649
  "
2650
  if (GET_CODE (operands[2]) == CONST_INT)
2651
    {
2652
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2653
        {
2654
          emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2655
          DONE;
2656
        }
2657
        /* Ideally we shouldn't fail here if we could know that operands[1]
2658
           ends up already living in an iwmmxt register. Otherwise it's
2659
           cheaper to have the alternate code being generated than moving
2660
           values to iwmmxt regs and back.  */
2661
        FAIL;
2662
    }
2663
  else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2664
    FAIL;
2665
  "
2666
)
2667
 
2668
(define_insn "arm_ashldi3_1bit"
2669
  [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2670
        (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2671
                   (const_int 1)))
2672
   (clobber (reg:CC CC_REGNUM))]
2673
  "TARGET_ARM"
2674
  "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2675
  [(set_attr "conds" "clob")
2676
   (set_attr "length" "8")]
2677
)
2678
 
2679
(define_expand "ashlsi3"
2680
  [(set (match_operand:SI            0 "s_register_operand" "")
2681
        (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2682
                   (match_operand:SI 2 "arm_rhs_operand" "")))]
2683
  "TARGET_EITHER"
2684
  "
2685
  if (GET_CODE (operands[2]) == CONST_INT
2686
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2687
    {
2688
      emit_insn (gen_movsi (operands[0], const0_rtx));
2689
      DONE;
2690
    }
2691
  "
2692
)
2693
 
2694
(define_insn "*thumb_ashlsi3"
2695
  [(set (match_operand:SI            0 "register_operand" "=l,l")
2696
        (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2697
                   (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2698
  "TARGET_THUMB"
2699
  "lsl\\t%0, %1, %2"
2700
  [(set_attr "length" "2")]
2701
)
2702
 
2703
(define_expand "ashrdi3"
2704
  [(set (match_operand:DI              0 "s_register_operand" "")
2705
        (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2706
                     (match_operand:SI 2 "reg_or_int_operand" "")))]
2707
  "TARGET_ARM"
2708
  "
2709
  if (GET_CODE (operands[2]) == CONST_INT)
2710
    {
2711
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2712
        {
2713
          emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2714
          DONE;
2715
        }
2716
        /* Ideally we shouldn't fail here if we could know that operands[1]
2717
           ends up already living in an iwmmxt register. Otherwise it's
2718
           cheaper to have the alternate code being generated than moving
2719
           values to iwmmxt regs and back.  */
2720
        FAIL;
2721
    }
2722
  else if (!TARGET_REALLY_IWMMXT)
2723
    FAIL;
2724
  "
2725
)
2726
 
2727
(define_insn "arm_ashrdi3_1bit"
2728
  [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2729
        (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2730
                     (const_int 1)))
2731
   (clobber (reg:CC CC_REGNUM))]
2732
  "TARGET_ARM"
2733
  "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2734
  [(set_attr "conds" "clob")
2735
   (set_attr "length" "8")]
2736
)
2737
 
2738
(define_expand "ashrsi3"
2739
  [(set (match_operand:SI              0 "s_register_operand" "")
2740
        (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2741
                     (match_operand:SI 2 "arm_rhs_operand" "")))]
2742
  "TARGET_EITHER"
2743
  "
2744
  if (GET_CODE (operands[2]) == CONST_INT
2745
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2746
    operands[2] = GEN_INT (31);
2747
  "
2748
)
2749
 
2750
(define_insn "*thumb_ashrsi3"
2751
  [(set (match_operand:SI              0 "register_operand" "=l,l")
2752
        (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2753
                     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2754
  "TARGET_THUMB"
2755
  "asr\\t%0, %1, %2"
2756
  [(set_attr "length" "2")]
2757
)
2758
 
2759
(define_expand "lshrdi3"
2760
  [(set (match_operand:DI              0 "s_register_operand" "")
2761
        (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2762
                     (match_operand:SI 2 "reg_or_int_operand" "")))]
2763
  "TARGET_ARM"
2764
  "
2765
  if (GET_CODE (operands[2]) == CONST_INT)
2766
    {
2767
      if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2768
        {
2769
          emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2770
          DONE;
2771
        }
2772
        /* Ideally we shouldn't fail here if we could know that operands[1]
2773
           ends up already living in an iwmmxt register. Otherwise it's
2774
           cheaper to have the alternate code being generated than moving
2775
           values to iwmmxt regs and back.  */
2776
        FAIL;
2777
    }
2778
  else if (!TARGET_REALLY_IWMMXT)
2779
    FAIL;
2780
  "
2781
)
2782
 
2783
(define_insn "arm_lshrdi3_1bit"
2784
  [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2785
        (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2786
                     (const_int 1)))
2787
   (clobber (reg:CC CC_REGNUM))]
2788
  "TARGET_ARM"
2789
  "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2790
  [(set_attr "conds" "clob")
2791
   (set_attr "length" "8")]
2792
)
2793
 
2794
(define_expand "lshrsi3"
2795
  [(set (match_operand:SI              0 "s_register_operand" "")
2796
        (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2797
                     (match_operand:SI 2 "arm_rhs_operand" "")))]
2798
  "TARGET_EITHER"
2799
  "
2800
  if (GET_CODE (operands[2]) == CONST_INT
2801
      && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2802
    {
2803
      emit_insn (gen_movsi (operands[0], const0_rtx));
2804
      DONE;
2805
    }
2806
  "
2807
)
2808
 
2809
(define_insn "*thumb_lshrsi3"
2810
  [(set (match_operand:SI              0 "register_operand" "=l,l")
2811
        (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2812
                     (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2813
  "TARGET_THUMB"
2814
  "lsr\\t%0, %1, %2"
2815
  [(set_attr "length" "2")]
2816
)
2817
 
2818
(define_expand "rotlsi3"
2819
  [(set (match_operand:SI              0 "s_register_operand" "")
2820
        (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2821
                     (match_operand:SI 2 "reg_or_int_operand" "")))]
2822
  "TARGET_ARM"
2823
  "
2824
  if (GET_CODE (operands[2]) == CONST_INT)
2825
    operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2826
  else
2827
    {
2828
      rtx reg = gen_reg_rtx (SImode);
2829
      emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2830
      operands[2] = reg;
2831
    }
2832
  "
2833
)
2834
 
2835
(define_expand "rotrsi3"
2836
  [(set (match_operand:SI              0 "s_register_operand" "")
2837
        (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2838
                     (match_operand:SI 2 "arm_rhs_operand" "")))]
2839
  "TARGET_EITHER"
2840
  "
2841
  if (TARGET_ARM)
2842
    {
2843
      if (GET_CODE (operands[2]) == CONST_INT
2844
          && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2845
        operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2846
    }
2847
  else /* TARGET_THUMB */
2848
    {
2849
      if (GET_CODE (operands [2]) == CONST_INT)
2850
        operands [2] = force_reg (SImode, operands[2]);
2851
    }
2852
  "
2853
)
2854
 
2855
(define_insn "*thumb_rotrsi3"
2856
  [(set (match_operand:SI              0 "register_operand" "=l")
2857
        (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2858
                     (match_operand:SI 2 "register_operand" "l")))]
2859
  "TARGET_THUMB"
2860
  "ror\\t%0, %0, %2"
2861
  [(set_attr "length" "2")]
2862
)
2863
 
2864
(define_insn "*arm_shiftsi3"
2865
  [(set (match_operand:SI   0 "s_register_operand" "=r")
2866
        (match_operator:SI  3 "shift_operator"
2867
         [(match_operand:SI 1 "s_register_operand"  "r")
2868
          (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2869
  "TARGET_ARM"
2870
  "mov%?\\t%0, %1%S3"
2871
  [(set_attr "predicable" "yes")
2872
   (set_attr "shift" "1")
2873
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874
                      (const_string "alu_shift")
2875
                      (const_string "alu_shift_reg")))]
2876
)
2877
 
2878
(define_insn "*shiftsi3_compare0"
2879
  [(set (reg:CC_NOOV CC_REGNUM)
2880
        (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2881
                          [(match_operand:SI 1 "s_register_operand" "r")
2882
                           (match_operand:SI 2 "arm_rhs_operand" "rM")])
2883
                         (const_int 0)))
2884
   (set (match_operand:SI 0 "s_register_operand" "=r")
2885
        (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2886
  "TARGET_ARM"
2887
  "mov%?s\\t%0, %1%S3"
2888
  [(set_attr "conds" "set")
2889
   (set_attr "shift" "1")
2890
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2891
                      (const_string "alu_shift")
2892
                      (const_string "alu_shift_reg")))]
2893
)
2894
 
2895
(define_insn "*shiftsi3_compare0_scratch"
2896
  [(set (reg:CC_NOOV CC_REGNUM)
2897
        (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2898
                          [(match_operand:SI 1 "s_register_operand" "r")
2899
                           (match_operand:SI 2 "arm_rhs_operand" "rM")])
2900
                         (const_int 0)))
2901
   (clobber (match_scratch:SI 0 "=r"))]
2902
  "TARGET_ARM"
2903
  "mov%?s\\t%0, %1%S3"
2904
  [(set_attr "conds" "set")
2905
   (set_attr "shift" "1")]
2906
)
2907
 
2908
(define_insn "*notsi_shiftsi"
2909
  [(set (match_operand:SI 0 "s_register_operand" "=r")
2910
        (not:SI (match_operator:SI 3 "shift_operator"
2911
                 [(match_operand:SI 1 "s_register_operand" "r")
2912
                  (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2913
  "TARGET_ARM"
2914
  "mvn%?\\t%0, %1%S3"
2915
  [(set_attr "predicable" "yes")
2916
   (set_attr "shift" "1")
2917
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2918
                      (const_string "alu_shift")
2919
                      (const_string "alu_shift_reg")))]
2920
)
2921
 
2922
(define_insn "*notsi_shiftsi_compare0"
2923
  [(set (reg:CC_NOOV CC_REGNUM)
2924
        (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2925
                          [(match_operand:SI 1 "s_register_operand" "r")
2926
                           (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2927
                         (const_int 0)))
2928
   (set (match_operand:SI 0 "s_register_operand" "=r")
2929
        (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2930
  "TARGET_ARM"
2931
  "mvn%?s\\t%0, %1%S3"
2932
  [(set_attr "conds" "set")
2933
   (set_attr "shift" "1")
2934
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2935
                      (const_string "alu_shift")
2936
                      (const_string "alu_shift_reg")))]
2937
)
2938
 
2939
(define_insn "*not_shiftsi_compare0_scratch"
2940
  [(set (reg:CC_NOOV CC_REGNUM)
2941
        (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2942
                          [(match_operand:SI 1 "s_register_operand" "r")
2943
                           (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2944
                         (const_int 0)))
2945
   (clobber (match_scratch:SI 0 "=r"))]
2946
  "TARGET_ARM"
2947
  "mvn%?s\\t%0, %1%S3"
2948
  [(set_attr "conds" "set")
2949
   (set_attr "shift" "1")
2950
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2951
                      (const_string "alu_shift")
2952
                      (const_string "alu_shift_reg")))]
2953
)
2954
 
2955
;; We don't really have extzv, but defining this using shifts helps
2956
;; to reduce register pressure later on.
2957
 
2958
(define_expand "extzv"
2959
  [(set (match_dup 4)
2960
        (ashift:SI (match_operand:SI   1 "register_operand" "")
2961
                   (match_operand:SI   2 "const_int_operand" "")))
2962
   (set (match_operand:SI              0 "register_operand" "")
2963
        (lshiftrt:SI (match_dup 4)
2964
                     (match_operand:SI 3 "const_int_operand" "")))]
2965
  "TARGET_THUMB"
2966
  "
2967
  {
2968
    HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2969
    HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2970
 
2971
    operands[3] = GEN_INT (rshift);
2972
 
2973
    if (lshift == 0)
2974
      {
2975
        emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2976
        DONE;
2977
      }
2978
 
2979
    operands[2] = GEN_INT (lshift);
2980
    operands[4] = gen_reg_rtx (SImode);
2981
  }"
2982
)
2983
 
2984
 
2985
;; Unary arithmetic insns
2986
 
2987
(define_expand "negdi2"
2988
 [(parallel
2989
   [(set (match_operand:DI          0 "s_register_operand" "")
2990
          (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2991
    (clobber (reg:CC CC_REGNUM))])]
2992
  "TARGET_EITHER"
2993
  "
2994
  if (TARGET_THUMB)
2995
    {
2996
      if (GET_CODE (operands[1]) != REG)
2997
        operands[1] = force_reg (SImode, operands[1]);
2998
     }
2999
  "
3000
)
3001
 
3002
;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3003
;; The second alternative is to allow the common case of a *full* overlap.
3004
(define_insn "*arm_negdi2"
3005
  [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3006
        (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3007
   (clobber (reg:CC CC_REGNUM))]
3008
  "TARGET_ARM"
3009
  "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3010
  [(set_attr "conds" "clob")
3011
   (set_attr "length" "8")]
3012
)
3013
 
3014
(define_insn "*thumb_negdi2"
3015
  [(set (match_operand:DI         0 "register_operand" "=&l")
3016
        (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3017
   (clobber (reg:CC CC_REGNUM))]
3018
  "TARGET_THUMB"
3019
  "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3020
  [(set_attr "length" "6")]
3021
)
3022
 
3023
(define_expand "negsi2"
3024
  [(set (match_operand:SI         0 "s_register_operand" "")
3025
        (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3026
  "TARGET_EITHER"
3027
  ""
3028
)
3029
 
3030
(define_insn "*arm_negsi2"
3031
  [(set (match_operand:SI         0 "s_register_operand" "=r")
3032
        (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3033
  "TARGET_ARM"
3034
  "rsb%?\\t%0, %1, #0"
3035
  [(set_attr "predicable" "yes")]
3036
)
3037
 
3038
(define_insn "*thumb_negsi2"
3039
  [(set (match_operand:SI         0 "register_operand" "=l")
3040
        (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3041
  "TARGET_THUMB"
3042
  "neg\\t%0, %1"
3043
  [(set_attr "length" "2")]
3044
)
3045
 
3046
(define_expand "negsf2"
3047
  [(set (match_operand:SF         0 "s_register_operand" "")
3048
        (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3049
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3050
  ""
3051
)
3052
 
3053
(define_expand "negdf2"
3054
  [(set (match_operand:DF         0 "s_register_operand" "")
3055
        (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3056
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057
  "")
3058
 
3059
;; abssi2 doesn't really clobber the condition codes if a different register
3060
;; is being set.  To keep things simple, assume during rtl manipulations that
3061
;; it does, but tell the final scan operator the truth.  Similarly for
3062
;; (neg (abs...))
3063
 
3064
(define_expand "abssi2"
3065
  [(parallel
3066
    [(set (match_operand:SI         0 "s_register_operand" "")
3067
          (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3068
     (clobber (reg:CC CC_REGNUM))])]
3069
  "TARGET_ARM"
3070
  "")
3071
 
3072
(define_insn "*arm_abssi2"
3073
  [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3074
        (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3075
   (clobber (reg:CC CC_REGNUM))]
3076
  "TARGET_ARM"
3077
  "@
3078
   cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3079
   eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3080
  [(set_attr "conds" "clob,*")
3081
   (set_attr "shift" "1")
3082
   ;; predicable can't be set based on the variant, so left as no
3083
   (set_attr "length" "8")]
3084
)
3085
 
3086
(define_insn "*neg_abssi2"
3087
  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3088
        (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3089
   (clobber (reg:CC CC_REGNUM))]
3090
  "TARGET_ARM"
3091
  "@
3092
   cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3093
   eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3094
  [(set_attr "conds" "clob,*")
3095
   (set_attr "shift" "1")
3096
   ;; predicable can't be set based on the variant, so left as no
3097
   (set_attr "length" "8")]
3098
)
3099
 
3100
(define_expand "abssf2"
3101
  [(set (match_operand:SF         0 "s_register_operand" "")
3102
        (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3103
  "TARGET_ARM && TARGET_HARD_FLOAT"
3104
  "")
3105
 
3106
(define_expand "absdf2"
3107
  [(set (match_operand:DF         0 "s_register_operand" "")
3108
        (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3109
  "TARGET_ARM && TARGET_HARD_FLOAT"
3110
  "")
3111
 
3112
(define_expand "sqrtsf2"
3113
  [(set (match_operand:SF 0 "s_register_operand" "")
3114
        (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3115
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3116
  "")
3117
 
3118
(define_expand "sqrtdf2"
3119
  [(set (match_operand:DF 0 "s_register_operand" "")
3120
        (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3121
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3122
  "")
3123
 
3124
(define_insn_and_split "one_cmpldi2"
3125
  [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3126
        (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3127
  "TARGET_ARM"
3128
  "#"
3129
  "TARGET_ARM && reload_completed"
3130
  [(set (match_dup 0) (not:SI (match_dup 1)))
3131
   (set (match_dup 2) (not:SI (match_dup 3)))]
3132
  "
3133
  {
3134
    operands[2] = gen_highpart (SImode, operands[0]);
3135
    operands[0] = gen_lowpart (SImode, operands[0]);
3136
    operands[3] = gen_highpart (SImode, operands[1]);
3137
    operands[1] = gen_lowpart (SImode, operands[1]);
3138
  }"
3139
  [(set_attr "length" "8")
3140
   (set_attr "predicable" "yes")]
3141
)
3142
 
3143
(define_expand "one_cmplsi2"
3144
  [(set (match_operand:SI         0 "s_register_operand" "")
3145
        (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3146
  "TARGET_EITHER"
3147
  ""
3148
)
3149
 
3150
(define_insn "*arm_one_cmplsi2"
3151
  [(set (match_operand:SI         0 "s_register_operand" "=r")
3152
        (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3153
  "TARGET_ARM"
3154
  "mvn%?\\t%0, %1"
3155
  [(set_attr "predicable" "yes")]
3156
)
3157
 
3158
(define_insn "*thumb_one_cmplsi2"
3159
  [(set (match_operand:SI         0 "register_operand" "=l")
3160
        (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3161
  "TARGET_THUMB"
3162
  "mvn\\t%0, %1"
3163
  [(set_attr "length" "2")]
3164
)
3165
 
3166
(define_insn "*notsi_compare0"
3167
  [(set (reg:CC_NOOV CC_REGNUM)
3168
        (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3169
                         (const_int 0)))
3170
   (set (match_operand:SI 0 "s_register_operand" "=r")
3171
        (not:SI (match_dup 1)))]
3172
  "TARGET_ARM"
3173
  "mvn%?s\\t%0, %1"
3174
  [(set_attr "conds" "set")]
3175
)
3176
 
3177
(define_insn "*notsi_compare0_scratch"
3178
  [(set (reg:CC_NOOV CC_REGNUM)
3179
        (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3180
                         (const_int 0)))
3181
   (clobber (match_scratch:SI 0 "=r"))]
3182
  "TARGET_ARM"
3183
  "mvn%?s\\t%0, %1"
3184
  [(set_attr "conds" "set")]
3185
)
3186
 
3187
;; Fixed <--> Floating conversion insns
3188
 
3189
(define_expand "floatsisf2"
3190
  [(set (match_operand:SF           0 "s_register_operand" "")
3191
        (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3192
  "TARGET_ARM && TARGET_HARD_FLOAT"
3193
  "
3194
  if (TARGET_MAVERICK)
3195
    {
3196
      emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3197
      DONE;
3198
    }
3199
")
3200
 
3201
(define_expand "floatsidf2"
3202
  [(set (match_operand:DF           0 "s_register_operand" "")
3203
        (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3204
  "TARGET_ARM && TARGET_HARD_FLOAT"
3205
  "
3206
  if (TARGET_MAVERICK)
3207
    {
3208
      emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3209
      DONE;
3210
    }
3211
")
3212
 
3213
(define_expand "fix_truncsfsi2"
3214
  [(set (match_operand:SI         0 "s_register_operand" "")
3215
        (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3216
  "TARGET_ARM && TARGET_HARD_FLOAT"
3217
  "
3218
  if (TARGET_MAVERICK)
3219
    {
3220
      if (!cirrus_fp_register (operands[0], SImode))
3221
        operands[0] = force_reg (SImode, operands[0]);
3222
      if (!cirrus_fp_register (operands[1], SFmode))
3223
        operands[1] = force_reg (SFmode, operands[0]);
3224
      emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3225
      DONE;
3226
    }
3227
")
3228
 
3229
(define_expand "fix_truncdfsi2"
3230
  [(set (match_operand:SI         0 "s_register_operand" "")
3231
        (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3232
  "TARGET_ARM && TARGET_HARD_FLOAT"
3233
  "
3234
  if (TARGET_MAVERICK)
3235
    {
3236
      if (!cirrus_fp_register (operands[1], DFmode))
3237
        operands[1] = force_reg (DFmode, operands[0]);
3238
      emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3239
      DONE;
3240
    }
3241
")
3242
 
3243
;; Truncation insns
3244
 
3245
(define_expand "truncdfsf2"
3246
  [(set (match_operand:SF  0 "s_register_operand" "")
3247
        (float_truncate:SF
3248
         (match_operand:DF 1 "s_register_operand" "")))]
3249
  "TARGET_ARM && TARGET_HARD_FLOAT"
3250
  ""
3251
)
3252
 
3253
;; Zero and sign extension instructions.
3254
 
3255
(define_insn "zero_extendsidi2"
3256
  [(set (match_operand:DI 0 "s_register_operand" "=r")
3257
        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3258
  "TARGET_ARM"
3259
  "*
3260
    if (REGNO (operands[1])
3261
        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3262
      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3263
    return \"mov%?\\t%R0, #0\";
3264
  "
3265
  [(set_attr "length" "8")
3266
   (set_attr "predicable" "yes")]
3267
)
3268
 
3269
(define_insn "zero_extendqidi2"
3270
  [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3271
        (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3272
  "TARGET_ARM"
3273
  "@
3274
   and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3275
   ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3276
  [(set_attr "length" "8")
3277
   (set_attr "predicable" "yes")
3278
   (set_attr "type" "*,load_byte")
3279
   (set_attr "pool_range" "*,4092")
3280
   (set_attr "neg_pool_range" "*,4084")]
3281
)
3282
 
3283
(define_insn "extendsidi2"
3284
  [(set (match_operand:DI 0 "s_register_operand" "=r")
3285
        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3286
  "TARGET_ARM"
3287
  "*
3288
    if (REGNO (operands[1])
3289
        != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3290
      output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3291
    return \"mov%?\\t%R0, %Q0, asr #31\";
3292
  "
3293
  [(set_attr "length" "8")
3294
   (set_attr "shift" "1")
3295
   (set_attr "predicable" "yes")]
3296
)
3297
 
3298
(define_expand "zero_extendhisi2"
3299
  [(set (match_dup 2)
3300
        (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3301
                   (const_int 16)))
3302
   (set (match_operand:SI 0 "s_register_operand" "")
3303
        (lshiftrt:SI (match_dup 2) (const_int 16)))]
3304
  "TARGET_EITHER"
3305
  "
3306
  {
3307
    if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3308
      {
3309
        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3310
                                gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3311
        DONE;
3312
      }
3313
 
3314
    if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3315
      {
3316
        emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3317
        DONE;
3318
      }
3319
 
3320
    if (!s_register_operand (operands[1], HImode))
3321
      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3322
 
3323
    if (arm_arch6)
3324
      {
3325
        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3326
                                gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3327
        DONE;
3328
      }
3329
 
3330
    operands[1] = gen_lowpart (SImode, operands[1]);
3331
    operands[2] = gen_reg_rtx (SImode);
3332
  }"
3333
)
3334
 
3335
(define_insn "*thumb_zero_extendhisi2"
3336
  [(set (match_operand:SI 0 "register_operand" "=l")
3337
        (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3338
  "TARGET_THUMB && !arm_arch6"
3339
  "*
3340
  rtx mem = XEXP (operands[1], 0);
3341
 
3342
  if (GET_CODE (mem) == CONST)
3343
    mem = XEXP (mem, 0);
3344
 
3345
  if (GET_CODE (mem) == LABEL_REF)
3346
    return \"ldr\\t%0, %1\";
3347
 
3348
  if (GET_CODE (mem) == PLUS)
3349
    {
3350
      rtx a = XEXP (mem, 0);
3351
      rtx b = XEXP (mem, 1);
3352
 
3353
      /* This can happen due to bugs in reload.  */
3354
      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3355
        {
3356
          rtx ops[2];
3357
          ops[0] = operands[0];
3358
          ops[1] = a;
3359
 
3360
          output_asm_insn (\"mov        %0, %1\", ops);
3361
 
3362
          XEXP (mem, 0) = operands[0];
3363
       }
3364
 
3365
      else if (   GET_CODE (a) == LABEL_REF
3366
               && GET_CODE (b) == CONST_INT)
3367
        return \"ldr\\t%0, %1\";
3368
    }
3369
 
3370
  return \"ldrh\\t%0, %1\";
3371
  "
3372
  [(set_attr "length" "4")
3373
   (set_attr "type" "load_byte")
3374
   (set_attr "pool_range" "60")]
3375
)
3376
 
3377
(define_insn "*thumb_zero_extendhisi2_v6"
3378
  [(set (match_operand:SI 0 "register_operand" "=l,l")
3379
        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3380
  "TARGET_THUMB && arm_arch6"
3381
  "*
3382
  rtx mem;
3383
 
3384
  if (which_alternative == 0)
3385
    return \"uxth\\t%0, %1\";
3386
 
3387
  mem = XEXP (operands[1], 0);
3388
 
3389
  if (GET_CODE (mem) == CONST)
3390
    mem = XEXP (mem, 0);
3391
 
3392
  if (GET_CODE (mem) == LABEL_REF)
3393
    return \"ldr\\t%0, %1\";
3394
 
3395
  if (GET_CODE (mem) == PLUS)
3396
    {
3397
      rtx a = XEXP (mem, 0);
3398
      rtx b = XEXP (mem, 1);
3399
 
3400
      /* This can happen due to bugs in reload.  */
3401
      if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3402
        {
3403
          rtx ops[2];
3404
          ops[0] = operands[0];
3405
          ops[1] = a;
3406
 
3407
          output_asm_insn (\"mov        %0, %1\", ops);
3408
 
3409
          XEXP (mem, 0) = operands[0];
3410
       }
3411
 
3412
      else if (   GET_CODE (a) == LABEL_REF
3413
               && GET_CODE (b) == CONST_INT)
3414
        return \"ldr\\t%0, %1\";
3415
    }
3416
 
3417
  return \"ldrh\\t%0, %1\";
3418
  "
3419
  [(set_attr "length" "2,4")
3420
   (set_attr "type" "alu_shift,load_byte")
3421
   (set_attr "pool_range" "*,60")]
3422
)
3423
 
3424
(define_insn "*arm_zero_extendhisi2"
3425
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3426
        (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3427
  "TARGET_ARM && arm_arch4 && !arm_arch6"
3428
  "ldr%?h\\t%0, %1"
3429
  [(set_attr "type" "load_byte")
3430
   (set_attr "predicable" "yes")
3431
   (set_attr "pool_range" "256")
3432
   (set_attr "neg_pool_range" "244")]
3433
)
3434
 
3435
(define_insn "*arm_zero_extendhisi2_v6"
3436
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3437
        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3438
  "TARGET_ARM && arm_arch6"
3439
  "@
3440
   uxth%?\\t%0, %1
3441
   ldr%?h\\t%0, %1"
3442
  [(set_attr "type" "alu_shift,load_byte")
3443
   (set_attr "predicable" "yes")
3444
   (set_attr "pool_range" "*,256")
3445
   (set_attr "neg_pool_range" "*,244")]
3446
)
3447
 
3448
(define_insn "*arm_zero_extendhisi2addsi"
3449
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3450
        (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3451
                 (match_operand:SI 2 "s_register_operand" "r")))]
3452
  "TARGET_ARM && arm_arch6"
3453
  "uxtah%?\\t%0, %2, %1"
3454
  [(set_attr "type" "alu_shift")
3455
   (set_attr "predicable" "yes")]
3456
)
3457
 
3458
(define_expand "zero_extendqisi2"
3459
  [(set (match_operand:SI 0 "s_register_operand" "")
3460
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3461
  "TARGET_EITHER"
3462
  "
3463
  if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3464
    {
3465
      if (TARGET_ARM)
3466
        {
3467
          emit_insn (gen_andsi3 (operands[0],
3468
                                 gen_lowpart (SImode, operands[1]),
3469
                                 GEN_INT (255)));
3470
        }
3471
      else /* TARGET_THUMB */
3472
        {
3473
          rtx temp = gen_reg_rtx (SImode);
3474
          rtx ops[3];
3475
 
3476
          operands[1] = copy_to_mode_reg (QImode, operands[1]);
3477
          operands[1] = gen_lowpart (SImode, operands[1]);
3478
 
3479
          ops[0] = temp;
3480
          ops[1] = operands[1];
3481
          ops[2] = GEN_INT (24);
3482
 
3483
          emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3484
                                  gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3485
 
3486
          ops[0] = operands[0];
3487
          ops[1] = temp;
3488
          ops[2] = GEN_INT (24);
3489
 
3490
          emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3491
                                  gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3492
        }
3493
      DONE;
3494
    }
3495
  "
3496
)
3497
 
3498
(define_insn "*thumb_zero_extendqisi2"
3499
  [(set (match_operand:SI 0 "register_operand" "=l")
3500
        (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3501
  "TARGET_THUMB && !arm_arch6"
3502
  "ldrb\\t%0, %1"
3503
  [(set_attr "length" "2")
3504
   (set_attr "type" "load_byte")
3505
   (set_attr "pool_range" "32")]
3506
)
3507
 
3508
(define_insn "*thumb_zero_extendqisi2_v6"
3509
  [(set (match_operand:SI 0 "register_operand" "=l,l")
3510
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3511
  "TARGET_THUMB && arm_arch6"
3512
  "@
3513
   uxtb\\t%0, %1
3514
   ldrb\\t%0, %1"
3515
  [(set_attr "length" "2,2")
3516
   (set_attr "type" "alu_shift,load_byte")
3517
   (set_attr "pool_range" "*,32")]
3518
)
3519
 
3520
(define_insn "*arm_zero_extendqisi2"
3521
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3522
        (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3523
  "TARGET_ARM && !arm_arch6"
3524
  "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3525
  [(set_attr "type" "load_byte")
3526
   (set_attr "predicable" "yes")
3527
   (set_attr "pool_range" "4096")
3528
   (set_attr "neg_pool_range" "4084")]
3529
)
3530
 
3531
(define_insn "*arm_zero_extendqisi2_v6"
3532
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3533
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3534
  "TARGET_ARM && arm_arch6"
3535
  "@
3536
   uxtb%?\\t%0, %1
3537
   ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3538
  [(set_attr "type" "alu_shift,load_byte")
3539
   (set_attr "predicable" "yes")
3540
   (set_attr "pool_range" "*,4096")
3541
   (set_attr "neg_pool_range" "*,4084")]
3542
)
3543
 
3544
(define_insn "*arm_zero_extendqisi2addsi"
3545
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3546
        (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3547
                 (match_operand:SI 2 "s_register_operand" "r")))]
3548
  "TARGET_ARM && arm_arch6"
3549
  "uxtab%?\\t%0, %2, %1"
3550
  [(set_attr "predicable" "yes")
3551
   (set_attr "type" "alu_shift")]
3552
)
3553
 
3554
(define_split
3555
  [(set (match_operand:SI 0 "s_register_operand" "")
3556
        (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3557
   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3558
  "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3559
  [(set (match_dup 2) (match_dup 1))
3560
   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3561
  ""
3562
)
3563
 
3564
(define_split
3565
  [(set (match_operand:SI 0 "s_register_operand" "")
3566
        (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3567
   (clobber (match_operand:SI 2 "s_register_operand" ""))]
3568
  "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3569
  [(set (match_dup 2) (match_dup 1))
3570
   (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3571
  ""
3572
)
3573
 
3574
(define_insn "*compareqi_eq0"
3575
  [(set (reg:CC_Z CC_REGNUM)
3576
        (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3577
                         (const_int 0)))]
3578
  "TARGET_ARM"
3579
  "tst\\t%0, #255"
3580
  [(set_attr "conds" "set")]
3581
)
3582
 
3583
(define_expand "extendhisi2"
3584
  [(set (match_dup 2)
3585
        (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3586
                   (const_int 16)))
3587
   (set (match_operand:SI 0 "s_register_operand" "")
3588
        (ashiftrt:SI (match_dup 2)
3589
                     (const_int 16)))]
3590
  "TARGET_EITHER"
3591
  "
3592
  {
3593
    if (GET_CODE (operands[1]) == MEM)
3594
      {
3595
        if (TARGET_THUMB)
3596
          {
3597
            emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3598
            DONE;
3599
          }
3600
        else if (arm_arch4)
3601
          {
3602
            emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3603
                       gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3604
            DONE;
3605
          }
3606
      }
3607
 
3608
    if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3609
      {
3610
        emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3611
        DONE;
3612
      }
3613
 
3614
    if (!s_register_operand (operands[1], HImode))
3615
      operands[1] = copy_to_mode_reg (HImode, operands[1]);
3616
 
3617
    if (arm_arch6)
3618
      {
3619
        if (TARGET_THUMB)
3620
          emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3621
        else
3622
          emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3623
                     gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3624
 
3625
        DONE;
3626
      }
3627
 
3628
    operands[1] = gen_lowpart (SImode, operands[1]);
3629
    operands[2] = gen_reg_rtx (SImode);
3630
  }"
3631
)
3632
 
3633
(define_insn "thumb_extendhisi2"
3634
  [(set (match_operand:SI 0 "register_operand" "=l")
3635
        (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3636
   (clobber (match_scratch:SI 2 "=&l"))]
3637
  "TARGET_THUMB && !arm_arch6"
3638
  "*
3639
  {
3640
    rtx ops[4];
3641
    rtx mem = XEXP (operands[1], 0);
3642
 
3643
    /* This code used to try to use 'V', and fix the address only if it was
3644
       offsettable, but this fails for e.g. REG+48 because 48 is outside the
3645
       range of QImode offsets, and offsettable_address_p does a QImode
3646
       address check.  */
3647
 
3648
    if (GET_CODE (mem) == CONST)
3649
      mem = XEXP (mem, 0);
3650
 
3651
    if (GET_CODE (mem) == LABEL_REF)
3652
      return \"ldr\\t%0, %1\";
3653
 
3654
    if (GET_CODE (mem) == PLUS)
3655
      {
3656
        rtx a = XEXP (mem, 0);
3657
        rtx b = XEXP (mem, 1);
3658
 
3659
        if (GET_CODE (a) == LABEL_REF
3660
            && GET_CODE (b) == CONST_INT)
3661
          return \"ldr\\t%0, %1\";
3662
 
3663
        if (GET_CODE (b) == REG)
3664
          return \"ldrsh\\t%0, %1\";
3665
 
3666
        ops[1] = a;
3667
        ops[2] = b;
3668
      }
3669
    else
3670
      {
3671
        ops[1] = mem;
3672
        ops[2] = const0_rtx;
3673
      }
3674
 
3675
    gcc_assert (GET_CODE (ops[1]) == REG);
3676
 
3677
    ops[0] = operands[0];
3678
    ops[3] = operands[2];
3679
    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3680
    return \"\";
3681
  }"
3682
  [(set_attr "length" "4")
3683
   (set_attr "type" "load_byte")
3684
   (set_attr "pool_range" "1020")]
3685
)
3686
 
3687
;; We used to have an early-clobber on the scratch register here.
3688
;; However, there's a bug somewhere in reload which means that this
3689
;; can be partially ignored during spill allocation if the memory
3690
;; address also needs reloading; this causes us to die later on when
3691
;; we try to verify the operands.  Fortunately, we don't really need
3692
;; the early-clobber: we can always use operand 0 if operand 2
3693
;; overlaps the address.
3694
(define_insn "*thumb_extendhisi2_insn_v6"
3695
  [(set (match_operand:SI 0 "register_operand" "=l,l")
3696
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3697
   (clobber (match_scratch:SI 2 "=X,l"))]
3698
  "TARGET_THUMB && arm_arch6"
3699
  "*
3700
  {
3701
    rtx ops[4];
3702
    rtx mem;
3703
 
3704
    if (which_alternative == 0)
3705
      return \"sxth\\t%0, %1\";
3706
 
3707
    mem = XEXP (operands[1], 0);
3708
 
3709
    /* This code used to try to use 'V', and fix the address only if it was
3710
       offsettable, but this fails for e.g. REG+48 because 48 is outside the
3711
       range of QImode offsets, and offsettable_address_p does a QImode
3712
       address check.  */
3713
 
3714
    if (GET_CODE (mem) == CONST)
3715
      mem = XEXP (mem, 0);
3716
 
3717
    if (GET_CODE (mem) == LABEL_REF)
3718
      return \"ldr\\t%0, %1\";
3719
 
3720
    if (GET_CODE (mem) == PLUS)
3721
      {
3722
        rtx a = XEXP (mem, 0);
3723
        rtx b = XEXP (mem, 1);
3724
 
3725
        if (GET_CODE (a) == LABEL_REF
3726
            && GET_CODE (b) == CONST_INT)
3727
          return \"ldr\\t%0, %1\";
3728
 
3729
        if (GET_CODE (b) == REG)
3730
          return \"ldrsh\\t%0, %1\";
3731
 
3732
        ops[1] = a;
3733
        ops[2] = b;
3734
      }
3735
    else
3736
      {
3737
        ops[1] = mem;
3738
        ops[2] = const0_rtx;
3739
      }
3740
 
3741
    gcc_assert (GET_CODE (ops[1]) == REG);
3742
 
3743
    ops[0] = operands[0];
3744
    if (reg_mentioned_p (operands[2], ops[1]))
3745
      ops[3] = ops[0];
3746
    else
3747
      ops[3] = operands[2];
3748
    output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3749
    return \"\";
3750
  }"
3751
  [(set_attr "length" "2,4")
3752
   (set_attr "type" "alu_shift,load_byte")
3753
   (set_attr "pool_range" "*,1020")]
3754
)
3755
 
3756
(define_expand "extendhisi2_mem"
3757
  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3758
   (set (match_dup 3)
3759
        (zero_extend:SI (match_dup 7)))
3760
   (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3761
   (set (match_operand:SI 0 "" "")
3762
        (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3763
  "TARGET_ARM"
3764
  "
3765
  {
3766
    rtx mem1, mem2;
3767
    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3768
 
3769
    mem1 = change_address (operands[1], QImode, addr);
3770
    mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3771
    operands[0] = gen_lowpart (SImode, operands[0]);
3772
    operands[1] = mem1;
3773
    operands[2] = gen_reg_rtx (SImode);
3774
    operands[3] = gen_reg_rtx (SImode);
3775
    operands[6] = gen_reg_rtx (SImode);
3776
    operands[7] = mem2;
3777
 
3778
    if (BYTES_BIG_ENDIAN)
3779
      {
3780
        operands[4] = operands[2];
3781
        operands[5] = operands[3];
3782
      }
3783
    else
3784
      {
3785
        operands[4] = operands[3];
3786
        operands[5] = operands[2];
3787
      }
3788
  }"
3789
)
3790
 
3791
(define_insn "*arm_extendhisi2"
3792
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3793
        (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3794
  "TARGET_ARM && arm_arch4 && !arm_arch6"
3795
  "ldr%?sh\\t%0, %1"
3796
  [(set_attr "type" "load_byte")
3797
   (set_attr "predicable" "yes")
3798
   (set_attr "pool_range" "256")
3799
   (set_attr "neg_pool_range" "244")]
3800
)
3801
 
3802
(define_insn "*arm_extendhisi2_v6"
3803
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3804
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3805
  "TARGET_ARM && arm_arch6"
3806
  "@
3807
   sxth%?\\t%0, %1
3808
   ldr%?sh\\t%0, %1"
3809
  [(set_attr "type" "alu_shift,load_byte")
3810
   (set_attr "predicable" "yes")
3811
   (set_attr "pool_range" "*,256")
3812
   (set_attr "neg_pool_range" "*,244")]
3813
)
3814
 
3815
(define_insn "*arm_extendhisi2addsi"
3816
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3817
        (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3818
                 (match_operand:SI 2 "s_register_operand" "r")))]
3819
  "TARGET_ARM && arm_arch6"
3820
  "sxtah%?\\t%0, %2, %1"
3821
)
3822
 
3823
(define_expand "extendqihi2"
3824
  [(set (match_dup 2)
3825
        (ashift:SI (match_operand:QI 1 "general_operand" "")
3826
                   (const_int 24)))
3827
   (set (match_operand:HI 0 "s_register_operand" "")
3828
        (ashiftrt:SI (match_dup 2)
3829
                     (const_int 24)))]
3830
  "TARGET_ARM"
3831
  "
3832
  {
3833
    if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3834
      {
3835
        emit_insn (gen_rtx_SET (VOIDmode,
3836
                                operands[0],
3837
                                gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3838
        DONE;
3839
      }
3840
    if (!s_register_operand (operands[1], QImode))
3841
      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3842
    operands[0] = gen_lowpart (SImode, operands[0]);
3843
    operands[1] = gen_lowpart (SImode, operands[1]);
3844
    operands[2] = gen_reg_rtx (SImode);
3845
  }"
3846
)
3847
 
3848
(define_insn "*extendqihi_insn"
3849
  [(set (match_operand:HI 0 "s_register_operand" "=r")
3850
        (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3851
  "TARGET_ARM && arm_arch4"
3852
  "ldr%?sb\\t%0, %1"
3853
  [(set_attr "type" "load_byte")
3854
   (set_attr "predicable" "yes")
3855
   (set_attr "pool_range" "256")
3856
   (set_attr "neg_pool_range" "244")]
3857
)
3858
 
3859
(define_expand "extendqisi2"
3860
  [(set (match_dup 2)
3861
        (ashift:SI (match_operand:QI 1 "general_operand" "")
3862
                   (const_int 24)))
3863
   (set (match_operand:SI 0 "s_register_operand" "")
3864
        (ashiftrt:SI (match_dup 2)
3865
                     (const_int 24)))]
3866
  "TARGET_EITHER"
3867
  "
3868
  {
3869
    if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3870
      {
3871
        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3872
                                gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3873
        DONE;
3874
      }
3875
 
3876
    if (!s_register_operand (operands[1], QImode))
3877
      operands[1] = copy_to_mode_reg (QImode, operands[1]);
3878
 
3879
    if (arm_arch6)
3880
      {
3881
        emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3882
                                gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3883
        DONE;
3884
      }
3885
 
3886
    operands[1] = gen_lowpart (SImode, operands[1]);
3887
    operands[2] = gen_reg_rtx (SImode);
3888
  }"
3889
)
3890
 
3891
(define_insn "*arm_extendqisi"
3892
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3893
        (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3894
  "TARGET_ARM && arm_arch4 && !arm_arch6"
3895
  "ldr%?sb\\t%0, %1"
3896
  [(set_attr "type" "load_byte")
3897
   (set_attr "predicable" "yes")
3898
   (set_attr "pool_range" "256")
3899
   (set_attr "neg_pool_range" "244")]
3900
)
3901
 
3902
(define_insn "*arm_extendqisi_v6"
3903
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3904
        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3905
  "TARGET_ARM && arm_arch6"
3906
  "@
3907
   sxtb%?\\t%0, %1
3908
   ldr%?sb\\t%0, %1"
3909
  [(set_attr "type" "alu_shift,load_byte")
3910
   (set_attr "predicable" "yes")
3911
   (set_attr "pool_range" "*,256")
3912
   (set_attr "neg_pool_range" "*,244")]
3913
)
3914
 
3915
(define_insn "*arm_extendqisi2addsi"
3916
  [(set (match_operand:SI 0 "s_register_operand" "=r")
3917
        (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3918
                 (match_operand:SI 2 "s_register_operand" "r")))]
3919
  "TARGET_ARM && arm_arch6"
3920
  "sxtab%?\\t%0, %2, %1"
3921
  [(set_attr "type" "alu_shift")
3922
   (set_attr "predicable" "yes")]
3923
)
3924
 
3925
(define_insn "*thumb_extendqisi2"
3926
  [(set (match_operand:SI 0 "register_operand" "=l,l")
3927
        (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3928
  "TARGET_THUMB && !arm_arch6"
3929
  "*
3930
  {
3931
    rtx ops[3];
3932
    rtx mem = XEXP (operands[1], 0);
3933
 
3934
    if (GET_CODE (mem) == CONST)
3935
      mem = XEXP (mem, 0);
3936
 
3937
    if (GET_CODE (mem) == LABEL_REF)
3938
      return \"ldr\\t%0, %1\";
3939
 
3940
    if (GET_CODE (mem) == PLUS
3941
        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3942
      return \"ldr\\t%0, %1\";
3943
 
3944
    if (which_alternative == 0)
3945
      return \"ldrsb\\t%0, %1\";
3946
 
3947
    ops[0] = operands[0];
3948
 
3949
    if (GET_CODE (mem) == PLUS)
3950
      {
3951
        rtx a = XEXP (mem, 0);
3952
        rtx b = XEXP (mem, 1);
3953
 
3954
        ops[1] = a;
3955
        ops[2] = b;
3956
 
3957
        if (GET_CODE (a) == REG)
3958
          {
3959
            if (GET_CODE (b) == REG)
3960
              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3961
            else if (REGNO (a) == REGNO (ops[0]))
3962
              {
3963
                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3964
                output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3965
                output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3966
              }
3967
            else
3968
              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3969
          }
3970
        else
3971
          {
3972
            gcc_assert (GET_CODE (b) == REG);
3973
            if (REGNO (b) == REGNO (ops[0]))
3974
              {
3975
                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3976
                output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3977
                output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3978
              }
3979
            else
3980
              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3981
          }
3982
      }
3983
    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3984
      {
3985
        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3986
        output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3987
        output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3988
      }
3989
    else
3990
      {
3991
        ops[1] = mem;
3992
        ops[2] = const0_rtx;
3993
 
3994
        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3995
      }
3996
    return \"\";
3997
  }"
3998
  [(set_attr "length" "2,6")
3999
   (set_attr "type" "load_byte,load_byte")
4000
   (set_attr "pool_range" "32,32")]
4001
)
4002
 
4003
(define_insn "*thumb_extendqisi2_v6"
4004
  [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4005
        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4006
  "TARGET_THUMB && arm_arch6"
4007
  "*
4008
  {
4009
    rtx ops[3];
4010
    rtx mem;
4011
 
4012
    if (which_alternative == 0)
4013
      return \"sxtb\\t%0, %1\";
4014
 
4015
    mem = XEXP (operands[1], 0);
4016
 
4017
    if (GET_CODE (mem) == CONST)
4018
      mem = XEXP (mem, 0);
4019
 
4020
    if (GET_CODE (mem) == LABEL_REF)
4021
      return \"ldr\\t%0, %1\";
4022
 
4023
    if (GET_CODE (mem) == PLUS
4024
        && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4025
      return \"ldr\\t%0, %1\";
4026
 
4027
    if (which_alternative == 0)
4028
      return \"ldrsb\\t%0, %1\";
4029
 
4030
    ops[0] = operands[0];
4031
 
4032
    if (GET_CODE (mem) == PLUS)
4033
      {
4034
        rtx a = XEXP (mem, 0);
4035
        rtx b = XEXP (mem, 1);
4036
 
4037
        ops[1] = a;
4038
        ops[2] = b;
4039
 
4040
        if (GET_CODE (a) == REG)
4041
          {
4042
            if (GET_CODE (b) == REG)
4043
              output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4044
            else if (REGNO (a) == REGNO (ops[0]))
4045
              {
4046
                output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4047
                output_asm_insn (\"sxtb\\t%0, %0\", ops);
4048
              }
4049
            else
4050
              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4051
          }
4052
        else
4053
          {
4054
            gcc_assert (GET_CODE (b) == REG);
4055
            if (REGNO (b) == REGNO (ops[0]))
4056
              {
4057
                output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4058
                output_asm_insn (\"sxtb\\t%0, %0\", ops);
4059
              }
4060
            else
4061
              output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4062
          }
4063
      }
4064
    else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4065
      {
4066
        output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4067
        output_asm_insn (\"sxtb\\t%0, %0\", ops);
4068
      }
4069
    else
4070
      {
4071
        ops[1] = mem;
4072
        ops[2] = const0_rtx;
4073
 
4074
        output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4075
      }
4076
    return \"\";
4077
  }"
4078
  [(set_attr "length" "2,2,4")
4079
   (set_attr "type" "alu_shift,load_byte,load_byte")
4080
   (set_attr "pool_range" "*,32,32")]
4081
)
4082
 
4083
(define_expand "extendsfdf2"
4084
  [(set (match_operand:DF                  0 "s_register_operand" "")
4085
        (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4086
  "TARGET_ARM && TARGET_HARD_FLOAT"
4087
  ""
4088
)
4089
 
4090
;; Move insns (including loads and stores)
4091
 
4092
;; XXX Just some ideas about movti.
4093
;; I don't think these are a good idea on the arm, there just aren't enough
4094
;; registers
4095
;;(define_expand "loadti"
4096
;;  [(set (match_operand:TI 0 "s_register_operand" "")
4097
;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4098
;;  "" "")
4099
 
4100
;;(define_expand "storeti"
4101
;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4102
;;      (match_operand:TI 1 "s_register_operand" ""))]
4103
;;  "" "")
4104
 
4105
;;(define_expand "movti"
4106
;;  [(set (match_operand:TI 0 "general_operand" "")
4107
;;      (match_operand:TI 1 "general_operand" ""))]
4108
;;  ""
4109
;;  "
4110
;;{
4111
;;  rtx insn;
4112
;;
4113
;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4114
;;    operands[1] = copy_to_reg (operands[1]);
4115
;;  if (GET_CODE (operands[0]) == MEM)
4116
;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4117
;;  else if (GET_CODE (operands[1]) == MEM)
4118
;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4119
;;  else
4120
;;    FAIL;
4121
;;
4122
;;  emit_insn (insn);
4123
;;  DONE;
4124
;;}")
4125
 
4126
;; Recognize garbage generated above.
4127
 
4128
;;(define_insn ""
4129
;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4130
;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4131
;;  ""
4132
;;  "*
4133
;;  {
4134
;;    register mem = (which_alternative < 3);
4135
;;    register const char *template;
4136
;;
4137
;;    operands[mem] = XEXP (operands[mem], 0);
4138
;;    switch (which_alternative)
4139
;;      {
4140
;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4141
;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4142
;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4143
;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4144
;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4145
;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4146
;;      }
4147
;;    output_asm_insn (template, operands);
4148
;;    return \"\";
4149
;;  }")
4150
 
4151
(define_expand "movdi"
4152
  [(set (match_operand:DI 0 "general_operand" "")
4153
        (match_operand:DI 1 "general_operand" ""))]
4154
  "TARGET_EITHER"
4155
  "
4156
  if (!no_new_pseudos)
4157
    {
4158
      if (GET_CODE (operands[0]) != REG)
4159
        operands[1] = force_reg (DImode, operands[1]);
4160
    }
4161
  "
4162
)
4163
 
4164
(define_insn "*arm_movdi"
4165
  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4166
        (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4167
  "TARGET_ARM
4168
   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4169
   && !TARGET_IWMMXT
4170
   && (   register_operand (operands[0], DImode)
4171
       || register_operand (operands[1], DImode))"
4172
  "*
4173
  switch (which_alternative)
4174
    {
4175
    case 0:
4176
    case 1:
4177
    case 2:
4178
      return \"#\";
4179
    default:
4180
      return output_move_double (operands);
4181
    }
4182
  "
4183
  [(set_attr "length" "8,12,16,8,8")
4184
   (set_attr "type" "*,*,*,load2,store2")
4185
   (set_attr "pool_range" "*,*,*,1020,*")
4186
   (set_attr "neg_pool_range" "*,*,*,1008,*")]
4187
)
4188
 
4189
(define_split
4190
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4191
        (match_operand:ANY64 1 "const_double_operand" ""))]
4192
  "TARGET_ARM
4193
   && reload_completed
4194
   && (arm_const_double_inline_cost (operands[1])
4195
       <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4196
  [(const_int 0)]
4197
  "
4198
  arm_split_constant (SET, SImode, curr_insn,
4199
                      INTVAL (gen_lowpart (SImode, operands[1])),
4200
                      gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4201
  arm_split_constant (SET, SImode, curr_insn,
4202
                      INTVAL (gen_highpart_mode (SImode,
4203
                                                 GET_MODE (operands[0]),
4204
                                                 operands[1])),
4205
                      gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4206
  DONE;
4207
  "
4208
)
4209
 
4210
; If optimizing for size, or if we have load delay slots, then
4211
; we want to split the constant into two separate operations.
4212
; In both cases this may split a trivial part into a single data op
4213
; leaving a single complex constant to load.  We can also get longer
4214
; offsets in a LDR which means we get better chances of sharing the pool
4215
; entries.  Finally, we can normally do a better job of scheduling
4216
; LDR instructions than we can with LDM.
4217
; This pattern will only match if the one above did not.
4218
(define_split
4219
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4220
        (match_operand:ANY64 1 "const_double_operand" ""))]
4221
  "TARGET_ARM && reload_completed
4222
   && arm_const_double_by_parts (operands[1])"
4223
  [(set (match_dup 0) (match_dup 1))
4224
   (set (match_dup 2) (match_dup 3))]
4225
  "
4226
  operands[2] = gen_highpart (SImode, operands[0]);
4227
  operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4228
                                   operands[1]);
4229
  operands[0] = gen_lowpart (SImode, operands[0]);
4230
  operands[1] = gen_lowpart (SImode, operands[1]);
4231
  "
4232
)
4233
 
4234
(define_split
4235
  [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4236
        (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4237
  "TARGET_EITHER && reload_completed"
4238
  [(set (match_dup 0) (match_dup 1))
4239
   (set (match_dup 2) (match_dup 3))]
4240
  "
4241
  operands[2] = gen_highpart (SImode, operands[0]);
4242
  operands[3] = gen_highpart (SImode, operands[1]);
4243
  operands[0] = gen_lowpart (SImode, operands[0]);
4244
  operands[1] = gen_lowpart (SImode, operands[1]);
4245
 
4246
  /* Handle a partial overlap.  */
4247
  if (rtx_equal_p (operands[0], operands[3]))
4248
    {
4249
      rtx tmp0 = operands[0];
4250
      rtx tmp1 = operands[1];
4251
 
4252
      operands[0] = operands[2];
4253
      operands[1] = operands[3];
4254
      operands[2] = tmp0;
4255
      operands[3] = tmp1;
4256
    }
4257
  "
4258
)
4259
 
4260
;; We can't actually do base+index doubleword loads if the index and
4261
;; destination overlap.  Split here so that we at least have chance to
4262
;; schedule.
4263
(define_split
4264
  [(set (match_operand:DI 0 "s_register_operand" "")
4265
        (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4266
                         (match_operand:SI 2 "s_register_operand" ""))))]
4267
  "TARGET_LDRD
4268
  && reg_overlap_mentioned_p (operands[0], operands[1])
4269
  && reg_overlap_mentioned_p (operands[0], operands[2])"
4270
  [(set (match_dup 4)
4271
        (plus:SI (match_dup 1)
4272
                 (match_dup 2)))
4273
   (set (match_dup 0)
4274
        (mem:DI (match_dup 4)))]
4275
  "
4276
  operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4277
  "
4278
)
4279
 
4280
;;; ??? This should have alternatives for constants.
4281
;;; ??? This was originally identical to the movdf_insn pattern.
4282
;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4283
;;; thumb_reorg with a memory reference.
4284
(define_insn "*thumb_movdi_insn"
4285
  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4286
        (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4287
  "TARGET_THUMB
4288
   && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4289
   && (   register_operand (operands[0], DImode)
4290
       || register_operand (operands[1], DImode))"
4291
  "*
4292
  {
4293
  switch (which_alternative)
4294
    {
4295
    default:
4296
    case 0:
4297
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4298
        return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4299
      return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4300
    case 1:
4301
      return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4302
    case 2:
4303
      operands[1] = GEN_INT (- INTVAL (operands[1]));
4304
      return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4305
    case 3:
4306
      return \"ldmia\\t%1, {%0, %H0}\";
4307
    case 4:
4308
      return \"stmia\\t%0, {%1, %H1}\";
4309
    case 5:
4310
      return thumb_load_double_from_address (operands);
4311
    case 6:
4312
      operands[2] = gen_rtx_MEM (SImode,
4313
                             plus_constant (XEXP (operands[0], 0), 4));
4314
      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4315
      return \"\";
4316
    case 7:
4317
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4318
        return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4319
      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4320
    }
4321
  }"
4322
  [(set_attr "length" "4,4,6,2,2,6,4,4")
4323
   (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4324
   (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4325
)
4326
 
4327
(define_expand "movsi"
4328
  [(set (match_operand:SI 0 "general_operand" "")
4329
        (match_operand:SI 1 "general_operand" ""))]
4330
  "TARGET_EITHER"
4331
  "
4332
  if (TARGET_ARM)
4333
    {
4334
      /* Everything except mem = const or mem = mem can be done easily.  */
4335
      if (GET_CODE (operands[0]) == MEM)
4336
        operands[1] = force_reg (SImode, operands[1]);
4337
      if (arm_general_register_operand (operands[0], SImode)
4338
          && GET_CODE (operands[1]) == CONST_INT
4339
          && !(const_ok_for_arm (INTVAL (operands[1]))
4340
               || const_ok_for_arm (~INTVAL (operands[1]))))
4341
        {
4342
           arm_split_constant (SET, SImode, NULL_RTX,
4343
                               INTVAL (operands[1]), operands[0], NULL_RTX,
4344
                               optimize && !no_new_pseudos);
4345
          DONE;
4346
        }
4347
    }
4348
  else /* TARGET_THUMB....  */
4349
    {
4350
      if (!no_new_pseudos)
4351
        {
4352
          if (GET_CODE (operands[0]) != REG)
4353
            operands[1] = force_reg (SImode, operands[1]);
4354
        }
4355
    }
4356
 
4357
  /* Recognize the case where operand[1] is a reference to thread-local
4358
     data and load its address to a register.  */
4359
  if (arm_tls_referenced_p (operands[1]))
4360
    {
4361
      rtx tmp = operands[1];
4362
      rtx addend = NULL;
4363
 
4364
      if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4365
        {
4366
          addend = XEXP (XEXP (tmp, 0), 1);
4367
          tmp = XEXP (XEXP (tmp, 0), 0);
4368
        }
4369
 
4370
      gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4371
      gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4372
 
4373
      tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4374
      if (addend)
4375
        {
4376
          tmp = gen_rtx_PLUS (SImode, tmp, addend);
4377
          tmp = force_operand (tmp, operands[0]);
4378
        }
4379
      operands[1] = tmp;
4380
    }
4381
  else if (flag_pic
4382
           && (CONSTANT_P (operands[1])
4383
               || symbol_mentioned_p (operands[1])
4384
               || label_mentioned_p (operands[1])))
4385
      operands[1] = legitimize_pic_address (operands[1], SImode,
4386
                                            (no_new_pseudos ? operands[0] : 0));
4387
  "
4388
)
4389
 
4390
(define_insn "*arm_movsi_insn"
4391
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4392
        (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4393
  "TARGET_ARM && ! TARGET_IWMMXT
4394
   && !(TARGET_HARD_FLOAT && TARGET_VFP)
4395
   && (   register_operand (operands[0], SImode)
4396
       || register_operand (operands[1], SImode))"
4397
  "@
4398
   mov%?\\t%0, %1
4399
   mvn%?\\t%0, #%B1
4400
   ldr%?\\t%0, %1
4401
   str%?\\t%1, %0"
4402
  [(set_attr "type" "*,*,load1,store1")
4403
   (set_attr "predicable" "yes")
4404
   (set_attr "pool_range" "*,*,4096,*")
4405
   (set_attr "neg_pool_range" "*,*,4084,*")]
4406
)
4407
 
4408
(define_split
4409
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
4410
        (match_operand:SI 1 "const_int_operand" ""))]
4411
  "TARGET_ARM
4412
  && (!(const_ok_for_arm (INTVAL (operands[1]))
4413
        || const_ok_for_arm (~INTVAL (operands[1]))))"
4414
  [(clobber (const_int 0))]
4415
  "
4416
  arm_split_constant (SET, SImode, NULL_RTX,
4417
                      INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4418
  DONE;
4419
  "
4420
)
4421
 
4422
(define_insn "*thumb_movsi_insn"
4423
  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4424
        (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4425
  "TARGET_THUMB
4426
   && (   register_operand (operands[0], SImode)
4427
       || register_operand (operands[1], SImode))"
4428
  "@
4429
   mov  %0, %1
4430
   mov  %0, %1
4431
   #
4432
   #
4433
   ldmia\\t%1, {%0}
4434
   stmia\\t%0, {%1}
4435
   ldr\\t%0, %1
4436
   str\\t%1, %0
4437
   mov\\t%0, %1"
4438
  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4439
   (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4440
   (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4441
)
4442
 
4443
(define_split
4444
  [(set (match_operand:SI 0 "register_operand" "")
4445
        (match_operand:SI 1 "const_int_operand" ""))]
4446
  "TARGET_THUMB && satisfies_constraint_J (operands[1])"
4447
  [(set (match_dup 0) (match_dup 1))
4448
   (set (match_dup 0) (neg:SI (match_dup 0)))]
4449
  "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4450
)
4451
 
4452
(define_split
4453
  [(set (match_operand:SI 0 "register_operand" "")
4454
        (match_operand:SI 1 "const_int_operand" ""))]
4455
  "TARGET_THUMB && satisfies_constraint_K (operands[1])"
4456
  [(set (match_dup 0) (match_dup 1))
4457
   (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4458
  "
4459
  {
4460
    unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4461
    unsigned HOST_WIDE_INT mask = 0xff;
4462
    int i;
4463
 
4464
    for (i = 0; i < 25; i++)
4465
      if ((val & (mask << i)) == val)
4466
        break;
4467
 
4468
    /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4469
    if (i == 0)
4470
      FAIL;
4471
 
4472
    operands[1] = GEN_INT (val >> i);
4473
    operands[2] = GEN_INT (i);
4474
  }"
4475
)
4476
 
4477
;; When generating pic, we need to load the symbol offset into a register.
4478
;; So that the optimizer does not confuse this with a normal symbol load
4479
;; we use an unspec.  The offset will be loaded from a constant pool entry,
4480
;; since that is the only type of relocation we can use.
4481
 
4482
;; The rather odd constraints on the following are to force reload to leave
4483
;; the insn alone, and to force the minipool generation pass to then move
4484
;; the GOT symbol to memory.
4485
 
4486
(define_insn "pic_load_addr_arm"
4487
  [(set (match_operand:SI 0 "s_register_operand" "=r")
4488
        (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4489
  "TARGET_ARM && flag_pic"
4490
  "ldr%?\\t%0, %1"
4491
  [(set_attr "type" "load1")
4492
   (set (attr "pool_range")     (const_int 4096))
4493
   (set (attr "neg_pool_range") (const_int 4084))]
4494
)
4495
 
4496
(define_insn "pic_load_addr_thumb"
4497
  [(set (match_operand:SI 0 "s_register_operand" "=l")
4498
        (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4499
  "TARGET_THUMB && flag_pic"
4500
  "ldr\\t%0, %1"
4501
  [(set_attr "type" "load1")
4502
   (set (attr "pool_range") (const_int 1024))]
4503
)
4504
 
4505
;; This variant is used for AOF assembly, since it needs to mention the
4506
;; pic register in the rtl.
4507
(define_expand "pic_load_addr_based"
4508
  [(set (match_operand:SI 0 "s_register_operand" "")
4509
        (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4510
  "TARGET_ARM && flag_pic"
4511
  "operands[2] = cfun->machine->pic_reg;"
4512
)
4513
 
4514
(define_insn "*pic_load_addr_based_insn"
4515
  [(set (match_operand:SI 0 "s_register_operand" "=r")
4516
        (unspec:SI [(match_operand 1 "" "")
4517
                    (match_operand 2 "s_register_operand" "r")]
4518
                   UNSPEC_PIC_SYM))]
4519
  "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4520
  "*
4521
#ifdef AOF_ASSEMBLER
4522
  operands[1] = aof_pic_entry (operands[1]);
4523
#endif
4524
  output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4525
  return \"\";
4526
  "
4527
  [(set_attr "type" "load1")
4528
   (set (attr "pool_range")
4529
        (if_then_else (eq_attr "is_thumb" "yes")
4530
                      (const_int 1024)
4531
                      (const_int 4096)))
4532
   (set (attr "neg_pool_range")
4533
        (if_then_else (eq_attr "is_thumb" "yes")
4534
                      (const_int 0)
4535
                      (const_int 4084)))]
4536
)
4537
 
4538
(define_insn "pic_add_dot_plus_four"
4539
  [(set (match_operand:SI 0 "register_operand" "=r")
4540
        (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4541
                             (const (plus:SI (pc) (const_int 4))))]
4542
                   UNSPEC_PIC_BASE))
4543
   (use (match_operand 2 "" ""))]
4544
  "TARGET_THUMB"
4545
  "*
4546
  (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4547
                                     INTVAL (operands[2]));
4548
  return \"add\\t%0, %|pc\";
4549
  "
4550
  [(set_attr "length" "2")]
4551
)
4552
 
4553
(define_insn "pic_add_dot_plus_eight"
4554
  [(set (match_operand:SI 0 "register_operand" "=r")
4555
        (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4556
                             (const (plus:SI (pc) (const_int 8))))]
4557
                   UNSPEC_PIC_BASE))
4558
   (use (match_operand 2 "" ""))]
4559
  "TARGET_ARM"
4560
  "*
4561
    (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4562
                                       INTVAL (operands[2]));
4563
    return \"add%?\\t%0, %|pc, %1\";
4564
  "
4565
  [(set_attr "predicable" "yes")]
4566
)
4567
 
4568
(define_insn "tls_load_dot_plus_eight"
4569
  [(set (match_operand:SI 0 "register_operand" "+r")
4570
        (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4571
                                     (const (plus:SI (pc) (const_int 8))))]
4572
                           UNSPEC_PIC_BASE)))
4573
   (use (match_operand 2 "" ""))]
4574
  "TARGET_ARM"
4575
  "*
4576
    (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4577
                                       INTVAL (operands[2]));
4578
    return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4579
  "
4580
  [(set_attr "predicable" "yes")]
4581
)
4582
 
4583
;; PIC references to local variables can generate pic_add_dot_plus_eight
4584
;; followed by a load.  These sequences can be crunched down to
4585
;; tls_load_dot_plus_eight by a peephole.
4586
 
4587
(define_peephole2
4588
  [(parallel [(set (match_operand:SI 0 "register_operand" "")
4589
                   (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4590
                                        (const (plus:SI (pc) (const_int 8))))]
4591
                              UNSPEC_PIC_BASE))
4592
              (use (label_ref (match_operand 1 "" "")))])
4593
   (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4594
  "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4595
  [(parallel [(set (match_dup 2)
4596
                   (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4597
                                                (const (plus:SI (pc) (const_int 8))))]
4598
                                      UNSPEC_PIC_BASE)))
4599
              (use (label_ref (match_dup 1)))])]
4600
  ""
4601
)
4602
 
4603
(define_expand "builtin_setjmp_receiver"
4604
  [(label_ref (match_operand 0 "" ""))]
4605
  "flag_pic"
4606
  "
4607
{
4608
  /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4609
     register.  */
4610
  if (arm_pic_register != INVALID_REGNUM)
4611
    arm_load_pic_register (1UL << 3);
4612
  DONE;
4613
}")
4614
 
4615
;; If copying one reg to another we can set the condition codes according to
4616
;; its value.  Such a move is common after a return from subroutine and the
4617
;; result is being tested against zero.
4618
 
4619
(define_insn "*movsi_compare0"
4620
  [(set (reg:CC CC_REGNUM)
4621
        (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4622
                    (const_int 0)))
4623
   (set (match_operand:SI 0 "s_register_operand" "=r,r")
4624
        (match_dup 1))]
4625
  "TARGET_ARM"
4626
  "@
4627
   cmp%?\\t%0, #0
4628
   sub%?s\\t%0, %1, #0"
4629
  [(set_attr "conds" "set")]
4630
)
4631
 
4632
;; Subroutine to store a half word from a register into memory.
4633
;; Operand 0 is the source register (HImode)
4634
;; Operand 1 is the destination address in a register (SImode)
4635
 
4636
;; In both this routine and the next, we must be careful not to spill
4637
;; a memory address of reg+large_const into a separate PLUS insn, since this
4638
;; can generate unrecognizable rtl.
4639
 
4640
(define_expand "storehi"
4641
  [;; store the low byte
4642
   (set (match_operand 1 "" "") (match_dup 3))
4643
   ;; extract the high byte
4644
   (set (match_dup 2)
4645
        (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4646
   ;; store the high byte
4647
   (set (match_dup 4) (match_dup 5))]
4648
  "TARGET_ARM"
4649
  "
4650
  {
4651
    rtx op1 = operands[1];
4652
    rtx addr = XEXP (op1, 0);
4653
    enum rtx_code code = GET_CODE (addr);
4654
 
4655
    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4656
        || code == MINUS)
4657
      op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4658
 
4659
    operands[4] = adjust_address (op1, QImode, 1);
4660
    operands[1] = adjust_address (operands[1], QImode, 0);
4661
    operands[3] = gen_lowpart (QImode, operands[0]);
4662
    operands[0] = gen_lowpart (SImode, operands[0]);
4663
    operands[2] = gen_reg_rtx (SImode);
4664
    operands[5] = gen_lowpart (QImode, operands[2]);
4665
  }"
4666
)
4667
 
4668
(define_expand "storehi_bigend"
4669
  [(set (match_dup 4) (match_dup 3))
4670
   (set (match_dup 2)
4671
        (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4672
   (set (match_operand 1 "" "") (match_dup 5))]
4673
  "TARGET_ARM"
4674
  "
4675
  {
4676
    rtx op1 = operands[1];
4677
    rtx addr = XEXP (op1, 0);
4678
    enum rtx_code code = GET_CODE (addr);
4679
 
4680
    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4681
        || code == MINUS)
4682
      op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4683
 
4684
    operands[4] = adjust_address (op1, QImode, 1);
4685
    operands[1] = adjust_address (operands[1], QImode, 0);
4686
    operands[3] = gen_lowpart (QImode, operands[0]);
4687
    operands[0] = gen_lowpart (SImode, operands[0]);
4688
    operands[2] = gen_reg_rtx (SImode);
4689
    operands[5] = gen_lowpart (QImode, operands[2]);
4690
  }"
4691
)
4692
 
4693
;; Subroutine to store a half word integer constant into memory.
4694
(define_expand "storeinthi"
4695
  [(set (match_operand 0 "" "")
4696
        (match_operand 1 "" ""))
4697
   (set (match_dup 3) (match_dup 2))]
4698
  "TARGET_ARM"
4699
  "
4700
  {
4701
    HOST_WIDE_INT value = INTVAL (operands[1]);
4702
    rtx addr = XEXP (operands[0], 0);
4703
    rtx op0 = operands[0];
4704
    enum rtx_code code = GET_CODE (addr);
4705
 
4706
    if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4707
        || code == MINUS)
4708
      op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4709
 
4710
    operands[1] = gen_reg_rtx (SImode);
4711
    if (BYTES_BIG_ENDIAN)
4712
      {
4713
        emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4714
        if ((value & 255) == ((value >> 8) & 255))
4715
          operands[2] = operands[1];
4716
        else
4717
          {
4718
            operands[2] = gen_reg_rtx (SImode);
4719
            emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4720
          }
4721
      }
4722
    else
4723
      {
4724
        emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4725
        if ((value & 255) == ((value >> 8) & 255))
4726
          operands[2] = operands[1];
4727
        else
4728
          {
4729
            operands[2] = gen_reg_rtx (SImode);
4730
            emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4731
          }
4732
      }
4733
 
4734
    operands[3] = adjust_address (op0, QImode, 1);
4735
    operands[0] = adjust_address (operands[0], QImode, 0);
4736
    operands[2] = gen_lowpart (QImode, operands[2]);
4737
    operands[1] = gen_lowpart (QImode, operands[1]);
4738
  }"
4739
)
4740
 
4741
(define_expand "storehi_single_op"
4742
  [(set (match_operand:HI 0 "memory_operand" "")
4743
        (match_operand:HI 1 "general_operand" ""))]
4744
  "TARGET_ARM && arm_arch4"
4745
  "
4746
  if (!s_register_operand (operands[1], HImode))
4747
    operands[1] = copy_to_mode_reg (HImode, operands[1]);
4748
  "
4749
)
4750
 
4751
(define_expand "movhi"
4752
  [(set (match_operand:HI 0 "general_operand" "")
4753
        (match_operand:HI 1 "general_operand" ""))]
4754
  "TARGET_EITHER"
4755
  "
4756
  if (TARGET_ARM)
4757
    {
4758
      if (!no_new_pseudos)
4759
        {
4760
          if (GET_CODE (operands[0]) == MEM)
4761
            {
4762
              if (arm_arch4)
4763
                {
4764
                  emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4765
                  DONE;
4766
                }
4767
              if (GET_CODE (operands[1]) == CONST_INT)
4768
                emit_insn (gen_storeinthi (operands[0], operands[1]));
4769
              else
4770
                {
4771
                  if (GET_CODE (operands[1]) == MEM)
4772
                    operands[1] = force_reg (HImode, operands[1]);
4773
                  if (BYTES_BIG_ENDIAN)
4774
                    emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4775
                  else
4776
                   emit_insn (gen_storehi (operands[1], operands[0]));
4777
                }
4778
              DONE;
4779
            }
4780
          /* Sign extend a constant, and keep it in an SImode reg.  */
4781
          else if (GET_CODE (operands[1]) == CONST_INT)
4782
            {
4783
              rtx reg = gen_reg_rtx (SImode);
4784
              HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4785
 
4786
              /* If the constant is already valid, leave it alone.  */
4787
              if (!const_ok_for_arm (val))
4788
                {
4789
                  /* If setting all the top bits will make the constant
4790
                     loadable in a single instruction, then set them.
4791
                     Otherwise, sign extend the number.  */
4792
 
4793
                  if (const_ok_for_arm (~(val | ~0xffff)))
4794
                    val |= ~0xffff;
4795
                  else if (val & 0x8000)
4796
                    val |= ~0xffff;
4797
                }
4798
 
4799
              emit_insn (gen_movsi (reg, GEN_INT (val)));
4800
              operands[1] = gen_lowpart (HImode, reg);
4801
            }
4802
          else if (arm_arch4 && optimize && !no_new_pseudos
4803
                   && GET_CODE (operands[1]) == MEM)
4804
            {
4805
              rtx reg = gen_reg_rtx (SImode);
4806
 
4807
              emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4808
              operands[1] = gen_lowpart (HImode, reg);
4809
            }
4810
          else if (!arm_arch4)
4811
            {
4812
              if (GET_CODE (operands[1]) == MEM)
4813
                {
4814
                  rtx base;
4815
                  rtx offset = const0_rtx;
4816
                  rtx reg = gen_reg_rtx (SImode);
4817
 
4818
                  if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4819
                       || (GET_CODE (base) == PLUS
4820
                           && (GET_CODE (offset = XEXP (base, 1))
4821
                               == CONST_INT)
4822
                           && ((INTVAL(offset) & 1) != 1)
4823
                           && GET_CODE (base = XEXP (base, 0)) == REG))
4824
                      && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4825
                    {
4826
                      rtx new;
4827
 
4828
                      new = widen_memory_access (operands[1], SImode,
4829
                                                 ((INTVAL (offset) & ~3)
4830
                                                  - INTVAL (offset)));
4831
                      emit_insn (gen_movsi (reg, new));
4832
                      if (((INTVAL (offset) & 2) != 0)
4833
                          ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4834
                        {
4835
                          rtx reg2 = gen_reg_rtx (SImode);
4836
 
4837
                          emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4838
                          reg = reg2;
4839
                        }
4840
                    }
4841
                  else
4842
                    emit_insn (gen_movhi_bytes (reg, operands[1]));
4843
 
4844
                  operands[1] = gen_lowpart (HImode, reg);
4845
               }
4846
           }
4847
        }
4848
      /* Handle loading a large integer during reload.  */
4849
      else if (GET_CODE (operands[1]) == CONST_INT
4850
               && !const_ok_for_arm (INTVAL (operands[1]))
4851
               && !const_ok_for_arm (~INTVAL (operands[1])))
4852
        {
4853
          /* Writing a constant to memory needs a scratch, which should
4854
             be handled with SECONDARY_RELOADs.  */
4855
          gcc_assert (GET_CODE (operands[0]) == REG);
4856
 
4857
          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4858
          emit_insn (gen_movsi (operands[0], operands[1]));
4859
          DONE;
4860
       }
4861
    }
4862
  else /* TARGET_THUMB */
4863
    {
4864
      if (!no_new_pseudos)
4865
        {
4866
          if (GET_CODE (operands[1]) == CONST_INT)
4867
            {
4868
              rtx reg = gen_reg_rtx (SImode);
4869
 
4870
              emit_insn (gen_movsi (reg, operands[1]));
4871
              operands[1] = gen_lowpart (HImode, reg);
4872
            }
4873
 
4874
          /* ??? We shouldn't really get invalid addresses here, but this can
4875
             happen if we are passed a SP (never OK for HImode/QImode) or
4876
             virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4877
             HImode/QImode) relative address.  */
4878
          /* ??? This should perhaps be fixed elsewhere, for instance, in
4879
             fixup_stack_1, by checking for other kinds of invalid addresses,
4880
             e.g. a bare reference to a virtual register.  This may confuse the
4881
             alpha though, which must handle this case differently.  */
4882
          if (GET_CODE (operands[0]) == MEM
4883
              && !memory_address_p (GET_MODE (operands[0]),
4884
                                    XEXP (operands[0], 0)))
4885
            operands[0]
4886
              = replace_equiv_address (operands[0],
4887
                                       copy_to_reg (XEXP (operands[0], 0)));
4888
 
4889
          if (GET_CODE (operands[1]) == MEM
4890
              && !memory_address_p (GET_MODE (operands[1]),
4891
                                    XEXP (operands[1], 0)))
4892
            operands[1]
4893
              = replace_equiv_address (operands[1],
4894
                                       copy_to_reg (XEXP (operands[1], 0)));
4895
 
4896
          if (GET_CODE (operands[1]) == MEM && optimize > 0)
4897
            {
4898
              rtx reg = gen_reg_rtx (SImode);
4899
 
4900
              emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4901
              operands[1] = gen_lowpart (HImode, reg);
4902
            }
4903
 
4904
          if (GET_CODE (operands[0]) == MEM)
4905
            operands[1] = force_reg (HImode, operands[1]);
4906
        }
4907
      else if (GET_CODE (operands[1]) == CONST_INT
4908
                && !satisfies_constraint_I (operands[1]))
4909
        {
4910
          /* Handle loading a large integer during reload.  */
4911
 
4912
          /* Writing a constant to memory needs a scratch, which should
4913
             be handled with SECONDARY_RELOADs.  */
4914
          gcc_assert (GET_CODE (operands[0]) == REG);
4915
 
4916
          operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4917
          emit_insn (gen_movsi (operands[0], operands[1]));
4918
          DONE;
4919
        }
4920
    }
4921
  "
4922
)
4923
 
4924
(define_insn "*thumb_movhi_insn"
4925
  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4926
        (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4927
  "TARGET_THUMB
4928
   && (   register_operand (operands[0], HImode)
4929
       || register_operand (operands[1], HImode))"
4930
  "*
4931
  switch (which_alternative)
4932
    {
4933
    case 0: return \"add        %0, %1, #0\";
4934
    case 2: return \"strh       %1, %0\";
4935
    case 3: return \"mov        %0, %1\";
4936
    case 4: return \"mov        %0, %1\";
4937
    case 5: return \"mov        %0, %1\";
4938
    default: gcc_unreachable ();
4939
    case 1:
4940
      /* The stack pointer can end up being taken as an index register.
4941
          Catch this case here and deal with it.  */
4942
      if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4943
          && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4944
          && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4945
        {
4946
          rtx ops[2];
4947
          ops[0] = operands[0];
4948
          ops[1] = XEXP (XEXP (operands[1], 0), 0);
4949
 
4950
          output_asm_insn (\"mov        %0, %1\", ops);
4951
 
4952
          XEXP (XEXP (operands[1], 0), 0) = operands[0];
4953
 
4954
        }
4955
      return \"ldrh     %0, %1\";
4956
    }"
4957
  [(set_attr "length" "2,4,2,2,2,2")
4958
   (set_attr "type" "*,load1,store1,*,*,*")]
4959
)
4960
 
4961
 
4962
(define_expand "movhi_bytes"
4963
  [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4964
   (set (match_dup 3)
4965
        (zero_extend:SI (match_dup 6)))
4966
   (set (match_operand:SI 0 "" "")
4967
         (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4968
  "TARGET_ARM"
4969
  "
4970
  {
4971
    rtx mem1, mem2;
4972
    rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4973
 
4974
    mem1 = change_address (operands[1], QImode, addr);
4975
    mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4976
    operands[0] = gen_lowpart (SImode, operands[0]);
4977
    operands[1] = mem1;
4978
    operands[2] = gen_reg_rtx (SImode);
4979
    operands[3] = gen_reg_rtx (SImode);
4980
    operands[6] = mem2;
4981
 
4982
    if (BYTES_BIG_ENDIAN)
4983
      {
4984
        operands[4] = operands[2];
4985
        operands[5] = operands[3];
4986
      }
4987
    else
4988
      {
4989
        operands[4] = operands[3];
4990
        operands[5] = operands[2];
4991
      }
4992
  }"
4993
)
4994
 
4995
(define_expand "movhi_bigend"
4996
  [(set (match_dup 2)
4997
        (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4998
                   (const_int 16)))
4999
   (set (match_dup 3)
5000
        (ashiftrt:SI (match_dup 2) (const_int 16)))
5001
   (set (match_operand:HI 0 "s_register_operand" "")
5002
        (match_dup 4))]
5003
  "TARGET_ARM"
5004
  "
5005
  operands[2] = gen_reg_rtx (SImode);
5006
  operands[3] = gen_reg_rtx (SImode);
5007
  operands[4] = gen_lowpart (HImode, operands[3]);
5008
  "
5009
)
5010
 
5011
;; Pattern to recognize insn generated default case above
5012
(define_insn "*movhi_insn_arch4"
5013
  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
5014
        (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5015
  "TARGET_ARM
5016
   && arm_arch4
5017
   && (GET_CODE (operands[1]) != CONST_INT
5018
       || const_ok_for_arm (INTVAL (operands[1]))
5019
       || const_ok_for_arm (~INTVAL (operands[1])))"
5020
  "@
5021
   mov%?\\t%0, %1\\t%@ movhi
5022
   mvn%?\\t%0, #%B1\\t%@ movhi
5023
   str%?h\\t%1, %0\\t%@ movhi
5024
   ldr%?h\\t%0, %1\\t%@ movhi"
5025
  [(set_attr "type" "*,*,store1,load1")
5026
   (set_attr "predicable" "yes")
5027
   (set_attr "pool_range" "*,*,*,256")
5028
   (set_attr "neg_pool_range" "*,*,*,244")]
5029
)
5030
 
5031
(define_insn "*movhi_bytes"
5032
  [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5033
        (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5034
  "TARGET_ARM"
5035
  "@
5036
   mov%?\\t%0, %1\\t%@ movhi
5037
   mvn%?\\t%0, #%B1\\t%@ movhi"
5038
  [(set_attr "predicable" "yes")]
5039
)
5040
 
5041
(define_expand "thumb_movhi_clobber"
5042
  [(set (match_operand:HI     0 "memory_operand"   "")
5043
        (match_operand:HI     1 "register_operand" ""))
5044
   (clobber (match_operand:DI 2 "register_operand" ""))]
5045
  "TARGET_THUMB"
5046
  "
5047
  if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5048
      && REGNO (operands[1]) <= LAST_LO_REGNUM)
5049
    {
5050
      emit_insn (gen_movhi (operands[0], operands[1]));
5051
      DONE;
5052
    }
5053
  /* XXX Fixme, need to handle other cases here as well.  */
5054
  gcc_unreachable ();
5055
  "
5056
)
5057
 
5058
;; We use a DImode scratch because we may occasionally need an additional
5059
;; temporary if the address isn't offsettable -- push_reload doesn't seem
5060
;; to take any notice of the "o" constraints on reload_memory_operand operand.
5061
(define_expand "reload_outhi"
5062
  [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5063
              (match_operand:HI 1 "s_register_operand"        "r")
5064
              (match_operand:DI 2 "s_register_operand"        "=&l")])]
5065
  "TARGET_EITHER"
5066
  "if (TARGET_ARM)
5067
     arm_reload_out_hi (operands);
5068
   else
5069
     thumb_reload_out_hi (operands);
5070
  DONE;
5071
  "
5072
)
5073
 
5074
(define_expand "reload_inhi"
5075
  [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5076
              (match_operand:HI 1 "arm_reload_memory_operand" "o")
5077
              (match_operand:DI 2 "s_register_operand" "=&r")])]
5078
  "TARGET_EITHER"
5079
  "
5080
  if (TARGET_ARM)
5081
    arm_reload_in_hi (operands);
5082
  else
5083
    thumb_reload_out_hi (operands);
5084
  DONE;
5085
")
5086
 
5087
(define_expand "movqi"
5088
  [(set (match_operand:QI 0 "general_operand" "")
5089
        (match_operand:QI 1 "general_operand" ""))]
5090
  "TARGET_EITHER"
5091
  "
5092
  /* Everything except mem = const or mem = mem can be done easily */
5093
 
5094
  if (!no_new_pseudos)
5095
    {
5096
      if (GET_CODE (operands[1]) == CONST_INT)
5097
        {
5098
          rtx reg = gen_reg_rtx (SImode);
5099
 
5100
          emit_insn (gen_movsi (reg, operands[1]));
5101
          operands[1] = gen_lowpart (QImode, reg);
5102
        }
5103
 
5104
      if (TARGET_THUMB)
5105
        {
5106
          /* ??? We shouldn't really get invalid addresses here, but this can
5107
             happen if we are passed a SP (never OK for HImode/QImode) or
5108
             virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5109
             HImode/QImode) relative address.  */
5110
          /* ??? This should perhaps be fixed elsewhere, for instance, in
5111
             fixup_stack_1, by checking for other kinds of invalid addresses,
5112
             e.g. a bare reference to a virtual register.  This may confuse the
5113
             alpha though, which must handle this case differently.  */
5114
          if (GET_CODE (operands[0]) == MEM
5115
              && !memory_address_p (GET_MODE (operands[0]),
5116
                                     XEXP (operands[0], 0)))
5117
            operands[0]
5118
              = replace_equiv_address (operands[0],
5119
                                       copy_to_reg (XEXP (operands[0], 0)));
5120
          if (GET_CODE (operands[1]) == MEM
5121
              && !memory_address_p (GET_MODE (operands[1]),
5122
                                    XEXP (operands[1], 0)))
5123
             operands[1]
5124
               = replace_equiv_address (operands[1],
5125
                                        copy_to_reg (XEXP (operands[1], 0)));
5126
        }
5127
 
5128
      if (GET_CODE (operands[1]) == MEM && optimize > 0)
5129
        {
5130
          rtx reg = gen_reg_rtx (SImode);
5131
 
5132
          emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5133
          operands[1] = gen_lowpart (QImode, reg);
5134
        }
5135
 
5136
      if (GET_CODE (operands[0]) == MEM)
5137
        operands[1] = force_reg (QImode, operands[1]);
5138
    }
5139
  else if (TARGET_THUMB
5140
           && GET_CODE (operands[1]) == CONST_INT
5141
           && !satisfies_constraint_I (operands[1]))
5142
    {
5143
      /* Handle loading a large integer during reload.  */
5144
 
5145
      /* Writing a constant to memory needs a scratch, which should
5146
         be handled with SECONDARY_RELOADs.  */
5147
      gcc_assert (GET_CODE (operands[0]) == REG);
5148
 
5149
      operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5150
      emit_insn (gen_movsi (operands[0], operands[1]));
5151
      DONE;
5152
    }
5153
  "
5154
)
5155
 
5156
 
5157
(define_insn "*arm_movqi_insn"
5158
  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5159
        (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5160
  "TARGET_ARM
5161
   && (   register_operand (operands[0], QImode)
5162
       || register_operand (operands[1], QImode))"
5163
  "@
5164
   mov%?\\t%0, %1
5165
   mvn%?\\t%0, #%B1
5166
   ldr%?b\\t%0, %1
5167
   str%?b\\t%1, %0"
5168
  [(set_attr "type" "*,*,load1,store1")
5169
   (set_attr "predicable" "yes")]
5170
)
5171
 
5172
(define_insn "*thumb_movqi_insn"
5173
  [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5174
        (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5175
  "TARGET_THUMB
5176
   && (   register_operand (operands[0], QImode)
5177
       || register_operand (operands[1], QImode))"
5178
  "@
5179
   add\\t%0, %1, #0
5180
   ldrb\\t%0, %1
5181
   strb\\t%1, %0
5182
   mov\\t%0, %1
5183
   mov\\t%0, %1
5184
   mov\\t%0, %1"
5185
  [(set_attr "length" "2")
5186
   (set_attr "type" "*,load1,store1,*,*,*")
5187
   (set_attr "pool_range" "*,32,*,*,*,*")]
5188
)
5189
 
5190
(define_expand "movsf"
5191
  [(set (match_operand:SF 0 "general_operand" "")
5192
        (match_operand:SF 1 "general_operand" ""))]
5193
  "TARGET_EITHER"
5194
  "
5195
  if (TARGET_ARM)
5196
    {
5197
      if (GET_CODE (operands[0]) == MEM)
5198
        operands[1] = force_reg (SFmode, operands[1]);
5199
    }
5200
  else /* TARGET_THUMB */
5201
    {
5202
      if (!no_new_pseudos)
5203
        {
5204
           if (GET_CODE (operands[0]) != REG)
5205
             operands[1] = force_reg (SFmode, operands[1]);
5206
        }
5207
    }
5208
  "
5209
)
5210
 
5211
;; Transform a floating-point move of a constant into a core register into
5212
;; an SImode operation.
5213
(define_split
5214
  [(set (match_operand:SF 0 "arm_general_register_operand" "")
5215
        (match_operand:SF 1 "immediate_operand" ""))]
5216
  "TARGET_ARM
5217
   && reload_completed
5218
   && GET_CODE (operands[1]) == CONST_DOUBLE"
5219
  [(set (match_dup 2) (match_dup 3))]
5220
  "
5221
  operands[2] = gen_lowpart (SImode, operands[0]);
5222
  operands[3] = gen_lowpart (SImode, operands[1]);
5223
  if (operands[2] == 0 || operands[3] == 0)
5224
    FAIL;
5225
  "
5226
)
5227
 
5228
(define_insn "*arm_movsf_soft_insn"
5229
  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5230
        (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5231
  "TARGET_ARM
5232
   && TARGET_SOFT_FLOAT
5233
   && (GET_CODE (operands[0]) != MEM
5234
       || register_operand (operands[1], SFmode))"
5235
  "@
5236
   mov%?\\t%0, %1
5237
   ldr%?\\t%0, %1\\t%@ float
5238
   str%?\\t%1, %0\\t%@ float"
5239
  [(set_attr "length" "4,4,4")
5240
   (set_attr "predicable" "yes")
5241
   (set_attr "type" "*,load1,store1")
5242
   (set_attr "pool_range" "*,4096,*")
5243
   (set_attr "neg_pool_range" "*,4084,*")]
5244
)
5245
 
5246
;;; ??? This should have alternatives for constants.
5247
(define_insn "*thumb_movsf_insn"
5248
  [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5249
        (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5250
  "TARGET_THUMB
5251
   && (   register_operand (operands[0], SFmode)
5252
       || register_operand (operands[1], SFmode))"
5253
  "@
5254
   add\\t%0, %1, #0
5255
   ldmia\\t%1, {%0}
5256
   stmia\\t%0, {%1}
5257
   ldr\\t%0, %1
5258
   str\\t%1, %0
5259
   mov\\t%0, %1
5260
   mov\\t%0, %1"
5261
  [(set_attr "length" "2")
5262
   (set_attr "type" "*,load1,store1,load1,store1,*,*")
5263
   (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5264
)
5265
 
5266
(define_expand "movdf"
5267
  [(set (match_operand:DF 0 "general_operand" "")
5268
        (match_operand:DF 1 "general_operand" ""))]
5269
  "TARGET_EITHER"
5270
  "
5271
  if (TARGET_ARM)
5272
    {
5273
      if (GET_CODE (operands[0]) == MEM)
5274
        operands[1] = force_reg (DFmode, operands[1]);
5275
    }
5276
  else /* TARGET_THUMB */
5277
    {
5278
      if (!no_new_pseudos)
5279
        {
5280
          if (GET_CODE (operands[0]) != REG)
5281
            operands[1] = force_reg (DFmode, operands[1]);
5282
        }
5283
    }
5284
  "
5285
)
5286
 
5287
;; Reloading a df mode value stored in integer regs to memory can require a
5288
;; scratch reg.
5289
(define_expand "reload_outdf"
5290
  [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5291
   (match_operand:DF 1 "s_register_operand" "r")
5292
   (match_operand:SI 2 "s_register_operand" "=&r")]
5293
  "TARGET_ARM"
5294
  "
5295
  {
5296
    enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5297
 
5298
    if (code == REG)
5299
      operands[2] = XEXP (operands[0], 0);
5300
    else if (code == POST_INC || code == PRE_DEC)
5301
      {
5302
        operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5303
        operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5304
        emit_insn (gen_movdi (operands[0], operands[1]));
5305
        DONE;
5306
      }
5307
    else if (code == PRE_INC)
5308
      {
5309
        rtx reg = XEXP (XEXP (operands[0], 0), 0);
5310
 
5311
        emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5312
        operands[2] = reg;
5313
      }
5314
    else if (code == POST_DEC)
5315
      operands[2] = XEXP (XEXP (operands[0], 0), 0);
5316
    else
5317
      emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5318
                             XEXP (XEXP (operands[0], 0), 1)));
5319
 
5320
    emit_insn (gen_rtx_SET (VOIDmode,
5321
                            replace_equiv_address (operands[0], operands[2]),
5322
                            operands[1]));
5323
 
5324
    if (code == POST_DEC)
5325
      emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5326
 
5327
    DONE;
5328
  }"
5329
)
5330
 
5331
(define_insn "*movdf_soft_insn"
5332
  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5333
        (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5334
  "TARGET_ARM && TARGET_SOFT_FLOAT
5335
   && (   register_operand (operands[0], DFmode)
5336
       || register_operand (operands[1], DFmode))"
5337
  "*
5338
  switch (which_alternative)
5339
    {
5340
    case 0:
5341
    case 1:
5342
    case 2:
5343
      return \"#\";
5344
    default:
5345
      return output_move_double (operands);
5346
    }
5347
  "
5348
  [(set_attr "length" "8,12,16,8,8")
5349
   (set_attr "type" "*,*,*,load2,store2")
5350
   (set_attr "pool_range" "1020")
5351
   (set_attr "neg_pool_range" "1008")]
5352
)
5353
 
5354
;;; ??? This should have alternatives for constants.
5355
;;; ??? This was originally identical to the movdi_insn pattern.
5356
;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5357
;;; thumb_reorg with a memory reference.
5358
(define_insn "*thumb_movdf_insn"
5359
  [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5360
        (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5361
  "TARGET_THUMB
5362
   && (   register_operand (operands[0], DFmode)
5363
       || register_operand (operands[1], DFmode))"
5364
  "*
5365
  switch (which_alternative)
5366
    {
5367
    default:
5368
    case 0:
5369
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5370
        return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5371
      return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5372
    case 1:
5373
      return \"ldmia\\t%1, {%0, %H0}\";
5374
    case 2:
5375
      return \"stmia\\t%0, {%1, %H1}\";
5376
    case 3:
5377
      return thumb_load_double_from_address (operands);
5378
    case 4:
5379
      operands[2] = gen_rtx_MEM (SImode,
5380
                                 plus_constant (XEXP (operands[0], 0), 4));
5381
      output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5382
      return \"\";
5383
    case 5:
5384
      if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5385
        return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5386
      return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5387
    }
5388
  "
5389
  [(set_attr "length" "4,2,2,6,4,4")
5390
   (set_attr "type" "*,load2,store2,load2,store2,*")
5391
   (set_attr "pool_range" "*,*,*,1020,*,*")]
5392
)
5393
 
5394
(define_expand "movxf"
5395
  [(set (match_operand:XF 0 "general_operand" "")
5396
        (match_operand:XF 1 "general_operand" ""))]
5397
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5398
  "
5399
  if (GET_CODE (operands[0]) == MEM)
5400
    operands[1] = force_reg (XFmode, operands[1]);
5401
  "
5402
)
5403
 
5404
;; Vector Moves
5405
(define_expand "movv2si"
5406
  [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5407
        (match_operand:V2SI 1 "general_operand" ""))]
5408
  "TARGET_REALLY_IWMMXT"
5409
{
5410
})
5411
 
5412
(define_expand "movv4hi"
5413
  [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5414
        (match_operand:V4HI 1 "general_operand" ""))]
5415
  "TARGET_REALLY_IWMMXT"
5416
{
5417
})
5418
 
5419
(define_expand "movv8qi"
5420
  [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5421
        (match_operand:V8QI 1 "general_operand" ""))]
5422
  "TARGET_REALLY_IWMMXT"
5423
{
5424
})
5425
 
5426
 
5427
;; load- and store-multiple insns
5428
;; The arm can load/store any set of registers, provided that they are in
5429
;; ascending order; but that is beyond GCC so stick with what it knows.
5430
 
5431
(define_expand "load_multiple"
5432
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5433
                          (match_operand:SI 1 "" ""))
5434
                     (use (match_operand:SI 2 "" ""))])]
5435
  "TARGET_ARM"
5436
{
5437
  HOST_WIDE_INT offset = 0;
5438
 
5439
  /* Support only fixed point registers.  */
5440
  if (GET_CODE (operands[2]) != CONST_INT
5441
      || INTVAL (operands[2]) > 14
5442
      || INTVAL (operands[2]) < 2
5443
      || GET_CODE (operands[1]) != MEM
5444
      || GET_CODE (operands[0]) != REG
5445
      || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5446
      || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5447
    FAIL;
5448
 
5449
  operands[3]
5450
    = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5451
                             force_reg (SImode, XEXP (operands[1], 0)),
5452
                             TRUE, FALSE, operands[1], &offset);
5453
})
5454
 
5455
;; Load multiple with write-back
5456
 
5457
(define_insn "*ldmsi_postinc4"
5458
  [(match_parallel 0 "load_multiple_operation"
5459
    [(set (match_operand:SI 1 "s_register_operand" "=r")
5460
          (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5461
                   (const_int 16)))
5462
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5463
          (mem:SI (match_dup 2)))
5464
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5465
          (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5466
     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5467
          (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5468
     (set (match_operand:SI 6 "arm_hard_register_operand" "")
5469
          (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5470
  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5471
  "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5472
  [(set_attr "type" "load4")
5473
   (set_attr "predicable" "yes")]
5474
)
5475
 
5476
(define_insn "*ldmsi_postinc4_thumb"
5477
  [(match_parallel 0 "load_multiple_operation"
5478
    [(set (match_operand:SI 1 "s_register_operand" "=l")
5479
          (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5480
                   (const_int 16)))
5481
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5482
          (mem:SI (match_dup 2)))
5483
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5484
          (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5485
     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5486
          (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5487
     (set (match_operand:SI 6 "arm_hard_register_operand" "")
5488
          (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5489
  "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5490
  "ldmia\\t%1!, {%3, %4, %5, %6}"
5491
  [(set_attr "type" "load4")]
5492
)
5493
 
5494
(define_insn "*ldmsi_postinc3"
5495
  [(match_parallel 0 "load_multiple_operation"
5496
    [(set (match_operand:SI 1 "s_register_operand" "=r")
5497
          (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5498
                   (const_int 12)))
5499
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5500
          (mem:SI (match_dup 2)))
5501
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5502
          (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5503
     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5504
          (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5505
  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5506
  "ldm%?ia\\t%1!, {%3, %4, %5}"
5507
  [(set_attr "type" "load3")
5508
   (set_attr "predicable" "yes")]
5509
)
5510
 
5511
(define_insn "*ldmsi_postinc2"
5512
  [(match_parallel 0 "load_multiple_operation"
5513
    [(set (match_operand:SI 1 "s_register_operand" "=r")
5514
          (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5515
                   (const_int 8)))
5516
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5517
          (mem:SI (match_dup 2)))
5518
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5519
          (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5520
  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5521
  "ldm%?ia\\t%1!, {%3, %4}"
5522
  [(set_attr "type" "load2")
5523
   (set_attr "predicable" "yes")]
5524
)
5525
 
5526
;; Ordinary load multiple
5527
 
5528
(define_insn "*ldmsi4"
5529
  [(match_parallel 0 "load_multiple_operation"
5530
    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5531
          (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5532
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5533
          (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5534
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5535
          (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5536
     (set (match_operand:SI 5 "arm_hard_register_operand" "")
5537
          (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5538
  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5539
  "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5540
  [(set_attr "type" "load4")
5541
   (set_attr "predicable" "yes")]
5542
)
5543
 
5544
(define_insn "*ldmsi3"
5545
  [(match_parallel 0 "load_multiple_operation"
5546
    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5547
          (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5548
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5549
          (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5550
     (set (match_operand:SI 4 "arm_hard_register_operand" "")
5551
          (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5552
  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5553
  "ldm%?ia\\t%1, {%2, %3, %4}"
5554
  [(set_attr "type" "load3")
5555
   (set_attr "predicable" "yes")]
5556
)
5557
 
5558
(define_insn "*ldmsi2"
5559
  [(match_parallel 0 "load_multiple_operation"
5560
    [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5561
          (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5562
     (set (match_operand:SI 3 "arm_hard_register_operand" "")
5563
          (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5564
  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5565
  "ldm%?ia\\t%1, {%2, %3}"
5566
  [(set_attr "type" "load2")
5567
   (set_attr "predicable" "yes")]
5568
)
5569
 
5570
(define_expand "store_multiple"
5571
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5572
                          (match_operand:SI 1 "" ""))
5573
                     (use (match_operand:SI 2 "" ""))])]
5574
  "TARGET_ARM"
5575
{
5576
  HOST_WIDE_INT offset = 0;
5577
 
5578
  /* Support only fixed point registers.  */
5579
  if (GET_CODE (operands[2]) != CONST_INT
5580
      || INTVAL (operands[2]) > 14
5581
      || INTVAL (operands[2]) < 2
5582
      || GET_CODE (operands[1]) != REG
5583
      || GET_CODE (operands[0]) != MEM
5584
      || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5585
      || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5586
    FAIL;
5587
 
5588
  operands[3]
5589
    = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5590
                              force_reg (SImode, XEXP (operands[0], 0)),
5591
                              TRUE, FALSE, operands[0], &offset);
5592
})
5593
 
5594
;; Store multiple with write-back
5595
 
5596
(define_insn "*stmsi_postinc4"
5597
  [(match_parallel 0 "store_multiple_operation"
5598
    [(set (match_operand:SI 1 "s_register_operand" "=r")
5599
          (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5600
                   (const_int 16)))
5601
     (set (mem:SI (match_dup 2))
5602
          (match_operand:SI 3 "arm_hard_register_operand" ""))
5603
     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5604
          (match_operand:SI 4 "arm_hard_register_operand" ""))
5605
     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5606
          (match_operand:SI 5 "arm_hard_register_operand" ""))
5607
     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5608
          (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5609
  "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5610
  "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5611
  [(set_attr "predicable" "yes")
5612
   (set_attr "type" "store4")]
5613
)
5614
 
5615
(define_insn "*stmsi_postinc4_thumb"
5616
  [(match_parallel 0 "store_multiple_operation"
5617
    [(set (match_operand:SI 1 "s_register_operand" "=l")
5618
          (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5619
                   (const_int 16)))
5620
     (set (mem:SI (match_dup 2))
5621
          (match_operand:SI 3 "arm_hard_register_operand" ""))
5622
     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5623
          (match_operand:SI 4 "arm_hard_register_operand" ""))
5624
     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5625
          (match_operand:SI 5 "arm_hard_register_operand" ""))
5626
     (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5627
          (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5628
  "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5629
  "stmia\\t%1!, {%3, %4, %5, %6}"
5630
  [(set_attr "type" "store4")]
5631
)
5632
 
5633
(define_insn "*stmsi_postinc3"
5634
  [(match_parallel 0 "store_multiple_operation"
5635
    [(set (match_operand:SI 1 "s_register_operand" "=r")
5636
          (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5637
                   (const_int 12)))
5638
     (set (mem:SI (match_dup 2))
5639
          (match_operand:SI 3 "arm_hard_register_operand" ""))
5640
     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5641
          (match_operand:SI 4 "arm_hard_register_operand" ""))
5642
     (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5643
          (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5644
  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5645
  "stm%?ia\\t%1!, {%3, %4, %5}"
5646
  [(set_attr "predicable" "yes")
5647
   (set_attr "type" "store3")]
5648
)
5649
 
5650
(define_insn "*stmsi_postinc2"
5651
  [(match_parallel 0 "store_multiple_operation"
5652
    [(set (match_operand:SI 1 "s_register_operand" "=r")
5653
          (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5654
                   (const_int 8)))
5655
     (set (mem:SI (match_dup 2))
5656
          (match_operand:SI 3 "arm_hard_register_operand" ""))
5657
     (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5658
          (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5659
  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5660
  "stm%?ia\\t%1!, {%3, %4}"
5661
  [(set_attr "predicable" "yes")
5662
   (set_attr "type" "store2")]
5663
)
5664
 
5665
;; Ordinary store multiple
5666
 
5667
(define_insn "*stmsi4"
5668
  [(match_parallel 0 "store_multiple_operation"
5669
    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5670
          (match_operand:SI 2 "arm_hard_register_operand" ""))
5671
     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5672
          (match_operand:SI 3 "arm_hard_register_operand" ""))
5673
     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5674
          (match_operand:SI 4 "arm_hard_register_operand" ""))
5675
     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5676
          (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5677
  "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5678
  "stm%?ia\\t%1, {%2, %3, %4, %5}"
5679
  [(set_attr "predicable" "yes")
5680
   (set_attr "type" "store4")]
5681
)
5682
 
5683
(define_insn "*stmsi3"
5684
  [(match_parallel 0 "store_multiple_operation"
5685
    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5686
          (match_operand:SI 2 "arm_hard_register_operand" ""))
5687
     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5688
          (match_operand:SI 3 "arm_hard_register_operand" ""))
5689
     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5690
          (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5691
  "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5692
  "stm%?ia\\t%1, {%2, %3, %4}"
5693
  [(set_attr "predicable" "yes")
5694
   (set_attr "type" "store3")]
5695
)
5696
 
5697
(define_insn "*stmsi2"
5698
  [(match_parallel 0 "store_multiple_operation"
5699
    [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5700
          (match_operand:SI 2 "arm_hard_register_operand" ""))
5701
     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5702
          (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5703
  "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5704
  "stm%?ia\\t%1, {%2, %3}"
5705
  [(set_attr "predicable" "yes")
5706
   (set_attr "type" "store2")]
5707
)
5708
 
5709
;; Move a block of memory if it is word aligned and MORE than 2 words long.
5710
;; We could let this apply for blocks of less than this, but it clobbers so
5711
;; many registers that there is then probably a better way.
5712
 
5713
(define_expand "movmemqi"
5714
  [(match_operand:BLK 0 "general_operand" "")
5715
   (match_operand:BLK 1 "general_operand" "")
5716
   (match_operand:SI 2 "const_int_operand" "")
5717
   (match_operand:SI 3 "const_int_operand" "")]
5718
  "TARGET_EITHER"
5719
  "
5720
  if (TARGET_ARM)
5721
    {
5722
      if (arm_gen_movmemqi (operands))
5723
        DONE;
5724
      FAIL;
5725
    }
5726
  else /* TARGET_THUMB */
5727
    {
5728
      if (   INTVAL (operands[3]) != 4
5729
          || INTVAL (operands[2]) > 48)
5730
        FAIL;
5731
 
5732
      thumb_expand_movmemqi (operands);
5733
      DONE;
5734
    }
5735
  "
5736
)
5737
 
5738
;; Thumb block-move insns
5739
 
5740
(define_insn "movmem12b"
5741
  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5742
        (mem:SI (match_operand:SI 3 "register_operand" "1")))
5743
   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5744
        (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5745
   (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5746
        (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5747
   (set (match_operand:SI 0 "register_operand" "=l")
5748
        (plus:SI (match_dup 2) (const_int 12)))
5749
   (set (match_operand:SI 1 "register_operand" "=l")
5750
        (plus:SI (match_dup 3) (const_int 12)))
5751
   (clobber (match_scratch:SI 4 "=&l"))
5752
   (clobber (match_scratch:SI 5 "=&l"))
5753
   (clobber (match_scratch:SI 6 "=&l"))]
5754
  "TARGET_THUMB"
5755
  "* return thumb_output_move_mem_multiple (3, operands);"
5756
  [(set_attr "length" "4")
5757
   ; This isn't entirely accurate...  It loads as well, but in terms of
5758
   ; scheduling the following insn it is better to consider it as a store
5759
   (set_attr "type" "store3")]
5760
)
5761
 
5762
(define_insn "movmem8b"
5763
  [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5764
        (mem:SI (match_operand:SI 3 "register_operand" "1")))
5765
   (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5766
        (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5767
   (set (match_operand:SI 0 "register_operand" "=l")
5768
        (plus:SI (match_dup 2) (const_int 8)))
5769
   (set (match_operand:SI 1 "register_operand" "=l")
5770
        (plus:SI (match_dup 3) (const_int 8)))
5771
   (clobber (match_scratch:SI 4 "=&l"))
5772
   (clobber (match_scratch:SI 5 "=&l"))]
5773
  "TARGET_THUMB"
5774
  "* return thumb_output_move_mem_multiple (2, operands);"
5775
  [(set_attr "length" "4")
5776
   ; This isn't entirely accurate...  It loads as well, but in terms of
5777
   ; scheduling the following insn it is better to consider it as a store
5778
   (set_attr "type" "store2")]
5779
)
5780
 
5781
 
5782
 
5783
;; Compare & branch insns
5784
;; The range calculations are based as follows:
5785
;; For forward branches, the address calculation returns the address of
5786
;; the next instruction.  This is 2 beyond the branch instruction.
5787
;; For backward branches, the address calculation returns the address of
5788
;; the first instruction in this pattern (cmp).  This is 2 before the branch
5789
;; instruction for the shortest sequence, and 4 before the branch instruction
5790
;; if we have to jump around an unconditional branch.
5791
;; To the basic branch range the PC offset must be added (this is +4).
5792
;; So for forward branches we have
5793
;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5794
;; And for backward branches we have
5795
;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5796
;;
5797
;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5798
;; For a 'b' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5799
 
5800
(define_expand "cbranchsi4"
5801
  [(set (pc) (if_then_else
5802
              (match_operator 0 "arm_comparison_operator"
5803
               [(match_operand:SI 1 "s_register_operand" "")
5804
                (match_operand:SI 2 "nonmemory_operand" "")])
5805
              (label_ref (match_operand 3 "" ""))
5806
              (pc)))]
5807
  "TARGET_THUMB"
5808
  "
5809
  if (thumb_cmpneg_operand (operands[2], SImode))
5810
    {
5811
      emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5812
                                              operands[3], operands[0]));
5813
      DONE;
5814
    }
5815
  if (!thumb_cmp_operand (operands[2], SImode))
5816
    operands[2] = force_reg (SImode, operands[2]);
5817
  ")
5818
 
5819
(define_insn "*cbranchsi4_insn"
5820
  [(set (pc) (if_then_else
5821
              (match_operator 0 "arm_comparison_operator"
5822
               [(match_operand:SI 1 "s_register_operand" "l,*h")
5823
                (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5824
              (label_ref (match_operand 3 "" ""))
5825
              (pc)))]
5826
  "TARGET_THUMB"
5827
  "*
5828
  output_asm_insn (\"cmp\\t%1, %2\", operands);
5829
 
5830
  switch (get_attr_length (insn))
5831
    {
5832
    case 4:  return \"b%d0\\t%l3\";
5833
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5834
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5835
    }
5836
  "
5837
  [(set (attr "far_jump")
5838
        (if_then_else
5839
            (eq_attr "length" "8")
5840
            (const_string "yes")
5841
            (const_string "no")))
5842
   (set (attr "length")
5843
        (if_then_else
5844
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5845
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
5846
            (const_int 4)
5847
            (if_then_else
5848
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5849
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5850
                (const_int 6)
5851
                (const_int 8))))]
5852
)
5853
 
5854
(define_insn "cbranchsi4_scratch"
5855
  [(set (pc) (if_then_else
5856
              (match_operator 4 "arm_comparison_operator"
5857
               [(match_operand:SI 1 "s_register_operand" "l,0")
5858
                (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5859
              (label_ref (match_operand 3 "" ""))
5860
              (pc)))
5861
   (clobber (match_scratch:SI 0 "=l,l"))]
5862
  "TARGET_THUMB"
5863
  "*
5864
  output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5865
 
5866
  switch (get_attr_length (insn))
5867
    {
5868
    case 4:  return \"b%d4\\t%l3\";
5869
    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5870
    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5871
    }
5872
  "
5873
  [(set (attr "far_jump")
5874
        (if_then_else
5875
            (eq_attr "length" "8")
5876
            (const_string "yes")
5877
            (const_string "no")))
5878
   (set (attr "length")
5879
        (if_then_else
5880
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5881
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
5882
            (const_int 4)
5883
            (if_then_else
5884
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5885
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5886
                (const_int 6)
5887
                (const_int 8))))]
5888
)
5889
(define_insn "*movsi_cbranchsi4"
5890
  [(set (pc)
5891
        (if_then_else
5892
         (match_operator 3 "arm_comparison_operator"
5893
          [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5894
           (const_int 0)])
5895
         (label_ref (match_operand 2 "" ""))
5896
         (pc)))
5897
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5898
        (match_dup 1))]
5899
  "TARGET_THUMB"
5900
  "*{
5901
  if (which_alternative == 0)
5902
    output_asm_insn (\"cmp\t%0, #0\", operands);
5903
  else if (which_alternative == 1)
5904
    output_asm_insn (\"sub\t%0, %1, #0\", operands);
5905
  else
5906
    {
5907
      output_asm_insn (\"cmp\t%1, #0\", operands);
5908
      if (which_alternative == 2)
5909
        output_asm_insn (\"mov\t%0, %1\", operands);
5910
      else
5911
        output_asm_insn (\"str\t%1, %0\", operands);
5912
    }
5913
  switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5914
    {
5915
    case 4:  return \"b%d3\\t%l2\";
5916
    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5917
    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5918
    }
5919
  }"
5920
  [(set (attr "far_jump")
5921
        (if_then_else
5922
            (ior (and (gt (symbol_ref ("which_alternative"))
5923
                          (const_int 1))
5924
                      (eq_attr "length" "8"))
5925
                 (eq_attr "length" "10"))
5926
            (const_string "yes")
5927
            (const_string "no")))
5928
   (set (attr "length")
5929
     (if_then_else
5930
       (le (symbol_ref ("which_alternative"))
5931
                       (const_int 1))
5932
       (if_then_else
5933
         (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5934
              (le (minus (match_dup 2) (pc)) (const_int 256)))
5935
         (const_int 4)
5936
         (if_then_else
5937
           (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5938
                (le (minus (match_dup 2) (pc)) (const_int 2048)))
5939
           (const_int 6)
5940
           (const_int 8)))
5941
       (if_then_else
5942
         (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5943
              (le (minus (match_dup 2) (pc)) (const_int 256)))
5944
         (const_int 6)
5945
         (if_then_else
5946
           (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5947
                (le (minus (match_dup 2) (pc)) (const_int 2048)))
5948
           (const_int 8)
5949
           (const_int 10)))))]
5950
)
5951
 
5952
(define_insn "*negated_cbranchsi4"
5953
  [(set (pc)
5954
        (if_then_else
5955
         (match_operator 0 "equality_operator"
5956
          [(match_operand:SI 1 "s_register_operand" "l")
5957
           (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5958
         (label_ref (match_operand 3 "" ""))
5959
         (pc)))]
5960
  "TARGET_THUMB"
5961
  "*
5962
  output_asm_insn (\"cmn\\t%1, %2\", operands);
5963
  switch (get_attr_length (insn))
5964
    {
5965
    case 4:  return \"b%d0\\t%l3\";
5966
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5967
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5968
    }
5969
  "
5970
  [(set (attr "far_jump")
5971
        (if_then_else
5972
            (eq_attr "length" "8")
5973
            (const_string "yes")
5974
            (const_string "no")))
5975
   (set (attr "length")
5976
        (if_then_else
5977
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5978
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
5979
            (const_int 4)
5980
            (if_then_else
5981
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5982
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
5983
                (const_int 6)
5984
                (const_int 8))))]
5985
)
5986
 
5987
(define_insn "*tbit_cbranch"
5988
  [(set (pc)
5989
        (if_then_else
5990
         (match_operator 0 "equality_operator"
5991
          [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5992
                            (const_int 1)
5993
                            (match_operand:SI 2 "const_int_operand" "i"))
5994
           (const_int 0)])
5995
         (label_ref (match_operand 3 "" ""))
5996
         (pc)))
5997
   (clobber (match_scratch:SI 4 "=l"))]
5998
  "TARGET_THUMB"
5999
  "*
6000
  {
6001
  rtx op[3];
6002
  op[0] = operands[4];
6003
  op[1] = operands[1];
6004
  op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6005
 
6006
  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6007
  switch (get_attr_length (insn))
6008
    {
6009
    case 4:  return \"b%d0\\t%l3\";
6010
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6011
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6012
    }
6013
  }"
6014
  [(set (attr "far_jump")
6015
        (if_then_else
6016
            (eq_attr "length" "8")
6017
            (const_string "yes")
6018
            (const_string "no")))
6019
   (set (attr "length")
6020
        (if_then_else
6021
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6022
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
6023
            (const_int 4)
6024
            (if_then_else
6025
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6026
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6027
                (const_int 6)
6028
                (const_int 8))))]
6029
)
6030
 
6031
(define_insn "*tlobits_cbranch"
6032
  [(set (pc)
6033
        (if_then_else
6034
         (match_operator 0 "equality_operator"
6035
          [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6036
                            (match_operand:SI 2 "const_int_operand" "i")
6037
                            (const_int 0))
6038
           (const_int 0)])
6039
         (label_ref (match_operand 3 "" ""))
6040
         (pc)))
6041
   (clobber (match_scratch:SI 4 "=l"))]
6042
  "TARGET_THUMB"
6043
  "*
6044
  {
6045
  rtx op[3];
6046
  op[0] = operands[4];
6047
  op[1] = operands[1];
6048
  op[2] = GEN_INT (32 - INTVAL (operands[2]));
6049
 
6050
  output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6051
  switch (get_attr_length (insn))
6052
    {
6053
    case 4:  return \"b%d0\\t%l3\";
6054
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6055
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6056
    }
6057
  }"
6058
  [(set (attr "far_jump")
6059
        (if_then_else
6060
            (eq_attr "length" "8")
6061
            (const_string "yes")
6062
            (const_string "no")))
6063
   (set (attr "length")
6064
        (if_then_else
6065
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6066
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
6067
            (const_int 4)
6068
            (if_then_else
6069
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6070
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6071
                (const_int 6)
6072
                (const_int 8))))]
6073
)
6074
 
6075
(define_insn "*tstsi3_cbranch"
6076
  [(set (pc)
6077
        (if_then_else
6078
         (match_operator 3 "equality_operator"
6079
          [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6080
                   (match_operand:SI 1 "s_register_operand" "l"))
6081
           (const_int 0)])
6082
         (label_ref (match_operand 2 "" ""))
6083
         (pc)))]
6084
  "TARGET_THUMB"
6085
  "*
6086
  {
6087
  output_asm_insn (\"tst\\t%0, %1\", operands);
6088
  switch (get_attr_length (insn))
6089
    {
6090
    case 4:  return \"b%d3\\t%l2\";
6091
    case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6092
    default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6093
    }
6094
  }"
6095
  [(set (attr "far_jump")
6096
        (if_then_else
6097
            (eq_attr "length" "8")
6098
            (const_string "yes")
6099
            (const_string "no")))
6100
   (set (attr "length")
6101
        (if_then_else
6102
            (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6103
                 (le (minus (match_dup 2) (pc)) (const_int 256)))
6104
            (const_int 4)
6105
            (if_then_else
6106
                (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6107
                     (le (minus (match_dup 2) (pc)) (const_int 2048)))
6108
                (const_int 6)
6109
                (const_int 8))))]
6110
)
6111
 
6112
(define_insn "*andsi3_cbranch"
6113
  [(set (pc)
6114
        (if_then_else
6115
         (match_operator 5 "equality_operator"
6116
          [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6117
                   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6118
           (const_int 0)])
6119
         (label_ref (match_operand 4 "" ""))
6120
         (pc)))
6121
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6122
        (and:SI (match_dup 2) (match_dup 3)))
6123
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6124
  "TARGET_THUMB"
6125
  "*
6126
  {
6127
  if (which_alternative == 0)
6128
    output_asm_insn (\"and\\t%0, %3\", operands);
6129
  else if (which_alternative == 1)
6130
    {
6131
      output_asm_insn (\"and\\t%1, %3\", operands);
6132
      output_asm_insn (\"mov\\t%0, %1\", operands);
6133
    }
6134
  else
6135
    {
6136
      output_asm_insn (\"and\\t%1, %3\", operands);
6137
      output_asm_insn (\"str\\t%1, %0\", operands);
6138
    }
6139
 
6140
  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6141
    {
6142
    case 4:  return \"b%d5\\t%l4\";
6143
    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6144
    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6145
    }
6146
  }"
6147
  [(set (attr "far_jump")
6148
        (if_then_else
6149
            (ior (and (eq (symbol_ref ("which_alternative"))
6150
                          (const_int 0))
6151
                      (eq_attr "length" "8"))
6152
                 (eq_attr "length" "10"))
6153
            (const_string "yes")
6154
            (const_string "no")))
6155
   (set (attr "length")
6156
     (if_then_else
6157
       (eq (symbol_ref ("which_alternative"))
6158
                       (const_int 0))
6159
       (if_then_else
6160
         (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6161
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6162
         (const_int 4)
6163
         (if_then_else
6164
           (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6165
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6166
           (const_int 6)
6167
           (const_int 8)))
6168
       (if_then_else
6169
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6170
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6171
         (const_int 6)
6172
         (if_then_else
6173
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6174
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6175
           (const_int 8)
6176
           (const_int 10)))))]
6177
)
6178
 
6179
(define_insn "*orrsi3_cbranch_scratch"
6180
  [(set (pc)
6181
        (if_then_else
6182
         (match_operator 4 "equality_operator"
6183
          [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6184
                   (match_operand:SI 2 "s_register_operand" "l"))
6185
           (const_int 0)])
6186
         (label_ref (match_operand 3 "" ""))
6187
         (pc)))
6188
   (clobber (match_scratch:SI 0 "=l"))]
6189
  "TARGET_THUMB"
6190
  "*
6191
  {
6192
  output_asm_insn (\"orr\\t%0, %2\", operands);
6193
  switch (get_attr_length (insn))
6194
    {
6195
    case 4:  return \"b%d4\\t%l3\";
6196
    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6197
    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6198
    }
6199
  }"
6200
  [(set (attr "far_jump")
6201
        (if_then_else
6202
            (eq_attr "length" "8")
6203
            (const_string "yes")
6204
            (const_string "no")))
6205
   (set (attr "length")
6206
        (if_then_else
6207
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6208
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
6209
            (const_int 4)
6210
            (if_then_else
6211
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6212
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6213
                (const_int 6)
6214
                (const_int 8))))]
6215
)
6216
 
6217
(define_insn "*orrsi3_cbranch"
6218
  [(set (pc)
6219
        (if_then_else
6220
         (match_operator 5 "equality_operator"
6221
          [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6222
                   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6223
           (const_int 0)])
6224
         (label_ref (match_operand 4 "" ""))
6225
         (pc)))
6226
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6227
        (ior:SI (match_dup 2) (match_dup 3)))
6228
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6229
  "TARGET_THUMB"
6230
  "*
6231
  {
6232
  if (which_alternative == 0)
6233
    output_asm_insn (\"orr\\t%0, %3\", operands);
6234
  else if (which_alternative == 1)
6235
    {
6236
      output_asm_insn (\"orr\\t%1, %3\", operands);
6237
      output_asm_insn (\"mov\\t%0, %1\", operands);
6238
    }
6239
  else
6240
    {
6241
      output_asm_insn (\"orr\\t%1, %3\", operands);
6242
      output_asm_insn (\"str\\t%1, %0\", operands);
6243
    }
6244
 
6245
  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6246
    {
6247
    case 4:  return \"b%d5\\t%l4\";
6248
    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6249
    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6250
    }
6251
  }"
6252
  [(set (attr "far_jump")
6253
        (if_then_else
6254
            (ior (and (eq (symbol_ref ("which_alternative"))
6255
                          (const_int 0))
6256
                      (eq_attr "length" "8"))
6257
                 (eq_attr "length" "10"))
6258
            (const_string "yes")
6259
            (const_string "no")))
6260
   (set (attr "length")
6261
     (if_then_else
6262
       (eq (symbol_ref ("which_alternative"))
6263
                       (const_int 0))
6264
       (if_then_else
6265
         (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6266
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6267
         (const_int 4)
6268
         (if_then_else
6269
           (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6270
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6271
           (const_int 6)
6272
           (const_int 8)))
6273
       (if_then_else
6274
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6275
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6276
         (const_int 6)
6277
         (if_then_else
6278
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6279
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6280
           (const_int 8)
6281
           (const_int 10)))))]
6282
)
6283
 
6284
(define_insn "*xorsi3_cbranch_scratch"
6285
  [(set (pc)
6286
        (if_then_else
6287
         (match_operator 4 "equality_operator"
6288
          [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6289
                   (match_operand:SI 2 "s_register_operand" "l"))
6290
           (const_int 0)])
6291
         (label_ref (match_operand 3 "" ""))
6292
         (pc)))
6293
   (clobber (match_scratch:SI 0 "=l"))]
6294
  "TARGET_THUMB"
6295
  "*
6296
  {
6297
  output_asm_insn (\"eor\\t%0, %2\", operands);
6298
  switch (get_attr_length (insn))
6299
    {
6300
    case 4:  return \"b%d4\\t%l3\";
6301
    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6302
    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6303
    }
6304
  }"
6305
  [(set (attr "far_jump")
6306
        (if_then_else
6307
            (eq_attr "length" "8")
6308
            (const_string "yes")
6309
            (const_string "no")))
6310
   (set (attr "length")
6311
        (if_then_else
6312
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6313
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
6314
            (const_int 4)
6315
            (if_then_else
6316
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6317
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6318
                (const_int 6)
6319
                (const_int 8))))]
6320
)
6321
 
6322
(define_insn "*xorsi3_cbranch"
6323
  [(set (pc)
6324
        (if_then_else
6325
         (match_operator 5 "equality_operator"
6326
          [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6327
                   (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6328
           (const_int 0)])
6329
         (label_ref (match_operand 4 "" ""))
6330
         (pc)))
6331
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6332
        (xor:SI (match_dup 2) (match_dup 3)))
6333
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6334
  "TARGET_THUMB"
6335
  "*
6336
  {
6337
  if (which_alternative == 0)
6338
    output_asm_insn (\"eor\\t%0, %3\", operands);
6339
  else if (which_alternative == 1)
6340
    {
6341
      output_asm_insn (\"eor\\t%1, %3\", operands);
6342
      output_asm_insn (\"mov\\t%0, %1\", operands);
6343
    }
6344
  else
6345
    {
6346
      output_asm_insn (\"eor\\t%1, %3\", operands);
6347
      output_asm_insn (\"str\\t%1, %0\", operands);
6348
    }
6349
 
6350
  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6351
    {
6352
    case 4:  return \"b%d5\\t%l4\";
6353
    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6354
    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6355
    }
6356
  }"
6357
  [(set (attr "far_jump")
6358
        (if_then_else
6359
            (ior (and (eq (symbol_ref ("which_alternative"))
6360
                          (const_int 0))
6361
                      (eq_attr "length" "8"))
6362
                 (eq_attr "length" "10"))
6363
            (const_string "yes")
6364
            (const_string "no")))
6365
   (set (attr "length")
6366
     (if_then_else
6367
       (eq (symbol_ref ("which_alternative"))
6368
                       (const_int 0))
6369
       (if_then_else
6370
         (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6371
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6372
         (const_int 4)
6373
         (if_then_else
6374
           (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6375
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6376
           (const_int 6)
6377
           (const_int 8)))
6378
       (if_then_else
6379
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6380
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6381
         (const_int 6)
6382
         (if_then_else
6383
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6384
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6385
           (const_int 8)
6386
           (const_int 10)))))]
6387
)
6388
 
6389
(define_insn "*bicsi3_cbranch_scratch"
6390
  [(set (pc)
6391
        (if_then_else
6392
         (match_operator 4 "equality_operator"
6393
          [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6394
                   (match_operand:SI 1 "s_register_operand" "0"))
6395
           (const_int 0)])
6396
         (label_ref (match_operand 3 "" ""))
6397
         (pc)))
6398
   (clobber (match_scratch:SI 0 "=l"))]
6399
  "TARGET_THUMB"
6400
  "*
6401
  {
6402
  output_asm_insn (\"bic\\t%0, %2\", operands);
6403
  switch (get_attr_length (insn))
6404
    {
6405
    case 4:  return \"b%d4\\t%l3\";
6406
    case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6407
    default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6408
    }
6409
  }"
6410
  [(set (attr "far_jump")
6411
        (if_then_else
6412
            (eq_attr "length" "8")
6413
            (const_string "yes")
6414
            (const_string "no")))
6415
   (set (attr "length")
6416
        (if_then_else
6417
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6418
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
6419
            (const_int 4)
6420
            (if_then_else
6421
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6422
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6423
                (const_int 6)
6424
                (const_int 8))))]
6425
)
6426
 
6427
(define_insn "*bicsi3_cbranch"
6428
  [(set (pc)
6429
        (if_then_else
6430
         (match_operator 5 "equality_operator"
6431
          [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6432
                   (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6433
           (const_int 0)])
6434
         (label_ref (match_operand 4 "" ""))
6435
         (pc)))
6436
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6437
        (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6438
   (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6439
  "TARGET_THUMB"
6440
  "*
6441
  {
6442
  if (which_alternative == 0)
6443
    output_asm_insn (\"bic\\t%0, %3\", operands);
6444
  else if (which_alternative <= 2)
6445
    {
6446
      output_asm_insn (\"bic\\t%1, %3\", operands);
6447
      /* It's ok if OP0 is a lo-reg, even though the mov will set the
6448
         conditions again, since we're only testing for equality.  */
6449
      output_asm_insn (\"mov\\t%0, %1\", operands);
6450
    }
6451
  else
6452
    {
6453
      output_asm_insn (\"bic\\t%1, %3\", operands);
6454
      output_asm_insn (\"str\\t%1, %0\", operands);
6455
    }
6456
 
6457
  switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6458
    {
6459
    case 4:  return \"b%d5\\t%l4\";
6460
    case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6461
    default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6462
    }
6463
  }"
6464
  [(set (attr "far_jump")
6465
        (if_then_else
6466
            (ior (and (eq (symbol_ref ("which_alternative"))
6467
                          (const_int 0))
6468
                      (eq_attr "length" "8"))
6469
                 (eq_attr "length" "10"))
6470
            (const_string "yes")
6471
            (const_string "no")))
6472
   (set (attr "length")
6473
     (if_then_else
6474
       (eq (symbol_ref ("which_alternative"))
6475
                       (const_int 0))
6476
       (if_then_else
6477
         (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6478
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6479
         (const_int 4)
6480
         (if_then_else
6481
           (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6482
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6483
           (const_int 6)
6484
           (const_int 8)))
6485
       (if_then_else
6486
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6487
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6488
         (const_int 6)
6489
         (if_then_else
6490
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6491
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6492
           (const_int 8)
6493
           (const_int 10)))))]
6494
)
6495
 
6496
(define_insn "*cbranchne_decr1"
6497
  [(set (pc)
6498
        (if_then_else (match_operator 3 "equality_operator"
6499
                       [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6500
                        (const_int 0)])
6501
                      (label_ref (match_operand 4 "" ""))
6502
                      (pc)))
6503
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6504
        (plus:SI (match_dup 2) (const_int -1)))
6505
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6506
  "TARGET_THUMB"
6507
  "*
6508
   {
6509
     rtx cond[2];
6510
     cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6511
                                ? GEU : LTU),
6512
                               VOIDmode, operands[2], const1_rtx);
6513
     cond[1] = operands[4];
6514
 
6515
     if (which_alternative == 0)
6516
       output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6517
     else if (which_alternative == 1)
6518
       {
6519
         /* We must provide an alternative for a hi reg because reload
6520
            cannot handle output reloads on a jump instruction, but we
6521
            can't subtract into that.  Fortunately a mov from lo to hi
6522
            does not clobber the condition codes.  */
6523
         output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6524
         output_asm_insn (\"mov\\t%0, %1\", operands);
6525
       }
6526
     else
6527
       {
6528
         /* Similarly, but the target is memory.  */
6529
         output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6530
         output_asm_insn (\"str\\t%1, %0\", operands);
6531
       }
6532
 
6533
     switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6534
       {
6535
         case 4:
6536
           output_asm_insn (\"b%d0\\t%l1\", cond);
6537
           return \"\";
6538
         case 6:
6539
           output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6540
           return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6541
         default:
6542
           output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6543
           return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6544
       }
6545
   }
6546
  "
6547
  [(set (attr "far_jump")
6548
        (if_then_else
6549
            (ior (and (eq (symbol_ref ("which_alternative"))
6550
                          (const_int 0))
6551
                      (eq_attr "length" "8"))
6552
                 (eq_attr "length" "10"))
6553
            (const_string "yes")
6554
            (const_string "no")))
6555
   (set_attr_alternative "length"
6556
      [
6557
       ;; Alternative 0
6558
       (if_then_else
6559
         (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6560
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6561
         (const_int 4)
6562
         (if_then_else
6563
           (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6564
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6565
           (const_int 6)
6566
           (const_int 8)))
6567
       ;; Alternative 1
6568
       (if_then_else
6569
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6570
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6571
         (const_int 6)
6572
         (if_then_else
6573
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6574
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6575
           (const_int 8)
6576
           (const_int 10)))
6577
       ;; Alternative 2
6578
       (if_then_else
6579
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6580
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6581
         (const_int 6)
6582
         (if_then_else
6583
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6584
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6585
           (const_int 8)
6586
           (const_int 10)))
6587
       ;; Alternative 3
6588
       (if_then_else
6589
         (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6590
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6591
         (const_int 6)
6592
         (if_then_else
6593
           (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6594
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6595
           (const_int 8)
6596
           (const_int 10)))])]
6597
)
6598
 
6599
(define_insn "*addsi3_cbranch"
6600
  [(set (pc)
6601
        (if_then_else
6602
         (match_operator 4 "comparison_operator"
6603
          [(plus:SI
6604
            (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6605
            (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6606
           (const_int 0)])
6607
         (label_ref (match_operand 5 "" ""))
6608
         (pc)))
6609
   (set
6610
    (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6611
    (plus:SI (match_dup 2) (match_dup 3)))
6612
   (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6613
  "TARGET_THUMB
6614
   && (GET_CODE (operands[4]) == EQ
6615
       || GET_CODE (operands[4]) == NE
6616
       || GET_CODE (operands[4]) == GE
6617
       || GET_CODE (operands[4]) == LT)"
6618
  "*
6619
   {
6620
     rtx cond[3];
6621
 
6622
 
6623
     cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6624
     cond[1] = operands[2];
6625
     cond[2] = operands[3];
6626
 
6627
     if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6628
       output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6629
     else
6630
       output_asm_insn (\"add\\t%0, %1, %2\", cond);
6631
 
6632
     if (which_alternative >= 3
6633
         && which_alternative < 4)
6634
       output_asm_insn (\"mov\\t%0, %1\", operands);
6635
     else if (which_alternative >= 4)
6636
       output_asm_insn (\"str\\t%1, %0\", operands);
6637
 
6638
     switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6639
       {
6640
         case 4:
6641
           return \"b%d4\\t%l5\";
6642
         case 6:
6643
           return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6644
         default:
6645
           return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6646
       }
6647
   }
6648
  "
6649
  [(set (attr "far_jump")
6650
        (if_then_else
6651
            (ior (and (lt (symbol_ref ("which_alternative"))
6652
                          (const_int 3))
6653
                      (eq_attr "length" "8"))
6654
                 (eq_attr "length" "10"))
6655
            (const_string "yes")
6656
            (const_string "no")))
6657
   (set (attr "length")
6658
     (if_then_else
6659
       (lt (symbol_ref ("which_alternative"))
6660
                       (const_int 3))
6661
       (if_then_else
6662
         (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6663
              (le (minus (match_dup 5) (pc)) (const_int 256)))
6664
         (const_int 4)
6665
         (if_then_else
6666
           (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6667
                (le (minus (match_dup 5) (pc)) (const_int 2048)))
6668
           (const_int 6)
6669
           (const_int 8)))
6670
       (if_then_else
6671
         (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6672
              (le (minus (match_dup 5) (pc)) (const_int 256)))
6673
         (const_int 6)
6674
         (if_then_else
6675
           (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6676
                (le (minus (match_dup 5) (pc)) (const_int 2048)))
6677
           (const_int 8)
6678
           (const_int 10)))))]
6679
)
6680
 
6681
(define_insn "*addsi3_cbranch_scratch"
6682
  [(set (pc)
6683
        (if_then_else
6684
         (match_operator 3 "comparison_operator"
6685
          [(plus:SI
6686
            (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6687
            (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6688
           (const_int 0)])
6689
         (label_ref (match_operand 4 "" ""))
6690
         (pc)))
6691
   (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6692
  "TARGET_THUMB
6693
   && (GET_CODE (operands[3]) == EQ
6694
       || GET_CODE (operands[3]) == NE
6695
       || GET_CODE (operands[3]) == GE
6696
       || GET_CODE (operands[3]) == LT)"
6697
  "*
6698
   {
6699
     switch (which_alternative)
6700
       {
6701
       case 0:
6702
         output_asm_insn (\"cmp\t%1, #%n2\", operands);
6703
         break;
6704
       case 1:
6705
         output_asm_insn (\"cmn\t%1, %2\", operands);
6706
         break;
6707
       case 2:
6708
         if (INTVAL (operands[2]) < 0)
6709
           output_asm_insn (\"sub\t%0, %1, %2\", operands);
6710
         else
6711
           output_asm_insn (\"add\t%0, %1, %2\", operands);
6712
         break;
6713
       case 3:
6714
         if (INTVAL (operands[2]) < 0)
6715
           output_asm_insn (\"sub\t%0, %0, %2\", operands);
6716
         else
6717
           output_asm_insn (\"add\t%0, %0, %2\", operands);
6718
         break;
6719
       }
6720
 
6721
     switch (get_attr_length (insn))
6722
       {
6723
         case 4:
6724
           return \"b%d3\\t%l4\";
6725
         case 6:
6726
           return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6727
         default:
6728
           return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6729
       }
6730
   }
6731
  "
6732
  [(set (attr "far_jump")
6733
        (if_then_else
6734
            (eq_attr "length" "8")
6735
            (const_string "yes")
6736
            (const_string "no")))
6737
   (set (attr "length")
6738
       (if_then_else
6739
         (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6740
              (le (minus (match_dup 4) (pc)) (const_int 256)))
6741
         (const_int 4)
6742
         (if_then_else
6743
           (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6744
                (le (minus (match_dup 4) (pc)) (const_int 2048)))
6745
           (const_int 6)
6746
           (const_int 8))))]
6747
)
6748
 
6749
(define_insn "*subsi3_cbranch"
6750
  [(set (pc)
6751
        (if_then_else
6752
         (match_operator 4 "comparison_operator"
6753
          [(minus:SI
6754
            (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6755
            (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6756
           (const_int 0)])
6757
         (label_ref (match_operand 5 "" ""))
6758
         (pc)))
6759
   (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6760
        (minus:SI (match_dup 2) (match_dup 3)))
6761
   (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6762
  "TARGET_THUMB
6763
   && (GET_CODE (operands[4]) == EQ
6764
       || GET_CODE (operands[4]) == NE
6765
       || GET_CODE (operands[4]) == GE
6766
       || GET_CODE (operands[4]) == LT)"
6767
  "*
6768
   {
6769
     if (which_alternative == 0)
6770
       output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6771
     else if (which_alternative == 1)
6772
       {
6773
         /* We must provide an alternative for a hi reg because reload
6774
            cannot handle output reloads on a jump instruction, but we
6775
            can't subtract into that.  Fortunately a mov from lo to hi
6776
            does not clobber the condition codes.  */
6777
         output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6778
         output_asm_insn (\"mov\\t%0, %1\", operands);
6779
       }
6780
     else
6781
       {
6782
         /* Similarly, but the target is memory.  */
6783
         output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6784
         output_asm_insn (\"str\\t%1, %0\", operands);
6785
       }
6786
 
6787
     switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6788
       {
6789
         case 4:
6790
           return \"b%d4\\t%l5\";
6791
         case 6:
6792
           return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6793
         default:
6794
           return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6795
       }
6796
   }
6797
  "
6798
  [(set (attr "far_jump")
6799
        (if_then_else
6800
            (ior (and (eq (symbol_ref ("which_alternative"))
6801
                          (const_int 0))
6802
                      (eq_attr "length" "8"))
6803
                 (eq_attr "length" "10"))
6804
            (const_string "yes")
6805
            (const_string "no")))
6806
   (set (attr "length")
6807
     (if_then_else
6808
       (eq (symbol_ref ("which_alternative"))
6809
                       (const_int 0))
6810
       (if_then_else
6811
         (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6812
              (le (minus (match_dup 5) (pc)) (const_int 256)))
6813
         (const_int 4)
6814
         (if_then_else
6815
           (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6816
                (le (minus (match_dup 5) (pc)) (const_int 2048)))
6817
           (const_int 6)
6818
           (const_int 8)))
6819
       (if_then_else
6820
         (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6821
              (le (minus (match_dup 5) (pc)) (const_int 256)))
6822
         (const_int 6)
6823
         (if_then_else
6824
           (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6825
                (le (minus (match_dup 5) (pc)) (const_int 2048)))
6826
           (const_int 8)
6827
           (const_int 10)))))]
6828
)
6829
 
6830
(define_insn "*subsi3_cbranch_scratch"
6831
  [(set (pc)
6832
        (if_then_else
6833
         (match_operator 0 "arm_comparison_operator"
6834
          [(minus:SI (match_operand:SI 1 "register_operand" "l")
6835
                     (match_operand:SI 2 "nonmemory_operand" "l"))
6836
           (const_int 0)])
6837
         (label_ref (match_operand 3 "" ""))
6838
         (pc)))]
6839
  "TARGET_THUMB
6840
   && (GET_CODE (operands[0]) == EQ
6841
       || GET_CODE (operands[0]) == NE
6842
       || GET_CODE (operands[0]) == GE
6843
       || GET_CODE (operands[0]) == LT)"
6844
  "*
6845
  output_asm_insn (\"cmp\\t%1, %2\", operands);
6846
  switch (get_attr_length (insn))
6847
    {
6848
    case 4:  return \"b%d0\\t%l3\";
6849
    case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6850
    default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6851
    }
6852
  "
6853
  [(set (attr "far_jump")
6854
        (if_then_else
6855
            (eq_attr "length" "8")
6856
            (const_string "yes")
6857
            (const_string "no")))
6858
   (set (attr "length")
6859
        (if_then_else
6860
            (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6861
                 (le (minus (match_dup 3) (pc)) (const_int 256)))
6862
            (const_int 4)
6863
            (if_then_else
6864
                (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6865
                     (le (minus (match_dup 3) (pc)) (const_int 2048)))
6866
                (const_int 6)
6867
                (const_int 8))))]
6868
)
6869
 
6870
;; Comparison and test insns
6871
 
6872
(define_expand "cmpsi"
6873
  [(match_operand:SI 0 "s_register_operand" "")
6874
   (match_operand:SI 1 "arm_add_operand" "")]
6875
  "TARGET_ARM"
6876
  "{
6877
    arm_compare_op0 = operands[0];
6878
    arm_compare_op1 = operands[1];
6879
    DONE;
6880
  }"
6881
)
6882
 
6883
(define_expand "cmpsf"
6884
  [(match_operand:SF 0 "s_register_operand" "")
6885
   (match_operand:SF 1 "arm_float_compare_operand" "")]
6886
  "TARGET_ARM && TARGET_HARD_FLOAT"
6887
  "
6888
  arm_compare_op0 = operands[0];
6889
  arm_compare_op1 = operands[1];
6890
  DONE;
6891
  "
6892
)
6893
 
6894
(define_expand "cmpdf"
6895
  [(match_operand:DF 0 "s_register_operand" "")
6896
   (match_operand:DF 1 "arm_float_compare_operand" "")]
6897
  "TARGET_ARM && TARGET_HARD_FLOAT"
6898
  "
6899
  arm_compare_op0 = operands[0];
6900
  arm_compare_op1 = operands[1];
6901
  DONE;
6902
  "
6903
)
6904
 
6905
(define_insn "*arm_cmpsi_insn"
6906
  [(set (reg:CC CC_REGNUM)
6907
        (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6908
                    (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6909
  "TARGET_ARM"
6910
  "@
6911
   cmp%?\\t%0, %1
6912
   cmn%?\\t%0, #%n1"
6913
  [(set_attr "conds" "set")]
6914
)
6915
 
6916
(define_insn "*cmpsi_shiftsi"
6917
  [(set (reg:CC CC_REGNUM)
6918
        (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6919
                    (match_operator:SI  3 "shift_operator"
6920
                     [(match_operand:SI 1 "s_register_operand" "r")
6921
                      (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6922
  "TARGET_ARM"
6923
  "cmp%?\\t%0, %1%S3"
6924
  [(set_attr "conds" "set")
6925
   (set_attr "shift" "1")
6926
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6927
                      (const_string "alu_shift")
6928
                      (const_string "alu_shift_reg")))]
6929
)
6930
 
6931
(define_insn "*cmpsi_shiftsi_swp"
6932
  [(set (reg:CC_SWP CC_REGNUM)
6933
        (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6934
                         [(match_operand:SI 1 "s_register_operand" "r")
6935
                          (match_operand:SI 2 "reg_or_int_operand" "rM")])
6936
                        (match_operand:SI 0 "s_register_operand" "r")))]
6937
  "TARGET_ARM"
6938
  "cmp%?\\t%0, %1%S3"
6939
  [(set_attr "conds" "set")
6940
   (set_attr "shift" "1")
6941
   (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6942
                      (const_string "alu_shift")
6943
                      (const_string "alu_shift_reg")))]
6944
)
6945
 
6946
(define_insn "*cmpsi_negshiftsi_si"
6947
  [(set (reg:CC_Z CC_REGNUM)
6948
        (compare:CC_Z
6949
         (neg:SI (match_operator:SI 1 "shift_operator"
6950
                    [(match_operand:SI 2 "s_register_operand" "r")
6951
                     (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6952
         (match_operand:SI 0 "s_register_operand" "r")))]
6953
  "TARGET_ARM"
6954
  "cmn%?\\t%0, %2%S1"
6955
  [(set_attr "conds" "set")
6956
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6957
                                    (const_string "alu_shift")
6958
                                    (const_string "alu_shift_reg")))]
6959
)
6960
 
6961
;; Cirrus SF compare instruction
6962
(define_insn "*cirrus_cmpsf"
6963
  [(set (reg:CCFP CC_REGNUM)
6964
        (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6965
                      (match_operand:SF 1 "cirrus_fp_register" "v")))]
6966
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6967
  "cfcmps%?\\tr15, %V0, %V1"
6968
  [(set_attr "type"   "mav_farith")
6969
   (set_attr "cirrus" "compare")]
6970
)
6971
 
6972
;; Cirrus DF compare instruction
6973
(define_insn "*cirrus_cmpdf"
6974
  [(set (reg:CCFP CC_REGNUM)
6975
        (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6976
                      (match_operand:DF 1 "cirrus_fp_register" "v")))]
6977
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6978
  "cfcmpd%?\\tr15, %V0, %V1"
6979
  [(set_attr "type"   "mav_farith")
6980
   (set_attr "cirrus" "compare")]
6981
)
6982
 
6983
;; Cirrus DI compare instruction
6984
(define_expand "cmpdi"
6985
  [(match_operand:DI 0 "cirrus_fp_register" "")
6986
   (match_operand:DI 1 "cirrus_fp_register" "")]
6987
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6988
  "{
6989
     arm_compare_op0 = operands[0];
6990
     arm_compare_op1 = operands[1];
6991
     DONE;
6992
   }")
6993
 
6994
(define_insn "*cirrus_cmpdi"
6995
  [(set (reg:CC CC_REGNUM)
6996
        (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6997
                    (match_operand:DI 1 "cirrus_fp_register" "v")))]
6998
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6999
  "cfcmp64%?\\tr15, %V0, %V1"
7000
  [(set_attr "type"   "mav_farith")
7001
   (set_attr "cirrus" "compare")]
7002
)
7003
 
7004
; This insn allows redundant compares to be removed by cse, nothing should
7005
; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7006
; is deleted later on. The match_dup will match the mode here, so that
7007
; mode changes of the condition codes aren't lost by this even though we don't
7008
; specify what they are.
7009
 
7010
(define_insn "*deleted_compare"
7011
  [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7012
  "TARGET_ARM"
7013
  "\\t%@ deleted compare"
7014
  [(set_attr "conds" "set")
7015
   (set_attr "length" "0")]
7016
)
7017
 
7018
 
7019
;; Conditional branch insns
7020
 
7021
(define_expand "beq"
7022
  [(set (pc)
7023
        (if_then_else (eq (match_dup 1) (const_int 0))
7024
                      (label_ref (match_operand 0 "" ""))
7025
                      (pc)))]
7026
  "TARGET_ARM"
7027
  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7028
)
7029
 
7030
(define_expand "bne"
7031
  [(set (pc)
7032
        (if_then_else (ne (match_dup 1) (const_int 0))
7033
                      (label_ref (match_operand 0 "" ""))
7034
                      (pc)))]
7035
  "TARGET_ARM"
7036
  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7037
)
7038
 
7039
(define_expand "bgt"
7040
  [(set (pc)
7041
        (if_then_else (gt (match_dup 1) (const_int 0))
7042
                      (label_ref (match_operand 0 "" ""))
7043
                      (pc)))]
7044
  "TARGET_ARM"
7045
  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7046
)
7047
 
7048
(define_expand "ble"
7049
  [(set (pc)
7050
        (if_then_else (le (match_dup 1) (const_int 0))
7051
                      (label_ref (match_operand 0 "" ""))
7052
                      (pc)))]
7053
  "TARGET_ARM"
7054
  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7055
)
7056
 
7057
(define_expand "bge"
7058
  [(set (pc)
7059
        (if_then_else (ge (match_dup 1) (const_int 0))
7060
                      (label_ref (match_operand 0 "" ""))
7061
                      (pc)))]
7062
  "TARGET_ARM"
7063
  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7064
)
7065
 
7066
(define_expand "blt"
7067
  [(set (pc)
7068
        (if_then_else (lt (match_dup 1) (const_int 0))
7069
                      (label_ref (match_operand 0 "" ""))
7070
                      (pc)))]
7071
  "TARGET_ARM"
7072
  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7073
)
7074
 
7075
(define_expand "bgtu"
7076
  [(set (pc)
7077
        (if_then_else (gtu (match_dup 1) (const_int 0))
7078
                      (label_ref (match_operand 0 "" ""))
7079
                      (pc)))]
7080
  "TARGET_ARM"
7081
  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7082
)
7083
 
7084
(define_expand "bleu"
7085
  [(set (pc)
7086
        (if_then_else (leu (match_dup 1) (const_int 0))
7087
                      (label_ref (match_operand 0 "" ""))
7088
                      (pc)))]
7089
  "TARGET_ARM"
7090
  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7091
)
7092
 
7093
(define_expand "bgeu"
7094
  [(set (pc)
7095
        (if_then_else (geu (match_dup 1) (const_int 0))
7096
                      (label_ref (match_operand 0 "" ""))
7097
                      (pc)))]
7098
  "TARGET_ARM"
7099
  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7100
)
7101
 
7102
(define_expand "bltu"
7103
  [(set (pc)
7104
        (if_then_else (ltu (match_dup 1) (const_int 0))
7105
                      (label_ref (match_operand 0 "" ""))
7106
                      (pc)))]
7107
  "TARGET_ARM"
7108
  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7109
)
7110
 
7111
(define_expand "bunordered"
7112
  [(set (pc)
7113
        (if_then_else (unordered (match_dup 1) (const_int 0))
7114
                      (label_ref (match_operand 0 "" ""))
7115
                      (pc)))]
7116
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7117
  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7118
                                      arm_compare_op1);"
7119
)
7120
 
7121
(define_expand "bordered"
7122
  [(set (pc)
7123
        (if_then_else (ordered (match_dup 1) (const_int 0))
7124
                      (label_ref (match_operand 0 "" ""))
7125
                      (pc)))]
7126
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7127
  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7128
                                      arm_compare_op1);"
7129
)
7130
 
7131
(define_expand "bungt"
7132
  [(set (pc)
7133
        (if_then_else (ungt (match_dup 1) (const_int 0))
7134
                      (label_ref (match_operand 0 "" ""))
7135
                      (pc)))]
7136
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7137
  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7138
)
7139
 
7140
(define_expand "bunlt"
7141
  [(set (pc)
7142
        (if_then_else (unlt (match_dup 1) (const_int 0))
7143
                      (label_ref (match_operand 0 "" ""))
7144
                      (pc)))]
7145
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7146
  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7147
)
7148
 
7149
(define_expand "bunge"
7150
  [(set (pc)
7151
        (if_then_else (unge (match_dup 1) (const_int 0))
7152
                      (label_ref (match_operand 0 "" ""))
7153
                      (pc)))]
7154
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7155
  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7156
)
7157
 
7158
(define_expand "bunle"
7159
  [(set (pc)
7160
        (if_then_else (unle (match_dup 1) (const_int 0))
7161
                      (label_ref (match_operand 0 "" ""))
7162
                      (pc)))]
7163
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7164
  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7165
)
7166
 
7167
;; The following two patterns need two branch instructions, since there is
7168
;; no single instruction that will handle all cases.
7169
(define_expand "buneq"
7170
  [(set (pc)
7171
        (if_then_else (uneq (match_dup 1) (const_int 0))
7172
                      (label_ref (match_operand 0 "" ""))
7173
                      (pc)))]
7174
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7175
  "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7176
)
7177
 
7178
(define_expand "bltgt"
7179
  [(set (pc)
7180
        (if_then_else (ltgt (match_dup 1) (const_int 0))
7181
                      (label_ref (match_operand 0 "" ""))
7182
                      (pc)))]
7183
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7184
  "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7185
)
7186
 
7187
;;
7188
;; Patterns to match conditional branch insns.
7189
;;
7190
 
7191
; Special pattern to match UNEQ.
7192
(define_insn "*arm_buneq"
7193
  [(set (pc)
7194
        (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7195
                      (label_ref (match_operand 0 "" ""))
7196
                      (pc)))]
7197
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7198
  "*
7199
  gcc_assert (!arm_ccfsm_state);
7200
 
7201
  return \"bvs\\t%l0\;beq\\t%l0\";
7202
  "
7203
  [(set_attr "conds" "jump_clob")
7204
   (set_attr "length" "8")]
7205
)
7206
 
7207
; Special pattern to match LTGT.
7208
(define_insn "*arm_bltgt"
7209
  [(set (pc)
7210
        (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7211
                      (label_ref (match_operand 0 "" ""))
7212
                      (pc)))]
7213
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7214
  "*
7215
  gcc_assert (!arm_ccfsm_state);
7216
 
7217
  return \"bmi\\t%l0\;bgt\\t%l0\";
7218
  "
7219
  [(set_attr "conds" "jump_clob")
7220
   (set_attr "length" "8")]
7221
)
7222
 
7223
(define_insn "*arm_cond_branch"
7224
  [(set (pc)
7225
        (if_then_else (match_operator 1 "arm_comparison_operator"
7226
                       [(match_operand 2 "cc_register" "") (const_int 0)])
7227
                      (label_ref (match_operand 0 "" ""))
7228
                      (pc)))]
7229
  "TARGET_ARM"
7230
  "*
7231
  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7232
    {
7233
      arm_ccfsm_state += 2;
7234
      return \"\";
7235
    }
7236
  return \"b%d1\\t%l0\";
7237
  "
7238
  [(set_attr "conds" "use")
7239
   (set_attr "type" "branch")]
7240
)
7241
 
7242
; Special pattern to match reversed UNEQ.
7243
(define_insn "*arm_buneq_reversed"
7244
  [(set (pc)
7245
        (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7246
                      (pc)
7247
                      (label_ref (match_operand 0 "" ""))))]
7248
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7249
  "*
7250
  gcc_assert (!arm_ccfsm_state);
7251
 
7252
  return \"bmi\\t%l0\;bgt\\t%l0\";
7253
  "
7254
  [(set_attr "conds" "jump_clob")
7255
   (set_attr "length" "8")]
7256
)
7257
 
7258
; Special pattern to match reversed LTGT.
7259
(define_insn "*arm_bltgt_reversed"
7260
  [(set (pc)
7261
        (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7262
                      (pc)
7263
                      (label_ref (match_operand 0 "" ""))))]
7264
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7265
  "*
7266
  gcc_assert (!arm_ccfsm_state);
7267
 
7268
  return \"bvs\\t%l0\;beq\\t%l0\";
7269
  "
7270
  [(set_attr "conds" "jump_clob")
7271
   (set_attr "length" "8")]
7272
)
7273
 
7274
(define_insn "*arm_cond_branch_reversed"
7275
  [(set (pc)
7276
        (if_then_else (match_operator 1 "arm_comparison_operator"
7277
                       [(match_operand 2 "cc_register" "") (const_int 0)])
7278
                      (pc)
7279
                      (label_ref (match_operand 0 "" ""))))]
7280
  "TARGET_ARM"
7281
  "*
7282
  if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7283
    {
7284
      arm_ccfsm_state += 2;
7285
      return \"\";
7286
    }
7287
  return \"b%D1\\t%l0\";
7288
  "
7289
  [(set_attr "conds" "use")
7290
   (set_attr "type" "branch")]
7291
)
7292
 
7293
 
7294
 
7295
; scc insns
7296
 
7297
(define_expand "seq"
7298
  [(set (match_operand:SI 0 "s_register_operand" "")
7299
        (eq:SI (match_dup 1) (const_int 0)))]
7300
  "TARGET_ARM"
7301
  "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7302
)
7303
 
7304
(define_expand "sne"
7305
  [(set (match_operand:SI 0 "s_register_operand" "")
7306
        (ne:SI (match_dup 1) (const_int 0)))]
7307
  "TARGET_ARM"
7308
  "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7309
)
7310
 
7311
(define_expand "sgt"
7312
  [(set (match_operand:SI 0 "s_register_operand" "")
7313
        (gt:SI (match_dup 1) (const_int 0)))]
7314
  "TARGET_ARM"
7315
  "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7316
)
7317
 
7318
(define_expand "sle"
7319
  [(set (match_operand:SI 0 "s_register_operand" "")
7320
        (le:SI (match_dup 1) (const_int 0)))]
7321
  "TARGET_ARM"
7322
  "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7323
)
7324
 
7325
(define_expand "sge"
7326
  [(set (match_operand:SI 0 "s_register_operand" "")
7327
        (ge:SI (match_dup 1) (const_int 0)))]
7328
  "TARGET_ARM"
7329
  "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7330
)
7331
 
7332
(define_expand "slt"
7333
  [(set (match_operand:SI 0 "s_register_operand" "")
7334
        (lt:SI (match_dup 1) (const_int 0)))]
7335
  "TARGET_ARM"
7336
  "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7337
)
7338
 
7339
(define_expand "sgtu"
7340
  [(set (match_operand:SI 0 "s_register_operand" "")
7341
        (gtu:SI (match_dup 1) (const_int 0)))]
7342
  "TARGET_ARM"
7343
  "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7344
)
7345
 
7346
(define_expand "sleu"
7347
  [(set (match_operand:SI 0 "s_register_operand" "")
7348
        (leu:SI (match_dup 1) (const_int 0)))]
7349
  "TARGET_ARM"
7350
  "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7351
)
7352
 
7353
(define_expand "sgeu"
7354
  [(set (match_operand:SI 0 "s_register_operand" "")
7355
        (geu:SI (match_dup 1) (const_int 0)))]
7356
  "TARGET_ARM"
7357
  "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7358
)
7359
 
7360
(define_expand "sltu"
7361
  [(set (match_operand:SI 0 "s_register_operand" "")
7362
        (ltu:SI (match_dup 1) (const_int 0)))]
7363
  "TARGET_ARM"
7364
  "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7365
)
7366
 
7367
(define_expand "sunordered"
7368
  [(set (match_operand:SI 0 "s_register_operand" "")
7369
        (unordered:SI (match_dup 1) (const_int 0)))]
7370
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7371
  "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7372
                                      arm_compare_op1);"
7373
)
7374
 
7375
(define_expand "sordered"
7376
  [(set (match_operand:SI 0 "s_register_operand" "")
7377
        (ordered:SI (match_dup 1) (const_int 0)))]
7378
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7379
  "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7380
                                      arm_compare_op1);"
7381
)
7382
 
7383
(define_expand "sungt"
7384
  [(set (match_operand:SI 0 "s_register_operand" "")
7385
        (ungt:SI (match_dup 1) (const_int 0)))]
7386
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7387
  "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7388
                                      arm_compare_op1);"
7389
)
7390
 
7391
(define_expand "sunge"
7392
  [(set (match_operand:SI 0 "s_register_operand" "")
7393
        (unge:SI (match_dup 1) (const_int 0)))]
7394
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7395
  "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7396
                                      arm_compare_op1);"
7397
)
7398
 
7399
(define_expand "sunlt"
7400
  [(set (match_operand:SI 0 "s_register_operand" "")
7401
        (unlt:SI (match_dup 1) (const_int 0)))]
7402
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7403
  "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7404
                                      arm_compare_op1);"
7405
)
7406
 
7407
(define_expand "sunle"
7408
  [(set (match_operand:SI 0 "s_register_operand" "")
7409
        (unle:SI (match_dup 1) (const_int 0)))]
7410
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7411
  "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7412
                                      arm_compare_op1);"
7413
)
7414
 
7415
;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7416
;;; simple ARM instructions.
7417
;
7418
; (define_expand "suneq"
7419
;   [(set (match_operand:SI 0 "s_register_operand" "")
7420
;       (uneq:SI (match_dup 1) (const_int 0)))]
7421
;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7422
;   "gcc_unreachable ();"
7423
; )
7424
;
7425
; (define_expand "sltgt"
7426
;   [(set (match_operand:SI 0 "s_register_operand" "")
7427
;       (ltgt:SI (match_dup 1) (const_int 0)))]
7428
;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7429
;   "gcc_unreachable ();"
7430
; )
7431
 
7432
(define_insn "*mov_scc"
7433
  [(set (match_operand:SI 0 "s_register_operand" "=r")
7434
        (match_operator:SI 1 "arm_comparison_operator"
7435
         [(match_operand 2 "cc_register" "") (const_int 0)]))]
7436
  "TARGET_ARM"
7437
  "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7438
  [(set_attr "conds" "use")
7439
   (set_attr "length" "8")]
7440
)
7441
 
7442
(define_insn "*mov_negscc"
7443
  [(set (match_operand:SI 0 "s_register_operand" "=r")
7444
        (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7445
                 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7446
  "TARGET_ARM"
7447
  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7448
  [(set_attr "conds" "use")
7449
   (set_attr "length" "8")]
7450
)
7451
 
7452
(define_insn "*mov_notscc"
7453
  [(set (match_operand:SI 0 "s_register_operand" "=r")
7454
        (not:SI (match_operator:SI 1 "arm_comparison_operator"
7455
                 [(match_operand 2 "cc_register" "") (const_int 0)])))]
7456
  "TARGET_ARM"
7457
  "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7458
  [(set_attr "conds" "use")
7459
   (set_attr "length" "8")]
7460
)
7461
 
7462
 
7463
;; Conditional move insns
7464
 
7465
(define_expand "movsicc"
7466
  [(set (match_operand:SI 0 "s_register_operand" "")
7467
        (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7468
                         (match_operand:SI 2 "arm_not_operand" "")
7469
                         (match_operand:SI 3 "arm_not_operand" "")))]
7470
  "TARGET_ARM"
7471
  "
7472
  {
7473
    enum rtx_code code = GET_CODE (operands[1]);
7474
    rtx ccreg;
7475
 
7476
    if (code == UNEQ || code == LTGT)
7477
      FAIL;
7478
 
7479
    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7480
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7481
  }"
7482
)
7483
 
7484
(define_expand "movsfcc"
7485
  [(set (match_operand:SF 0 "s_register_operand" "")
7486
        (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7487
                         (match_operand:SF 2 "s_register_operand" "")
7488
                         (match_operand:SF 3 "nonmemory_operand" "")))]
7489
  "TARGET_ARM"
7490
  "
7491
  {
7492
    enum rtx_code code = GET_CODE (operands[1]);
7493
    rtx ccreg;
7494
 
7495
    if (code == UNEQ || code == LTGT)
7496
      FAIL;
7497
 
7498
    /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7499
       Otherwise, ensure it is a valid FP add operand */
7500
    if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7501
        || (!arm_float_add_operand (operands[3], SFmode)))
7502
      operands[3] = force_reg (SFmode, operands[3]);
7503
 
7504
    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7505
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7506
  }"
7507
)
7508
 
7509
(define_expand "movdfcc"
7510
  [(set (match_operand:DF 0 "s_register_operand" "")
7511
        (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7512
                         (match_operand:DF 2 "s_register_operand" "")
7513
                         (match_operand:DF 3 "arm_float_add_operand" "")))]
7514
  "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7515
  "
7516
  {
7517
    enum rtx_code code = GET_CODE (operands[1]);
7518
    rtx ccreg;
7519
 
7520
    if (code == UNEQ || code == LTGT)
7521
      FAIL;
7522
 
7523
    ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7524
    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7525
  }"
7526
)
7527
 
7528
(define_insn "*movsicc_insn"
7529
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7530
        (if_then_else:SI
7531
         (match_operator 3 "arm_comparison_operator"
7532
          [(match_operand 4 "cc_register" "") (const_int 0)])
7533
         (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7534
         (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7535
  "TARGET_ARM"
7536
  "@
7537
   mov%D3\\t%0, %2
7538
   mvn%D3\\t%0, #%B2
7539
   mov%d3\\t%0, %1
7540
   mvn%d3\\t%0, #%B1
7541
   mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7542
   mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7543
   mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7544
   mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7545
  [(set_attr "length" "4,4,4,4,8,8,8,8")
7546
   (set_attr "conds" "use")]
7547
)
7548
 
7549
(define_insn "*movsfcc_soft_insn"
7550
  [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7551
        (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7552
                          [(match_operand 4 "cc_register" "") (const_int 0)])
7553
                         (match_operand:SF 1 "s_register_operand" "0,r")
7554
                         (match_operand:SF 2 "s_register_operand" "r,0")))]
7555
  "TARGET_ARM && TARGET_SOFT_FLOAT"
7556
  "@
7557
   mov%D3\\t%0, %2
7558
   mov%d3\\t%0, %1"
7559
  [(set_attr "conds" "use")]
7560
)
7561
 
7562
 
7563
;; Jump and linkage insns
7564
 
7565
(define_expand "jump"
7566
  [(set (pc)
7567
        (label_ref (match_operand 0 "" "")))]
7568
  "TARGET_EITHER"
7569
  ""
7570
)
7571
 
7572
(define_insn "*arm_jump"
7573
  [(set (pc)
7574
        (label_ref (match_operand 0 "" "")))]
7575
  "TARGET_ARM"
7576
  "*
7577
  {
7578
    if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7579
      {
7580
        arm_ccfsm_state += 2;
7581
        return \"\";
7582
      }
7583
    return \"b%?\\t%l0\";
7584
  }
7585
  "
7586
  [(set_attr "predicable" "yes")]
7587
)
7588
 
7589
(define_insn "*thumb_jump"
7590
  [(set (pc)
7591
        (label_ref (match_operand 0 "" "")))]
7592
  "TARGET_THUMB"
7593
  "*
7594
  if (get_attr_length (insn) == 2)
7595
    return \"b\\t%l0\";
7596
  return \"bl\\t%l0\\t%@ far jump\";
7597
  "
7598
  [(set (attr "far_jump")
7599
        (if_then_else
7600
            (eq_attr "length" "4")
7601
            (const_string "yes")
7602
            (const_string "no")))
7603
   (set (attr "length")
7604
        (if_then_else
7605
            (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7606
                 (le (minus (match_dup 0) (pc)) (const_int 2048)))
7607
            (const_int 2)
7608
            (const_int 4)))]
7609
)
7610
 
7611
(define_expand "call"
7612
  [(parallel [(call (match_operand 0 "memory_operand" "")
7613
                    (match_operand 1 "general_operand" ""))
7614
              (use (match_operand 2 "" ""))
7615
              (clobber (reg:SI LR_REGNUM))])]
7616
  "TARGET_EITHER"
7617
  "
7618
  {
7619
    rtx callee;
7620
 
7621
    /* In an untyped call, we can get NULL for operand 2.  */
7622
    if (operands[2] == NULL_RTX)
7623
      operands[2] = const0_rtx;
7624
 
7625
    /* This is to decide if we should generate indirect calls by loading the
7626
       32 bit address of the callee into a register before performing the
7627
       branch and link.  operand[2] encodes the long_call/short_call
7628
       attribute of the function being called.  This attribute is set whenever
7629
       __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7630
       is used, and the short_call attribute can also be set if function is
7631
       declared as static or if it has already been defined in the current
7632
       compilation unit.  See arm.c and arm.h for info about this.  The third
7633
       parameter to arm_is_longcall_p is used to tell it which pattern
7634
       invoked it.  */
7635
    callee  = XEXP (operands[0], 0);
7636
 
7637
    if ((GET_CODE (callee) == SYMBOL_REF
7638
         && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7639
        || (GET_CODE (callee) != SYMBOL_REF
7640
            && GET_CODE (callee) != REG))
7641
      XEXP (operands[0], 0) = force_reg (Pmode, callee);
7642
  }"
7643
)
7644
 
7645
(define_insn "*call_reg_armv5"
7646
  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7647
         (match_operand 1 "" ""))
7648
   (use (match_operand 2 "" ""))
7649
   (clobber (reg:SI LR_REGNUM))]
7650
  "TARGET_ARM && arm_arch5"
7651
  "blx%?\\t%0"
7652
  [(set_attr "type" "call")]
7653
)
7654
 
7655
(define_insn "*call_reg_arm"
7656
  [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7657
         (match_operand 1 "" ""))
7658
   (use (match_operand 2 "" ""))
7659
   (clobber (reg:SI LR_REGNUM))]
7660
  "TARGET_ARM && !arm_arch5"
7661
  "*
7662
  return output_call (operands);
7663
  "
7664
  ;; length is worst case, normally it is only two
7665
  [(set_attr "length" "12")
7666
   (set_attr "type" "call")]
7667
)
7668
 
7669
(define_insn "*call_mem"
7670
  [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7671
         (match_operand 1 "" ""))
7672
   (use (match_operand 2 "" ""))
7673
   (clobber (reg:SI LR_REGNUM))]
7674
  "TARGET_ARM"
7675
  "*
7676
  return output_call_mem (operands);
7677
  "
7678
  [(set_attr "length" "12")
7679
   (set_attr "type" "call")]
7680
)
7681
 
7682
(define_insn "*call_reg_thumb_v5"
7683
  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7684
         (match_operand 1 "" ""))
7685
   (use (match_operand 2 "" ""))
7686
   (clobber (reg:SI LR_REGNUM))]
7687
  "TARGET_THUMB && arm_arch5"
7688
  "blx\\t%0"
7689
  [(set_attr "length" "2")
7690
   (set_attr "type" "call")]
7691
)
7692
 
7693
(define_insn "*call_reg_thumb"
7694
  [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7695
         (match_operand 1 "" ""))
7696
   (use (match_operand 2 "" ""))
7697
   (clobber (reg:SI LR_REGNUM))]
7698
  "TARGET_THUMB && !arm_arch5"
7699
  "*
7700
  {
7701
    if (!TARGET_CALLER_INTERWORKING)
7702
      return thumb_call_via_reg (operands[0]);
7703
    else if (operands[1] == const0_rtx)
7704
      return \"bl\\t%__interwork_call_via_%0\";
7705
    else if (frame_pointer_needed)
7706
      return \"bl\\t%__interwork_r7_call_via_%0\";
7707
    else
7708
      return \"bl\\t%__interwork_r11_call_via_%0\";
7709
  }"
7710
  [(set_attr "type" "call")]
7711
)
7712
 
7713
(define_expand "call_value"
7714
  [(parallel [(set (match_operand       0 "" "")
7715
                   (call (match_operand 1 "memory_operand" "")
7716
                         (match_operand 2 "general_operand" "")))
7717
              (use (match_operand 3 "" ""))
7718
              (clobber (reg:SI LR_REGNUM))])]
7719
  "TARGET_EITHER"
7720
  "
7721
  {
7722
    rtx callee = XEXP (operands[1], 0);
7723
 
7724
    /* In an untyped call, we can get NULL for operand 2.  */
7725
    if (operands[3] == 0)
7726
      operands[3] = const0_rtx;
7727
 
7728
    /* See the comment in define_expand \"call\".  */
7729
    if ((GET_CODE (callee) == SYMBOL_REF
7730
         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7731
        || (GET_CODE (callee) != SYMBOL_REF
7732
            && GET_CODE (callee) != REG))
7733
      XEXP (operands[1], 0) = force_reg (Pmode, callee);
7734
  }"
7735
)
7736
 
7737
(define_insn "*call_value_reg_armv5"
7738
  [(set (match_operand 0 "" "")
7739
        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7740
              (match_operand 2 "" "")))
7741
   (use (match_operand 3 "" ""))
7742
   (clobber (reg:SI LR_REGNUM))]
7743
  "TARGET_ARM && arm_arch5"
7744
  "blx%?\\t%1"
7745
  [(set_attr "type" "call")]
7746
)
7747
 
7748
(define_insn "*call_value_reg_arm"
7749
  [(set (match_operand 0 "" "")
7750
        (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7751
              (match_operand 2 "" "")))
7752
   (use (match_operand 3 "" ""))
7753
   (clobber (reg:SI LR_REGNUM))]
7754
  "TARGET_ARM && !arm_arch5"
7755
  "*
7756
  return output_call (&operands[1]);
7757
  "
7758
  [(set_attr "length" "12")
7759
   (set_attr "type" "call")]
7760
)
7761
 
7762
(define_insn "*call_value_mem"
7763
  [(set (match_operand 0 "" "")
7764
        (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7765
              (match_operand 2 "" "")))
7766
   (use (match_operand 3 "" ""))
7767
   (clobber (reg:SI LR_REGNUM))]
7768
  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7769
  "*
7770
  return output_call_mem (&operands[1]);
7771
  "
7772
  [(set_attr "length" "12")
7773
   (set_attr "type" "call")]
7774
)
7775
 
7776
(define_insn "*call_value_reg_thumb_v5"
7777
  [(set (match_operand 0 "" "")
7778
        (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7779
              (match_operand 2 "" "")))
7780
   (use (match_operand 3 "" ""))
7781
   (clobber (reg:SI LR_REGNUM))]
7782
  "TARGET_THUMB && arm_arch5"
7783
  "blx\\t%1"
7784
  [(set_attr "length" "2")
7785
   (set_attr "type" "call")]
7786
)
7787
 
7788
(define_insn "*call_value_reg_thumb"
7789
  [(set (match_operand 0 "" "")
7790
        (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7791
              (match_operand 2 "" "")))
7792
   (use (match_operand 3 "" ""))
7793
   (clobber (reg:SI LR_REGNUM))]
7794
  "TARGET_THUMB && !arm_arch5"
7795
  "*
7796
  {
7797
    if (!TARGET_CALLER_INTERWORKING)
7798
      return thumb_call_via_reg (operands[1]);
7799
    else if (operands[2] == const0_rtx)
7800
      return \"bl\\t%__interwork_call_via_%1\";
7801
    else if (frame_pointer_needed)
7802
      return \"bl\\t%__interwork_r7_call_via_%1\";
7803
    else
7804
      return \"bl\\t%__interwork_r11_call_via_%1\";
7805
  }"
7806
  [(set_attr "type" "call")]
7807
)
7808
 
7809
;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7810
;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7811
 
7812
(define_insn "*call_symbol"
7813
  [(call (mem:SI (match_operand:SI 0 "" ""))
7814
         (match_operand 1 "" ""))
7815
   (use (match_operand 2 "" ""))
7816
   (clobber (reg:SI LR_REGNUM))]
7817
  "TARGET_ARM
7818
   && (GET_CODE (operands[0]) == SYMBOL_REF)
7819
   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7820
  "*
7821
  {
7822
    return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7823
  }"
7824
  [(set_attr "type" "call")]
7825
)
7826
 
7827
(define_insn "*call_value_symbol"
7828
  [(set (match_operand 0 "" "")
7829
        (call (mem:SI (match_operand:SI 1 "" ""))
7830
        (match_operand:SI 2 "" "")))
7831
   (use (match_operand 3 "" ""))
7832
   (clobber (reg:SI LR_REGNUM))]
7833
  "TARGET_ARM
7834
   && (GET_CODE (operands[1]) == SYMBOL_REF)
7835
   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7836
  "*
7837
  {
7838
    return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7839
  }"
7840
  [(set_attr "type" "call")]
7841
)
7842
 
7843
(define_insn "*call_insn"
7844
  [(call (mem:SI (match_operand:SI 0 "" ""))
7845
         (match_operand:SI 1 "" ""))
7846
   (use (match_operand 2 "" ""))
7847
   (clobber (reg:SI LR_REGNUM))]
7848
  "TARGET_THUMB
7849
   && GET_CODE (operands[0]) == SYMBOL_REF
7850
   && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7851
  "bl\\t%a0"
7852
  [(set_attr "length" "4")
7853
   (set_attr "type" "call")]
7854
)
7855
 
7856
(define_insn "*call_value_insn"
7857
  [(set (match_operand 0 "" "")
7858
        (call (mem:SI (match_operand 1 "" ""))
7859
              (match_operand 2 "" "")))
7860
   (use (match_operand 3 "" ""))
7861
   (clobber (reg:SI LR_REGNUM))]
7862
  "TARGET_THUMB
7863
   && GET_CODE (operands[1]) == SYMBOL_REF
7864
   && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7865
  "bl\\t%a1"
7866
  [(set_attr "length" "4")
7867
   (set_attr "type" "call")]
7868
)
7869
 
7870
;; We may also be able to do sibcalls for Thumb, but it's much harder...
7871
(define_expand "sibcall"
7872
  [(parallel [(call (match_operand 0 "memory_operand" "")
7873
                    (match_operand 1 "general_operand" ""))
7874
              (return)
7875
              (use (match_operand 2 "" ""))])]
7876
  "TARGET_ARM"
7877
  "
7878
  {
7879
    if (operands[2] == NULL_RTX)
7880
      operands[2] = const0_rtx;
7881
  }"
7882
)
7883
 
7884
(define_expand "sibcall_value"
7885
  [(parallel [(set (match_operand 0 "" "")
7886
                   (call (match_operand 1 "memory_operand" "")
7887
                         (match_operand 2 "general_operand" "")))
7888
              (return)
7889
              (use (match_operand 3 "" ""))])]
7890
  "TARGET_ARM"
7891
  "
7892
  {
7893
    if (operands[3] == NULL_RTX)
7894
      operands[3] = const0_rtx;
7895
  }"
7896
)
7897
 
7898
(define_insn "*sibcall_insn"
7899
 [(call (mem:SI (match_operand:SI 0 "" "X"))
7900
        (match_operand 1 "" ""))
7901
  (return)
7902
  (use (match_operand 2 "" ""))]
7903
  "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7904
  "*
7905
  return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7906
  "
7907
  [(set_attr "type" "call")]
7908
)
7909
 
7910
(define_insn "*sibcall_value_insn"
7911
 [(set (match_operand 0 "" "")
7912
       (call (mem:SI (match_operand:SI 1 "" "X"))
7913
             (match_operand 2 "" "")))
7914
  (return)
7915
  (use (match_operand 3 "" ""))]
7916
  "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7917
  "*
7918
  return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7919
  "
7920
  [(set_attr "type" "call")]
7921
)
7922
 
7923
;; Often the return insn will be the same as loading from memory, so set attr
7924
(define_insn "return"
7925
  [(return)]
7926
  "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7927
  "*
7928
  {
7929
    if (arm_ccfsm_state == 2)
7930
      {
7931
        arm_ccfsm_state += 2;
7932
        return \"\";
7933
      }
7934
    return output_return_instruction (const_true_rtx, TRUE, FALSE);
7935
  }"
7936
  [(set_attr "type" "load1")
7937
   (set_attr "length" "12")
7938
   (set_attr "predicable" "yes")]
7939
)
7940
 
7941
(define_insn "*cond_return"
7942
  [(set (pc)
7943
        (if_then_else (match_operator 0 "arm_comparison_operator"
7944
                       [(match_operand 1 "cc_register" "") (const_int 0)])
7945
                      (return)
7946
                      (pc)))]
7947
  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7948
  "*
7949
  {
7950
    if (arm_ccfsm_state == 2)
7951
      {
7952
        arm_ccfsm_state += 2;
7953
        return \"\";
7954
      }
7955
    return output_return_instruction (operands[0], TRUE, FALSE);
7956
  }"
7957
  [(set_attr "conds" "use")
7958
   (set_attr "length" "12")
7959
   (set_attr "type" "load1")]
7960
)
7961
 
7962
(define_insn "*cond_return_inverted"
7963
  [(set (pc)
7964
        (if_then_else (match_operator 0 "arm_comparison_operator"
7965
                       [(match_operand 1 "cc_register" "") (const_int 0)])
7966
                      (pc)
7967
                      (return)))]
7968
  "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7969
  "*
7970
  {
7971
    if (arm_ccfsm_state == 2)
7972
      {
7973
        arm_ccfsm_state += 2;
7974
        return \"\";
7975
      }
7976
    return output_return_instruction (operands[0], TRUE, TRUE);
7977
  }"
7978
  [(set_attr "conds" "use")
7979
   (set_attr "length" "12")
7980
   (set_attr "type" "load1")]
7981
)
7982
 
7983
;; Generate a sequence of instructions to determine if the processor is
7984
;; in 26-bit or 32-bit mode, and return the appropriate return address
7985
;; mask.
7986
 
7987
(define_expand "return_addr_mask"
7988
  [(set (match_dup 1)
7989
      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7990
                       (const_int 0)))
7991
   (set (match_operand:SI 0 "s_register_operand" "")
7992
      (if_then_else:SI (eq (match_dup 1) (const_int 0))
7993
                       (const_int -1)
7994
                       (const_int 67108860)))] ; 0x03fffffc
7995
  "TARGET_ARM"
7996
  "
7997
  operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7998
  ")
7999
 
8000
(define_insn "*check_arch2"
8001
  [(set (match_operand:CC_NOOV 0 "cc_register" "")
8002
      (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8003
                       (const_int 0)))]
8004
  "TARGET_ARM"
8005
  "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8006
  [(set_attr "length" "8")
8007
   (set_attr "conds" "set")]
8008
)
8009
 
8010
;; Call subroutine returning any type.
8011
 
8012
(define_expand "untyped_call"
8013
  [(parallel [(call (match_operand 0 "" "")
8014
                    (const_int 0))
8015
              (match_operand 1 "" "")
8016
              (match_operand 2 "" "")])]
8017
  "TARGET_EITHER"
8018
  "
8019
  {
8020
    int i;
8021
    rtx par = gen_rtx_PARALLEL (VOIDmode,
8022
                                rtvec_alloc (XVECLEN (operands[2], 0)));
8023
    rtx addr = gen_reg_rtx (Pmode);
8024
    rtx mem;
8025
    int size = 0;
8026
 
8027
    emit_move_insn (addr, XEXP (operands[1], 0));
8028
    mem = change_address (operands[1], BLKmode, addr);
8029
 
8030
    for (i = 0; i < XVECLEN (operands[2], 0); i++)
8031
      {
8032
        rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8033
 
8034
        /* Default code only uses r0 as a return value, but we could
8035
           be using anything up to 4 registers.  */
8036
        if (REGNO (src) == R0_REGNUM)
8037
          src = gen_rtx_REG (TImode, R0_REGNUM);
8038
 
8039
        XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8040
                                                 GEN_INT (size));
8041
        size += GET_MODE_SIZE (GET_MODE (src));
8042
      }
8043
 
8044
    emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8045
                                    const0_rtx));
8046
 
8047
    size = 0;
8048
 
8049
    for (i = 0; i < XVECLEN (par, 0); i++)
8050
      {
8051
        HOST_WIDE_INT offset = 0;
8052
        rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8053
 
8054
        if (size != 0)
8055
          emit_move_insn (addr, plus_constant (addr, size));
8056
 
8057
        mem = change_address (mem, GET_MODE (reg), NULL);
8058
        if (REGNO (reg) == R0_REGNUM)
8059
          {
8060
            /* On thumb we have to use a write-back instruction.  */
8061
            emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8062
                        TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8063
            size = TARGET_ARM ? 16 : 0;
8064
          }
8065
        else
8066
          {
8067
            emit_move_insn (mem, reg);
8068
            size = GET_MODE_SIZE (GET_MODE (reg));
8069
          }
8070
      }
8071
 
8072
    /* The optimizer does not know that the call sets the function value
8073
       registers we stored in the result block.  We avoid problems by
8074
       claiming that all hard registers are used and clobbered at this
8075
       point.  */
8076
    emit_insn (gen_blockage ());
8077
 
8078
    DONE;
8079
  }"
8080
)
8081
 
8082
(define_expand "untyped_return"
8083
  [(match_operand:BLK 0 "memory_operand" "")
8084
   (match_operand 1 "" "")]
8085
  "TARGET_EITHER"
8086
  "
8087
  {
8088
    int i;
8089
    rtx addr = gen_reg_rtx (Pmode);
8090
    rtx mem;
8091
    int size = 0;
8092
 
8093
    emit_move_insn (addr, XEXP (operands[0], 0));
8094
    mem = change_address (operands[0], BLKmode, addr);
8095
 
8096
    for (i = 0; i < XVECLEN (operands[1], 0); i++)
8097
      {
8098
        HOST_WIDE_INT offset = 0;
8099
        rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8100
 
8101
        if (size != 0)
8102
          emit_move_insn (addr, plus_constant (addr, size));
8103
 
8104
        mem = change_address (mem, GET_MODE (reg), NULL);
8105
        if (REGNO (reg) == R0_REGNUM)
8106
          {
8107
            /* On thumb we have to use a write-back instruction.  */
8108
            emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8109
                        TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8110
            size = TARGET_ARM ? 16 : 0;
8111
          }
8112
        else
8113
          {
8114
            emit_move_insn (reg, mem);
8115
            size = GET_MODE_SIZE (GET_MODE (reg));
8116
          }
8117
      }
8118
 
8119
    /* Emit USE insns before the return.  */
8120
    for (i = 0; i < XVECLEN (operands[1], 0); i++)
8121
      emit_insn (gen_rtx_USE (VOIDmode,
8122
                              SET_DEST (XVECEXP (operands[1], 0, i))));
8123
 
8124
    /* Construct the return.  */
8125
    expand_naked_return ();
8126
 
8127
    DONE;
8128
  }"
8129
)
8130
 
8131
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8132
;; all of memory.  This blocks insns from being moved across this point.
8133
 
8134
(define_insn "blockage"
8135
  [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8136
  "TARGET_EITHER"
8137
  ""
8138
  [(set_attr "length" "0")
8139
   (set_attr "type" "block")]
8140
)
8141
 
8142
(define_expand "casesi"
8143
  [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8144
   (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8145
   (match_operand:SI 2 "const_int_operand" "")  ; total range
8146
   (match_operand:SI 3 "" "")                   ; table label
8147
   (match_operand:SI 4 "" "")]                  ; Out of range label
8148
  "TARGET_ARM"
8149
  "
8150
  {
8151
    rtx reg;
8152
    if (operands[1] != const0_rtx)
8153
      {
8154
        reg = gen_reg_rtx (SImode);
8155
 
8156
        emit_insn (gen_addsi3 (reg, operands[0],
8157
                               GEN_INT (-INTVAL (operands[1]))));
8158
        operands[0] = reg;
8159
      }
8160
 
8161
    if (!const_ok_for_arm (INTVAL (operands[2])))
8162
      operands[2] = force_reg (SImode, operands[2]);
8163
 
8164
    emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8165
                                         operands[4]));
8166
    DONE;
8167
  }"
8168
)
8169
 
8170
;; The USE in this pattern is needed to tell flow analysis that this is
8171
;; a CASESI insn.  It has no other purpose.
8172
(define_insn "casesi_internal"
8173
  [(parallel [(set (pc)
8174
               (if_then_else
8175
                (leu (match_operand:SI 0 "s_register_operand" "r")
8176
                     (match_operand:SI 1 "arm_rhs_operand" "rI"))
8177
                (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8178
                                 (label_ref (match_operand 2 "" ""))))
8179
                (label_ref (match_operand 3 "" ""))))
8180
              (clobber (reg:CC CC_REGNUM))
8181
              (use (label_ref (match_dup 2)))])]
8182
  "TARGET_ARM"
8183
  "*
8184
    if (flag_pic)
8185
      return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8186
    return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8187
  "
8188
  [(set_attr "conds" "clob")
8189
   (set_attr "length" "12")]
8190
)
8191
 
8192
(define_expand "indirect_jump"
8193
  [(set (pc)
8194
        (match_operand:SI 0 "s_register_operand" ""))]
8195
  "TARGET_EITHER"
8196
  ""
8197
)
8198
 
8199
;; NB Never uses BX.
8200
(define_insn "*arm_indirect_jump"
8201
  [(set (pc)
8202
        (match_operand:SI 0 "s_register_operand" "r"))]
8203
  "TARGET_ARM"
8204
  "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8205
  [(set_attr "predicable" "yes")]
8206
)
8207
 
8208
(define_insn "*load_indirect_jump"
8209
  [(set (pc)
8210
        (match_operand:SI 0 "memory_operand" "m"))]
8211
  "TARGET_ARM"
8212
  "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8213
  [(set_attr "type" "load1")
8214
   (set_attr "pool_range" "4096")
8215
   (set_attr "neg_pool_range" "4084")
8216
   (set_attr "predicable" "yes")]
8217
)
8218
 
8219
;; NB Never uses BX.
8220
(define_insn "*thumb_indirect_jump"
8221
  [(set (pc)
8222
        (match_operand:SI 0 "register_operand" "l*r"))]
8223
  "TARGET_THUMB"
8224
  "mov\\tpc, %0"
8225
  [(set_attr "conds" "clob")
8226
   (set_attr "length" "2")]
8227
)
8228
 
8229
 
8230
;; Misc insns
8231
 
8232
(define_insn "nop"
8233
  [(const_int 0)]
8234
  "TARGET_EITHER"
8235
  "*
8236
  if (TARGET_ARM)
8237
    return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8238
  return  \"mov\\tr8, r8\";
8239
  "
8240
  [(set (attr "length")
8241
        (if_then_else (eq_attr "is_thumb" "yes")
8242
                      (const_int 2)
8243
                      (const_int 4)))]
8244
)
8245
 
8246
 
8247
;; Patterns to allow combination of arithmetic, cond code and shifts
8248
 
8249
(define_insn "*arith_shiftsi"
8250
  [(set (match_operand:SI 0 "s_register_operand" "=r")
8251
        (match_operator:SI 1 "shiftable_operator"
8252
          [(match_operator:SI 3 "shift_operator"
8253
             [(match_operand:SI 4 "s_register_operand" "r")
8254
              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8255
           (match_operand:SI 2 "s_register_operand" "r")]))]
8256
  "TARGET_ARM"
8257
  "%i1%?\\t%0, %2, %4%S3"
8258
  [(set_attr "predicable" "yes")
8259
   (set_attr "shift" "4")
8260
   (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8261
                      (const_string "alu_shift")
8262
                      (const_string "alu_shift_reg")))]
8263
)
8264
 
8265
(define_split
8266
  [(set (match_operand:SI 0 "s_register_operand" "")
8267
        (match_operator:SI 1 "shiftable_operator"
8268
         [(match_operator:SI 2 "shiftable_operator"
8269
           [(match_operator:SI 3 "shift_operator"
8270
             [(match_operand:SI 4 "s_register_operand" "")
8271
              (match_operand:SI 5 "reg_or_int_operand" "")])
8272
            (match_operand:SI 6 "s_register_operand" "")])
8273
          (match_operand:SI 7 "arm_rhs_operand" "")]))
8274
   (clobber (match_operand:SI 8 "s_register_operand" ""))]
8275
  "TARGET_ARM"
8276
  [(set (match_dup 8)
8277
        (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8278
                         (match_dup 6)]))
8279
   (set (match_dup 0)
8280
        (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8281
  "")
8282
 
8283
(define_insn "*arith_shiftsi_compare0"
8284
  [(set (reg:CC_NOOV CC_REGNUM)
8285
        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8286
                          [(match_operator:SI 3 "shift_operator"
8287
                            [(match_operand:SI 4 "s_register_operand" "r")
8288
                             (match_operand:SI 5 "reg_or_int_operand" "rI")])
8289
                           (match_operand:SI 2 "s_register_operand" "r")])
8290
                         (const_int 0)))
8291
   (set (match_operand:SI 0 "s_register_operand" "=r")
8292
        (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8293
                         (match_dup 2)]))]
8294
  "TARGET_ARM"
8295
  "%i1%?s\\t%0, %2, %4%S3"
8296
  [(set_attr "conds" "set")
8297
   (set_attr "shift" "4")
8298
   (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8299
                      (const_string "alu_shift")
8300
                      (const_string "alu_shift_reg")))]
8301
)
8302
 
8303
(define_insn "*arith_shiftsi_compare0_scratch"
8304
  [(set (reg:CC_NOOV CC_REGNUM)
8305
        (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8306
                          [(match_operator:SI 3 "shift_operator"
8307
                            [(match_operand:SI 4 "s_register_operand" "r")
8308
                             (match_operand:SI 5 "reg_or_int_operand" "rI")])
8309
                           (match_operand:SI 2 "s_register_operand" "r")])
8310
                         (const_int 0)))
8311
   (clobber (match_scratch:SI 0 "=r"))]
8312
  "TARGET_ARM"
8313
  "%i1%?s\\t%0, %2, %4%S3"
8314
  [(set_attr "conds" "set")
8315
   (set_attr "shift" "4")
8316
   (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8317
                      (const_string "alu_shift")
8318
                      (const_string "alu_shift_reg")))]
8319
)
8320
 
8321
(define_insn "*sub_shiftsi"
8322
  [(set (match_operand:SI 0 "s_register_operand" "=r")
8323
        (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8324
                  (match_operator:SI 2 "shift_operator"
8325
                   [(match_operand:SI 3 "s_register_operand" "r")
8326
                    (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8327
  "TARGET_ARM"
8328
  "sub%?\\t%0, %1, %3%S2"
8329
  [(set_attr "predicable" "yes")
8330
   (set_attr "shift" "3")
8331
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8332
                      (const_string "alu_shift")
8333
                      (const_string "alu_shift_reg")))]
8334
)
8335
 
8336
(define_insn "*sub_shiftsi_compare0"
8337
  [(set (reg:CC_NOOV CC_REGNUM)
8338
        (compare:CC_NOOV
8339
         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8340
                   (match_operator:SI 2 "shift_operator"
8341
                    [(match_operand:SI 3 "s_register_operand" "r")
8342
                     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8343
         (const_int 0)))
8344
   (set (match_operand:SI 0 "s_register_operand" "=r")
8345
        (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8346
                                                 (match_dup 4)])))]
8347
  "TARGET_ARM"
8348
  "sub%?s\\t%0, %1, %3%S2"
8349
  [(set_attr "conds" "set")
8350
   (set_attr "shift" "3")
8351
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8352
                      (const_string "alu_shift")
8353
                      (const_string "alu_shift_reg")))]
8354
)
8355
 
8356
(define_insn "*sub_shiftsi_compare0_scratch"
8357
  [(set (reg:CC_NOOV CC_REGNUM)
8358
        (compare:CC_NOOV
8359
         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8360
                   (match_operator:SI 2 "shift_operator"
8361
                    [(match_operand:SI 3 "s_register_operand" "r")
8362
                     (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8363
         (const_int 0)))
8364
   (clobber (match_scratch:SI 0 "=r"))]
8365
  "TARGET_ARM"
8366
  "sub%?s\\t%0, %1, %3%S2"
8367
  [(set_attr "conds" "set")
8368
   (set_attr "shift" "3")
8369
   (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8370
                      (const_string "alu_shift")
8371
                      (const_string "alu_shift_reg")))]
8372
)
8373
 
8374
 
8375
 
8376
(define_insn "*and_scc"
8377
  [(set (match_operand:SI 0 "s_register_operand" "=r")
8378
        (and:SI (match_operator:SI 1 "arm_comparison_operator"
8379
                 [(match_operand 3 "cc_register" "") (const_int 0)])
8380
                (match_operand:SI 2 "s_register_operand" "r")))]
8381
  "TARGET_ARM"
8382
  "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8383
  [(set_attr "conds" "use")
8384
   (set_attr "length" "8")]
8385
)
8386
 
8387
(define_insn "*ior_scc"
8388
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8389
        (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8390
                 [(match_operand 3 "cc_register" "") (const_int 0)])
8391
                (match_operand:SI 1 "s_register_operand" "0,?r")))]
8392
  "TARGET_ARM"
8393
  "@
8394
   orr%d2\\t%0, %1, #1
8395
   mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8396
  [(set_attr "conds" "use")
8397
   (set_attr "length" "4,8")]
8398
)
8399
 
8400
(define_insn "*compare_scc"
8401
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8402
        (match_operator:SI 1 "arm_comparison_operator"
8403
         [(match_operand:SI 2 "s_register_operand" "r,r")
8404
          (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8405
   (clobber (reg:CC CC_REGNUM))]
8406
  "TARGET_ARM"
8407
  "*
8408
    if (operands[3] == const0_rtx)
8409
      {
8410
        if (GET_CODE (operands[1]) == LT)
8411
          return \"mov\\t%0, %2, lsr #31\";
8412
 
8413
        if (GET_CODE (operands[1]) == GE)
8414
          return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8415
 
8416
        if (GET_CODE (operands[1]) == EQ)
8417
          return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8418
      }
8419
 
8420
    if (GET_CODE (operands[1]) == NE)
8421
      {
8422
        if (which_alternative == 1)
8423
          return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8424
        return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8425
      }
8426
    if (which_alternative == 1)
8427
      output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8428
    else
8429
      output_asm_insn (\"cmp\\t%2, %3\", operands);
8430
    return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8431
  "
8432
  [(set_attr "conds" "clob")
8433
   (set_attr "length" "12")]
8434
)
8435
 
8436
(define_insn "*cond_move"
8437
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8438
        (if_then_else:SI (match_operator 3 "equality_operator"
8439
                          [(match_operator 4 "arm_comparison_operator"
8440
                            [(match_operand 5 "cc_register" "") (const_int 0)])
8441
                           (const_int 0)])
8442
                         (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8443
                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8444
  "TARGET_ARM"
8445
  "*
8446
    if (GET_CODE (operands[3]) == NE)
8447
      {
8448
        if (which_alternative != 1)
8449
          output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8450
        if (which_alternative != 0)
8451
          output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8452
        return \"\";
8453
      }
8454
    if (which_alternative != 0)
8455
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8456
    if (which_alternative != 1)
8457
      output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8458
    return \"\";
8459
  "
8460
  [(set_attr "conds" "use")
8461
   (set_attr "length" "4,4,8")]
8462
)
8463
 
8464
(define_insn "*cond_arith"
8465
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8466
        (match_operator:SI 5 "shiftable_operator"
8467
         [(match_operator:SI 4 "arm_comparison_operator"
8468
           [(match_operand:SI 2 "s_register_operand" "r,r")
8469
            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8470
          (match_operand:SI 1 "s_register_operand" "0,?r")]))
8471
   (clobber (reg:CC CC_REGNUM))]
8472
  "TARGET_ARM"
8473
  "*
8474
    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8475
      return \"%i5\\t%0, %1, %2, lsr #31\";
8476
 
8477
    output_asm_insn (\"cmp\\t%2, %3\", operands);
8478
    if (GET_CODE (operands[5]) == AND)
8479
      output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8480
    else if (GET_CODE (operands[5]) == MINUS)
8481
      output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8482
    else if (which_alternative != 0)
8483
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8484
    return \"%i5%d4\\t%0, %1, #1\";
8485
  "
8486
  [(set_attr "conds" "clob")
8487
   (set_attr "length" "12")]
8488
)
8489
 
8490
(define_insn "*cond_sub"
8491
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8492
        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8493
                  (match_operator:SI 4 "arm_comparison_operator"
8494
                   [(match_operand:SI 2 "s_register_operand" "r,r")
8495
                    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8496
   (clobber (reg:CC CC_REGNUM))]
8497
  "TARGET_ARM"
8498
  "*
8499
    output_asm_insn (\"cmp\\t%2, %3\", operands);
8500
    if (which_alternative != 0)
8501
      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8502
    return \"sub%d4\\t%0, %1, #1\";
8503
  "
8504
  [(set_attr "conds" "clob")
8505
   (set_attr "length" "8,12")]
8506
)
8507
 
8508
(define_insn "*cmp_ite0"
8509
  [(set (match_operand 6 "dominant_cc_register" "")
8510
        (compare
8511
         (if_then_else:SI
8512
          (match_operator 4 "arm_comparison_operator"
8513
           [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8514
            (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8515
          (match_operator:SI 5 "arm_comparison_operator"
8516
           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8517
            (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8518
          (const_int 0))
8519
         (const_int 0)))]
8520
  "TARGET_ARM"
8521
  "*
8522
  {
8523
    static const char * const opcodes[4][2] =
8524
    {
8525
      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8526
       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8527
      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8528
       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8529
      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8530
       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8531
      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8532
       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8533
    };
8534
    int swap =
8535
      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8536
 
8537
    return opcodes[which_alternative][swap];
8538
  }"
8539
  [(set_attr "conds" "set")
8540
   (set_attr "length" "8")]
8541
)
8542
 
8543
(define_insn "*cmp_ite1"
8544
  [(set (match_operand 6 "dominant_cc_register" "")
8545
        (compare
8546
         (if_then_else:SI
8547
          (match_operator 4 "arm_comparison_operator"
8548
           [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8549
            (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8550
          (match_operator:SI 5 "arm_comparison_operator"
8551
           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8552
            (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8553
          (const_int 1))
8554
         (const_int 0)))]
8555
  "TARGET_ARM"
8556
  "*
8557
  {
8558
    static const char * const opcodes[4][2] =
8559
    {
8560
      {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8561
       \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8562
      {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8563
       \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8564
      {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8565
       \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8566
      {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8567
       \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8568
    };
8569
    int swap =
8570
      comparison_dominates_p (GET_CODE (operands[5]),
8571
                              reverse_condition (GET_CODE (operands[4])));
8572
 
8573
    return opcodes[which_alternative][swap];
8574
  }"
8575
  [(set_attr "conds" "set")
8576
   (set_attr "length" "8")]
8577
)
8578
 
8579
(define_insn "*cmp_and"
8580
  [(set (match_operand 6 "dominant_cc_register" "")
8581
        (compare
8582
         (and:SI
8583
          (match_operator 4 "arm_comparison_operator"
8584
           [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8585
            (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8586
          (match_operator:SI 5 "arm_comparison_operator"
8587
           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8588
            (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8589
         (const_int 0)))]
8590
  "TARGET_ARM"
8591
  "*
8592
  {
8593
    static const char *const opcodes[4][2] =
8594
    {
8595
      {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8596
       \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8597
      {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8598
       \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8599
      {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8600
       \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8601
      {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8602
       \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8603
    };
8604
    int swap =
8605
      comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8606
 
8607
    return opcodes[which_alternative][swap];
8608
  }"
8609
  [(set_attr "conds" "set")
8610
   (set_attr "predicable" "no")
8611
   (set_attr "length" "8")]
8612
)
8613
 
8614
(define_insn "*cmp_ior"
8615
  [(set (match_operand 6 "dominant_cc_register" "")
8616
        (compare
8617
         (ior:SI
8618
          (match_operator 4 "arm_comparison_operator"
8619
           [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8620
            (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8621
          (match_operator:SI 5 "arm_comparison_operator"
8622
           [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8623
            (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8624
         (const_int 0)))]
8625
  "TARGET_ARM"
8626
  "*
8627
{
8628
  static const char *const opcodes[4][2] =
8629
  {
8630
    {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8631
     \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8632
    {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8633
     \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8634
    {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8635
     \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8636
    {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8637
     \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8638
  };
8639
  int swap =
8640
    comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8641
 
8642
  return opcodes[which_alternative][swap];
8643
}
8644
"
8645
  [(set_attr "conds" "set")
8646
   (set_attr "length" "8")]
8647
)
8648
 
8649
(define_insn_and_split "*ior_scc_scc"
8650
  [(set (match_operand:SI 0 "s_register_operand" "=r")
8651
        (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8652
                 [(match_operand:SI 1 "s_register_operand" "r")
8653
                  (match_operand:SI 2 "arm_add_operand" "rIL")])
8654
                (match_operator:SI 6 "arm_comparison_operator"
8655
                 [(match_operand:SI 4 "s_register_operand" "r")
8656
                  (match_operand:SI 5 "arm_add_operand" "rIL")])))
8657
   (clobber (reg:CC CC_REGNUM))]
8658
  "TARGET_ARM
8659
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8660
       != CCmode)"
8661
  "#"
8662
  "TARGET_ARM && reload_completed"
8663
  [(set (match_dup 7)
8664
        (compare
8665
         (ior:SI
8666
          (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8667
          (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8668
         (const_int 0)))
8669
   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8670
  "operands[7]
8671
     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8672
                                                  DOM_CC_X_OR_Y),
8673
                    CC_REGNUM);"
8674
  [(set_attr "conds" "clob")
8675
   (set_attr "length" "16")])
8676
 
8677
; If the above pattern is followed by a CMP insn, then the compare is
8678
; redundant, since we can rework the conditional instruction that follows.
8679
(define_insn_and_split "*ior_scc_scc_cmp"
8680
  [(set (match_operand 0 "dominant_cc_register" "")
8681
        (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8682
                          [(match_operand:SI 1 "s_register_operand" "r")
8683
                           (match_operand:SI 2 "arm_add_operand" "rIL")])
8684
                         (match_operator:SI 6 "arm_comparison_operator"
8685
                          [(match_operand:SI 4 "s_register_operand" "r")
8686
                           (match_operand:SI 5 "arm_add_operand" "rIL")]))
8687
                 (const_int 0)))
8688
   (set (match_operand:SI 7 "s_register_operand" "=r")
8689
        (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8690
                (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8691
  "TARGET_ARM"
8692
  "#"
8693
  "TARGET_ARM && reload_completed"
8694
  [(set (match_dup 0)
8695
        (compare
8696
         (ior:SI
8697
          (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8698
          (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8699
         (const_int 0)))
8700
   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8701
  ""
8702
  [(set_attr "conds" "set")
8703
   (set_attr "length" "16")])
8704
 
8705
(define_insn_and_split "*and_scc_scc"
8706
  [(set (match_operand:SI 0 "s_register_operand" "=r")
8707
        (and:SI (match_operator:SI 3 "arm_comparison_operator"
8708
                 [(match_operand:SI 1 "s_register_operand" "r")
8709
                  (match_operand:SI 2 "arm_add_operand" "rIL")])
8710
                (match_operator:SI 6 "arm_comparison_operator"
8711
                 [(match_operand:SI 4 "s_register_operand" "r")
8712
                  (match_operand:SI 5 "arm_add_operand" "rIL")])))
8713
   (clobber (reg:CC CC_REGNUM))]
8714
  "TARGET_ARM
8715
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8716
       != CCmode)"
8717
  "#"
8718
  "TARGET_ARM && reload_completed
8719
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8720
       != CCmode)"
8721
  [(set (match_dup 7)
8722
        (compare
8723
         (and:SI
8724
          (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8725
          (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8726
         (const_int 0)))
8727
   (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8728
  "operands[7]
8729
     = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8730
                                                  DOM_CC_X_AND_Y),
8731
                    CC_REGNUM);"
8732
  [(set_attr "conds" "clob")
8733
   (set_attr "length" "16")])
8734
 
8735
; If the above pattern is followed by a CMP insn, then the compare is
8736
; redundant, since we can rework the conditional instruction that follows.
8737
(define_insn_and_split "*and_scc_scc_cmp"
8738
  [(set (match_operand 0 "dominant_cc_register" "")
8739
        (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8740
                          [(match_operand:SI 1 "s_register_operand" "r")
8741
                           (match_operand:SI 2 "arm_add_operand" "rIL")])
8742
                         (match_operator:SI 6 "arm_comparison_operator"
8743
                          [(match_operand:SI 4 "s_register_operand" "r")
8744
                           (match_operand:SI 5 "arm_add_operand" "rIL")]))
8745
                 (const_int 0)))
8746
   (set (match_operand:SI 7 "s_register_operand" "=r")
8747
        (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8748
                (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8749
  "TARGET_ARM"
8750
  "#"
8751
  "TARGET_ARM && reload_completed"
8752
  [(set (match_dup 0)
8753
        (compare
8754
         (and:SI
8755
          (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8756
          (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8757
         (const_int 0)))
8758
   (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8759
  ""
8760
  [(set_attr "conds" "set")
8761
   (set_attr "length" "16")])
8762
 
8763
;; If there is no dominance in the comparison, then we can still save an
8764
;; instruction in the AND case, since we can know that the second compare
8765
;; need only zero the value if false (if true, then the value is already
8766
;; correct).
8767
(define_insn_and_split "*and_scc_scc_nodom"
8768
  [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8769
        (and:SI (match_operator:SI 3 "arm_comparison_operator"
8770
                 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8771
                  (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8772
                (match_operator:SI 6 "arm_comparison_operator"
8773
                 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8774
                  (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8775
   (clobber (reg:CC CC_REGNUM))]
8776
  "TARGET_ARM
8777
   && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8778
       == CCmode)"
8779
  "#"
8780
  "TARGET_ARM && reload_completed"
8781
  [(parallel [(set (match_dup 0)
8782
                   (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8783
              (clobber (reg:CC CC_REGNUM))])
8784
   (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8785
   (set (match_dup 0)
8786
        (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8787
                         (match_dup 0)
8788
                         (const_int 0)))]
8789
  "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8790
                                              operands[4], operands[5]),
8791
                              CC_REGNUM);
8792
   operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8793
                                  operands[5]);"
8794
  [(set_attr "conds" "clob")
8795
   (set_attr "length" "20")])
8796
 
8797
(define_split
8798
  [(set (reg:CC_NOOV CC_REGNUM)
8799
        (compare:CC_NOOV (ior:SI
8800
                          (and:SI (match_operand:SI 0 "s_register_operand" "")
8801
                                  (const_int 1))
8802
                          (match_operator:SI 1 "comparison_operator"
8803
                           [(match_operand:SI 2 "s_register_operand" "")
8804
                            (match_operand:SI 3 "arm_add_operand" "")]))
8805
                         (const_int 0)))
8806
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
8807
  "TARGET_ARM"
8808
  [(set (match_dup 4)
8809
        (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8810
                (match_dup 0)))
8811
   (set (reg:CC_NOOV CC_REGNUM)
8812
        (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8813
                         (const_int 0)))]
8814
  "")
8815
 
8816
(define_split
8817
  [(set (reg:CC_NOOV CC_REGNUM)
8818
        (compare:CC_NOOV (ior:SI
8819
                          (match_operator:SI 1 "comparison_operator"
8820
                           [(match_operand:SI 2 "s_register_operand" "")
8821
                            (match_operand:SI 3 "arm_add_operand" "")])
8822
                          (and:SI (match_operand:SI 0 "s_register_operand" "")
8823
                                  (const_int 1)))
8824
                         (const_int 0)))
8825
   (clobber (match_operand:SI 4 "s_register_operand" ""))]
8826
  "TARGET_ARM"
8827
  [(set (match_dup 4)
8828
        (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8829
                (match_dup 0)))
8830
   (set (reg:CC_NOOV CC_REGNUM)
8831
        (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8832
                         (const_int 0)))]
8833
  "")
8834
 
8835
(define_insn "*negscc"
8836
  [(set (match_operand:SI 0 "s_register_operand" "=r")
8837
        (neg:SI (match_operator 3 "arm_comparison_operator"
8838
                 [(match_operand:SI 1 "s_register_operand" "r")
8839
                  (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8840
   (clobber (reg:CC CC_REGNUM))]
8841
  "TARGET_ARM"
8842
  "*
8843
  if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8844
    return \"mov\\t%0, %1, asr #31\";
8845
 
8846
  if (GET_CODE (operands[3]) == NE)
8847
    return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8848
 
8849
  if (GET_CODE (operands[3]) == GT)
8850
    return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8851
 
8852
  output_asm_insn (\"cmp\\t%1, %2\", operands);
8853
  output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8854
  return \"mvn%d3\\t%0, #0\";
8855
  "
8856
  [(set_attr "conds" "clob")
8857
   (set_attr "length" "12")]
8858
)
8859
 
8860
(define_insn "movcond"
8861
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8862
        (if_then_else:SI
8863
         (match_operator 5 "arm_comparison_operator"
8864
          [(match_operand:SI 3 "s_register_operand" "r,r,r")
8865
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8866
         (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8867
         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8868
   (clobber (reg:CC CC_REGNUM))]
8869
  "TARGET_ARM"
8870
  "*
8871
  if (GET_CODE (operands[5]) == LT
8872
      && (operands[4] == const0_rtx))
8873
    {
8874
      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8875
        {
8876
          if (operands[2] == const0_rtx)
8877
            return \"and\\t%0, %1, %3, asr #31\";
8878
          return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8879
        }
8880
      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8881
        {
8882
          if (operands[1] == const0_rtx)
8883
            return \"bic\\t%0, %2, %3, asr #31\";
8884
          return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8885
        }
8886
      /* The only case that falls through to here is when both ops 1 & 2
8887
         are constants.  */
8888
    }
8889
 
8890
  if (GET_CODE (operands[5]) == GE
8891
      && (operands[4] == const0_rtx))
8892
    {
8893
      if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8894
        {
8895
          if (operands[2] == const0_rtx)
8896
            return \"bic\\t%0, %1, %3, asr #31\";
8897
          return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8898
        }
8899
      else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8900
        {
8901
          if (operands[1] == const0_rtx)
8902
            return \"and\\t%0, %2, %3, asr #31\";
8903
          return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8904
        }
8905
      /* The only case that falls through to here is when both ops 1 & 2
8906
         are constants.  */
8907
    }
8908
  if (GET_CODE (operands[4]) == CONST_INT
8909
      && !const_ok_for_arm (INTVAL (operands[4])))
8910
    output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8911
  else
8912
    output_asm_insn (\"cmp\\t%3, %4\", operands);
8913
  if (which_alternative != 0)
8914
    output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8915
  if (which_alternative != 1)
8916
    output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8917
  return \"\";
8918
  "
8919
  [(set_attr "conds" "clob")
8920
   (set_attr "length" "8,8,12")]
8921
)
8922
 
8923
(define_insn "*ifcompare_plus_move"
8924
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8925
        (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8926
                          [(match_operand:SI 4 "s_register_operand" "r,r")
8927
                           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8928
                         (plus:SI
8929
                          (match_operand:SI 2 "s_register_operand" "r,r")
8930
                          (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8931
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8932
   (clobber (reg:CC CC_REGNUM))]
8933
  "TARGET_ARM"
8934
  "#"
8935
  [(set_attr "conds" "clob")
8936
   (set_attr "length" "8,12")]
8937
)
8938
 
8939
(define_insn "*if_plus_move"
8940
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8941
        (if_then_else:SI
8942
         (match_operator 4 "arm_comparison_operator"
8943
          [(match_operand 5 "cc_register" "") (const_int 0)])
8944
         (plus:SI
8945
          (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8946
          (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8947
         (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8948
  "TARGET_ARM"
8949
  "@
8950
   add%d4\\t%0, %2, %3
8951
   sub%d4\\t%0, %2, #%n3
8952
   add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8953
   sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8954
  [(set_attr "conds" "use")
8955
   (set_attr "length" "4,4,8,8")
8956
   (set_attr "type" "*,*,*,*")]
8957
)
8958
 
8959
(define_insn "*ifcompare_move_plus"
8960
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8961
        (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8962
                          [(match_operand:SI 4 "s_register_operand" "r,r")
8963
                           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8964
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8965
                         (plus:SI
8966
                          (match_operand:SI 2 "s_register_operand" "r,r")
8967
                          (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8968
   (clobber (reg:CC CC_REGNUM))]
8969
  "TARGET_ARM"
8970
  "#"
8971
  [(set_attr "conds" "clob")
8972
   (set_attr "length" "8,12")]
8973
)
8974
 
8975
(define_insn "*if_move_plus"
8976
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8977
        (if_then_else:SI
8978
         (match_operator 4 "arm_comparison_operator"
8979
          [(match_operand 5 "cc_register" "") (const_int 0)])
8980
         (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8981
         (plus:SI
8982
          (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8983
          (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8984
  "TARGET_ARM"
8985
  "@
8986
   add%D4\\t%0, %2, %3
8987
   sub%D4\\t%0, %2, #%n3
8988
   add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8989
   sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8990
  [(set_attr "conds" "use")
8991
   (set_attr "length" "4,4,8,8")
8992
   (set_attr "type" "*,*,*,*")]
8993
)
8994
 
8995
(define_insn "*ifcompare_arith_arith"
8996
  [(set (match_operand:SI 0 "s_register_operand" "=r")
8997
        (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8998
                          [(match_operand:SI 5 "s_register_operand" "r")
8999
                           (match_operand:SI 6 "arm_add_operand" "rIL")])
9000
                         (match_operator:SI 8 "shiftable_operator"
9001
                          [(match_operand:SI 1 "s_register_operand" "r")
9002
                           (match_operand:SI 2 "arm_rhs_operand" "rI")])
9003
                         (match_operator:SI 7 "shiftable_operator"
9004
                          [(match_operand:SI 3 "s_register_operand" "r")
9005
                           (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9006
   (clobber (reg:CC CC_REGNUM))]
9007
  "TARGET_ARM"
9008
  "#"
9009
  [(set_attr "conds" "clob")
9010
   (set_attr "length" "12")]
9011
)
9012
 
9013
(define_insn "*if_arith_arith"
9014
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9015
        (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9016
                          [(match_operand 8 "cc_register" "") (const_int 0)])
9017
                         (match_operator:SI 6 "shiftable_operator"
9018
                          [(match_operand:SI 1 "s_register_operand" "r")
9019
                           (match_operand:SI 2 "arm_rhs_operand" "rI")])
9020
                         (match_operator:SI 7 "shiftable_operator"
9021
                          [(match_operand:SI 3 "s_register_operand" "r")
9022
                           (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9023
  "TARGET_ARM"
9024
  "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9025
  [(set_attr "conds" "use")
9026
   (set_attr "length" "8")]
9027
)
9028
 
9029
(define_insn "*ifcompare_arith_move"
9030
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9031
        (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9032
                          [(match_operand:SI 2 "s_register_operand" "r,r")
9033
                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9034
                         (match_operator:SI 7 "shiftable_operator"
9035
                          [(match_operand:SI 4 "s_register_operand" "r,r")
9036
                           (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9037
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9038
   (clobber (reg:CC CC_REGNUM))]
9039
  "TARGET_ARM"
9040
  "*
9041
  /* If we have an operation where (op x 0) is the identity operation and
9042
     the conditional operator is LT or GE and we are comparing against zero and
9043
     everything is in registers then we can do this in two instructions.  */
9044
  if (operands[3] == const0_rtx
9045
      && GET_CODE (operands[7]) != AND
9046
      && GET_CODE (operands[5]) == REG
9047
      && GET_CODE (operands[1]) == REG
9048
      && REGNO (operands[1]) == REGNO (operands[4])
9049
      && REGNO (operands[4]) != REGNO (operands[0]))
9050
    {
9051
      if (GET_CODE (operands[6]) == LT)
9052
        return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9053
      else if (GET_CODE (operands[6]) == GE)
9054
        return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9055
    }
9056
  if (GET_CODE (operands[3]) == CONST_INT
9057
      && !const_ok_for_arm (INTVAL (operands[3])))
9058
    output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9059
  else
9060
    output_asm_insn (\"cmp\\t%2, %3\", operands);
9061
  output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9062
  if (which_alternative != 0)
9063
    return \"mov%D6\\t%0, %1\";
9064
  return \"\";
9065
  "
9066
  [(set_attr "conds" "clob")
9067
   (set_attr "length" "8,12")]
9068
)
9069
 
9070
(define_insn "*if_arith_move"
9071
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9072
        (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9073
                          [(match_operand 6 "cc_register" "") (const_int 0)])
9074
                         (match_operator:SI 5 "shiftable_operator"
9075
                          [(match_operand:SI 2 "s_register_operand" "r,r")
9076
                           (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9077
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9078
  "TARGET_ARM"
9079
  "@
9080
   %I5%d4\\t%0, %2, %3
9081
   %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9082
  [(set_attr "conds" "use")
9083
   (set_attr "length" "4,8")
9084
   (set_attr "type" "*,*")]
9085
)
9086
 
9087
(define_insn "*ifcompare_move_arith"
9088
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9089
        (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9090
                          [(match_operand:SI 4 "s_register_operand" "r,r")
9091
                           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9092
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9093
                         (match_operator:SI 7 "shiftable_operator"
9094
                          [(match_operand:SI 2 "s_register_operand" "r,r")
9095
                           (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9096
   (clobber (reg:CC CC_REGNUM))]
9097
  "TARGET_ARM"
9098
  "*
9099
  /* If we have an operation where (op x 0) is the identity operation and
9100
     the conditional operator is LT or GE and we are comparing against zero and
9101
     everything is in registers then we can do this in two instructions */
9102
  if (operands[5] == const0_rtx
9103
      && GET_CODE (operands[7]) != AND
9104
      && GET_CODE (operands[3]) == REG
9105
      && GET_CODE (operands[1]) == REG
9106
      && REGNO (operands[1]) == REGNO (operands[2])
9107
      && REGNO (operands[2]) != REGNO (operands[0]))
9108
    {
9109
      if (GET_CODE (operands[6]) == GE)
9110
        return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9111
      else if (GET_CODE (operands[6]) == LT)
9112
        return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9113
    }
9114
 
9115
  if (GET_CODE (operands[5]) == CONST_INT
9116
      && !const_ok_for_arm (INTVAL (operands[5])))
9117
    output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9118
  else
9119
    output_asm_insn (\"cmp\\t%4, %5\", operands);
9120
 
9121
  if (which_alternative != 0)
9122
    output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9123
  return \"%I7%D6\\t%0, %2, %3\";
9124
  "
9125
  [(set_attr "conds" "clob")
9126
   (set_attr "length" "8,12")]
9127
)
9128
 
9129
(define_insn "*if_move_arith"
9130
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9131
        (if_then_else:SI
9132
         (match_operator 4 "arm_comparison_operator"
9133
          [(match_operand 6 "cc_register" "") (const_int 0)])
9134
         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9135
         (match_operator:SI 5 "shiftable_operator"
9136
          [(match_operand:SI 2 "s_register_operand" "r,r")
9137
           (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9138
  "TARGET_ARM"
9139
  "@
9140
   %I5%D4\\t%0, %2, %3
9141
   %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9142
  [(set_attr "conds" "use")
9143
   (set_attr "length" "4,8")
9144
   (set_attr "type" "*,*")]
9145
)
9146
 
9147
(define_insn "*ifcompare_move_not"
9148
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9149
        (if_then_else:SI
9150
         (match_operator 5 "arm_comparison_operator"
9151
          [(match_operand:SI 3 "s_register_operand" "r,r")
9152
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9153
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9154
         (not:SI
9155
          (match_operand:SI 2 "s_register_operand" "r,r"))))
9156
   (clobber (reg:CC CC_REGNUM))]
9157
  "TARGET_ARM"
9158
  "#"
9159
  [(set_attr "conds" "clob")
9160
   (set_attr "length" "8,12")]
9161
)
9162
 
9163
(define_insn "*if_move_not"
9164
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9165
        (if_then_else:SI
9166
         (match_operator 4 "arm_comparison_operator"
9167
          [(match_operand 3 "cc_register" "") (const_int 0)])
9168
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9169
         (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9170
  "TARGET_ARM"
9171
  "@
9172
   mvn%D4\\t%0, %2
9173
   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9174
   mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9175
  [(set_attr "conds" "use")
9176
   (set_attr "length" "4,8,8")]
9177
)
9178
 
9179
(define_insn "*ifcompare_not_move"
9180
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9181
        (if_then_else:SI
9182
         (match_operator 5 "arm_comparison_operator"
9183
          [(match_operand:SI 3 "s_register_operand" "r,r")
9184
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9185
         (not:SI
9186
          (match_operand:SI 2 "s_register_operand" "r,r"))
9187
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9188
   (clobber (reg:CC CC_REGNUM))]
9189
  "TARGET_ARM"
9190
  "#"
9191
  [(set_attr "conds" "clob")
9192
   (set_attr "length" "8,12")]
9193
)
9194
 
9195
(define_insn "*if_not_move"
9196
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9197
        (if_then_else:SI
9198
         (match_operator 4 "arm_comparison_operator"
9199
          [(match_operand 3 "cc_register" "") (const_int 0)])
9200
         (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9201
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9202
  "TARGET_ARM"
9203
  "@
9204
   mvn%d4\\t%0, %2
9205
   mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9206
   mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9207
  [(set_attr "conds" "use")
9208
   (set_attr "length" "4,8,8")]
9209
)
9210
 
9211
(define_insn "*ifcompare_shift_move"
9212
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9213
        (if_then_else:SI
9214
         (match_operator 6 "arm_comparison_operator"
9215
          [(match_operand:SI 4 "s_register_operand" "r,r")
9216
           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9217
         (match_operator:SI 7 "shift_operator"
9218
          [(match_operand:SI 2 "s_register_operand" "r,r")
9219
           (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9220
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9221
   (clobber (reg:CC CC_REGNUM))]
9222
  "TARGET_ARM"
9223
  "#"
9224
  [(set_attr "conds" "clob")
9225
   (set_attr "length" "8,12")]
9226
)
9227
 
9228
(define_insn "*if_shift_move"
9229
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9230
        (if_then_else:SI
9231
         (match_operator 5 "arm_comparison_operator"
9232
          [(match_operand 6 "cc_register" "") (const_int 0)])
9233
         (match_operator:SI 4 "shift_operator"
9234
          [(match_operand:SI 2 "s_register_operand" "r,r,r")
9235
           (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9236
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9237
  "TARGET_ARM"
9238
  "@
9239
   mov%d5\\t%0, %2%S4
9240
   mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9241
   mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9242
  [(set_attr "conds" "use")
9243
   (set_attr "shift" "2")
9244
   (set_attr "length" "4,8,8")
9245
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9246
                      (const_string "alu_shift")
9247
                      (const_string "alu_shift_reg")))]
9248
)
9249
 
9250
(define_insn "*ifcompare_move_shift"
9251
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9252
        (if_then_else:SI
9253
         (match_operator 6 "arm_comparison_operator"
9254
          [(match_operand:SI 4 "s_register_operand" "r,r")
9255
           (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9256
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9257
         (match_operator:SI 7 "shift_operator"
9258
          [(match_operand:SI 2 "s_register_operand" "r,r")
9259
           (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9260
   (clobber (reg:CC CC_REGNUM))]
9261
  "TARGET_ARM"
9262
  "#"
9263
  [(set_attr "conds" "clob")
9264
   (set_attr "length" "8,12")]
9265
)
9266
 
9267
(define_insn "*if_move_shift"
9268
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9269
        (if_then_else:SI
9270
         (match_operator 5 "arm_comparison_operator"
9271
          [(match_operand 6 "cc_register" "") (const_int 0)])
9272
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9273
         (match_operator:SI 4 "shift_operator"
9274
          [(match_operand:SI 2 "s_register_operand" "r,r,r")
9275
           (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9276
  "TARGET_ARM"
9277
  "@
9278
   mov%D5\\t%0, %2%S4
9279
   mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9280
   mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9281
  [(set_attr "conds" "use")
9282
   (set_attr "shift" "2")
9283
   (set_attr "length" "4,8,8")
9284
   (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9285
                      (const_string "alu_shift")
9286
                      (const_string "alu_shift_reg")))]
9287
)
9288
 
9289
(define_insn "*ifcompare_shift_shift"
9290
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9291
        (if_then_else:SI
9292
         (match_operator 7 "arm_comparison_operator"
9293
          [(match_operand:SI 5 "s_register_operand" "r")
9294
           (match_operand:SI 6 "arm_add_operand" "rIL")])
9295
         (match_operator:SI 8 "shift_operator"
9296
          [(match_operand:SI 1 "s_register_operand" "r")
9297
           (match_operand:SI 2 "arm_rhs_operand" "rM")])
9298
         (match_operator:SI 9 "shift_operator"
9299
          [(match_operand:SI 3 "s_register_operand" "r")
9300
           (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9301
   (clobber (reg:CC CC_REGNUM))]
9302
  "TARGET_ARM"
9303
  "#"
9304
  [(set_attr "conds" "clob")
9305
   (set_attr "length" "12")]
9306
)
9307
 
9308
(define_insn "*if_shift_shift"
9309
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9310
        (if_then_else:SI
9311
         (match_operator 5 "arm_comparison_operator"
9312
          [(match_operand 8 "cc_register" "") (const_int 0)])
9313
         (match_operator:SI 6 "shift_operator"
9314
          [(match_operand:SI 1 "s_register_operand" "r")
9315
           (match_operand:SI 2 "arm_rhs_operand" "rM")])
9316
         (match_operator:SI 7 "shift_operator"
9317
          [(match_operand:SI 3 "s_register_operand" "r")
9318
           (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9319
  "TARGET_ARM"
9320
  "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9321
  [(set_attr "conds" "use")
9322
   (set_attr "shift" "1")
9323
   (set_attr "length" "8")
9324
   (set (attr "type") (if_then_else
9325
                        (and (match_operand 2 "const_int_operand" "")
9326
                             (match_operand 4 "const_int_operand" ""))
9327
                      (const_string "alu_shift")
9328
                      (const_string "alu_shift_reg")))]
9329
)
9330
 
9331
(define_insn "*ifcompare_not_arith"
9332
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9333
        (if_then_else:SI
9334
         (match_operator 6 "arm_comparison_operator"
9335
          [(match_operand:SI 4 "s_register_operand" "r")
9336
           (match_operand:SI 5 "arm_add_operand" "rIL")])
9337
         (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9338
         (match_operator:SI 7 "shiftable_operator"
9339
          [(match_operand:SI 2 "s_register_operand" "r")
9340
           (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9341
   (clobber (reg:CC CC_REGNUM))]
9342
  "TARGET_ARM"
9343
  "#"
9344
  [(set_attr "conds" "clob")
9345
   (set_attr "length" "12")]
9346
)
9347
 
9348
(define_insn "*if_not_arith"
9349
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9350
        (if_then_else:SI
9351
         (match_operator 5 "arm_comparison_operator"
9352
          [(match_operand 4 "cc_register" "") (const_int 0)])
9353
         (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9354
         (match_operator:SI 6 "shiftable_operator"
9355
          [(match_operand:SI 2 "s_register_operand" "r")
9356
           (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9357
  "TARGET_ARM"
9358
  "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9359
  [(set_attr "conds" "use")
9360
   (set_attr "length" "8")]
9361
)
9362
 
9363
(define_insn "*ifcompare_arith_not"
9364
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9365
        (if_then_else:SI
9366
         (match_operator 6 "arm_comparison_operator"
9367
          [(match_operand:SI 4 "s_register_operand" "r")
9368
           (match_operand:SI 5 "arm_add_operand" "rIL")])
9369
         (match_operator:SI 7 "shiftable_operator"
9370
          [(match_operand:SI 2 "s_register_operand" "r")
9371
           (match_operand:SI 3 "arm_rhs_operand" "rI")])
9372
         (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9373
   (clobber (reg:CC CC_REGNUM))]
9374
  "TARGET_ARM"
9375
  "#"
9376
  [(set_attr "conds" "clob")
9377
   (set_attr "length" "12")]
9378
)
9379
 
9380
(define_insn "*if_arith_not"
9381
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9382
        (if_then_else:SI
9383
         (match_operator 5 "arm_comparison_operator"
9384
          [(match_operand 4 "cc_register" "") (const_int 0)])
9385
         (match_operator:SI 6 "shiftable_operator"
9386
          [(match_operand:SI 2 "s_register_operand" "r")
9387
           (match_operand:SI 3 "arm_rhs_operand" "rI")])
9388
         (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9389
  "TARGET_ARM"
9390
  "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9391
  [(set_attr "conds" "use")
9392
   (set_attr "length" "8")]
9393
)
9394
 
9395
(define_insn "*ifcompare_neg_move"
9396
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9397
        (if_then_else:SI
9398
         (match_operator 5 "arm_comparison_operator"
9399
          [(match_operand:SI 3 "s_register_operand" "r,r")
9400
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9401
         (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9402
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9403
   (clobber (reg:CC CC_REGNUM))]
9404
  "TARGET_ARM"
9405
  "#"
9406
  [(set_attr "conds" "clob")
9407
   (set_attr "length" "8,12")]
9408
)
9409
 
9410
(define_insn "*if_neg_move"
9411
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9412
        (if_then_else:SI
9413
         (match_operator 4 "arm_comparison_operator"
9414
          [(match_operand 3 "cc_register" "") (const_int 0)])
9415
         (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9416
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9417
  "TARGET_ARM"
9418
  "@
9419
   rsb%d4\\t%0, %2, #0
9420
   mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9421
   mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9422
  [(set_attr "conds" "use")
9423
   (set_attr "length" "4,8,8")]
9424
)
9425
 
9426
(define_insn "*ifcompare_move_neg"
9427
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9428
        (if_then_else:SI
9429
         (match_operator 5 "arm_comparison_operator"
9430
          [(match_operand:SI 3 "s_register_operand" "r,r")
9431
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9432
         (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9433
         (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9434
   (clobber (reg:CC CC_REGNUM))]
9435
  "TARGET_ARM"
9436
  "#"
9437
  [(set_attr "conds" "clob")
9438
   (set_attr "length" "8,12")]
9439
)
9440
 
9441
(define_insn "*if_move_neg"
9442
  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9443
        (if_then_else:SI
9444
         (match_operator 4 "arm_comparison_operator"
9445
          [(match_operand 3 "cc_register" "") (const_int 0)])
9446
         (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9447
         (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9448
  "TARGET_ARM"
9449
  "@
9450
   rsb%D4\\t%0, %2, #0
9451
   mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9452
   mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9453
  [(set_attr "conds" "use")
9454
   (set_attr "length" "4,8,8")]
9455
)
9456
 
9457
(define_insn "*arith_adjacentmem"
9458
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9459
        (match_operator:SI 1 "shiftable_operator"
9460
         [(match_operand:SI 2 "memory_operand" "m")
9461
          (match_operand:SI 3 "memory_operand" "m")]))
9462
   (clobber (match_scratch:SI 4 "=r"))]
9463
  "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9464
  "*
9465
  {
9466
    rtx ldm[3];
9467
    rtx arith[4];
9468
    rtx base_reg;
9469
    HOST_WIDE_INT val1 = 0, val2 = 0;
9470
 
9471
    if (REGNO (operands[0]) > REGNO (operands[4]))
9472
      {
9473
        ldm[1] = operands[4];
9474
        ldm[2] = operands[0];
9475
      }
9476
    else
9477
      {
9478
        ldm[1] = operands[0];
9479
        ldm[2] = operands[4];
9480
      }
9481
 
9482
    base_reg = XEXP (operands[2], 0);
9483
 
9484
    if (!REG_P (base_reg))
9485
      {
9486
        val1 = INTVAL (XEXP (base_reg, 1));
9487
        base_reg = XEXP (base_reg, 0);
9488
      }
9489
 
9490
    if (!REG_P (XEXP (operands[3], 0)))
9491
      val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9492
 
9493
    arith[0] = operands[0];
9494
    arith[3] = operands[1];
9495
 
9496
    if (val1 < val2)
9497
      {
9498
        arith[1] = ldm[1];
9499
        arith[2] = ldm[2];
9500
      }
9501
    else
9502
      {
9503
        arith[1] = ldm[2];
9504
        arith[2] = ldm[1];
9505
      }
9506
 
9507
    ldm[0] = base_reg;
9508
    if (val1 !=0 && val2 != 0)
9509
      {
9510
        rtx ops[3];
9511
 
9512
        if (val1 == 4 || val2 == 4)
9513
          /* Other val must be 8, since we know they are adjacent and neither
9514
             is zero.  */
9515
          output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9516
        else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
9517
          {
9518
            ldm[0] = ops[0] = operands[4];
9519
            ops[1] = base_reg;
9520
            ops[2] = GEN_INT (val1);
9521
            output_add_immediate (ops);
9522
            if (val1 < val2)
9523
              output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9524
            else
9525
              output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9526
          }
9527
        else
9528
          {
9529
            /* Offset is out of range for a single add, so use two ldr.  */
9530
            ops[0] = ldm[1];
9531
            ops[1] = base_reg;
9532
            ops[2] = GEN_INT (val1);
9533
            output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9534
            ops[0] = ldm[2];
9535
            ops[2] = GEN_INT (val2);
9536
            output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9537
          }
9538
      }
9539
    else if (val1 != 0)
9540
      {
9541
        if (val1 < val2)
9542
          output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9543
        else
9544
          output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9545
      }
9546
    else
9547
      {
9548
        if (val1 < val2)
9549
          output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9550
        else
9551
          output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9552
      }
9553
    output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9554
    return \"\";
9555
  }"
9556
  [(set_attr "length" "12")
9557
   (set_attr "predicable" "yes")
9558
   (set_attr "type" "load1")]
9559
)
9560
 
9561
; This pattern is never tried by combine, so do it as a peephole
9562
 
9563
(define_peephole2
9564
  [(set (match_operand:SI 0 "arm_general_register_operand" "")
9565
        (match_operand:SI 1 "arm_general_register_operand" ""))
9566
   (set (reg:CC CC_REGNUM)
9567
        (compare:CC (match_dup 1) (const_int 0)))]
9568
  "TARGET_ARM"
9569
  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9570
              (set (match_dup 0) (match_dup 1))])]
9571
  ""
9572
)
9573
 
9574
; Peepholes to spot possible load- and store-multiples, if the ordering is
9575
; reversed, check that the memory references aren't volatile.
9576
 
9577
(define_peephole
9578
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9579
        (match_operand:SI 4 "memory_operand" "m"))
9580
   (set (match_operand:SI 1 "s_register_operand" "=r")
9581
        (match_operand:SI 5 "memory_operand" "m"))
9582
   (set (match_operand:SI 2 "s_register_operand" "=r")
9583
        (match_operand:SI 6 "memory_operand" "m"))
9584
   (set (match_operand:SI 3 "s_register_operand" "=r")
9585
        (match_operand:SI 7 "memory_operand" "m"))]
9586
  "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9587
  "*
9588
  return emit_ldm_seq (operands, 4);
9589
  "
9590
)
9591
 
9592
(define_peephole
9593
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9594
        (match_operand:SI 3 "memory_operand" "m"))
9595
   (set (match_operand:SI 1 "s_register_operand" "=r")
9596
        (match_operand:SI 4 "memory_operand" "m"))
9597
   (set (match_operand:SI 2 "s_register_operand" "=r")
9598
        (match_operand:SI 5 "memory_operand" "m"))]
9599
  "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9600
  "*
9601
  return emit_ldm_seq (operands, 3);
9602
  "
9603
)
9604
 
9605
(define_peephole
9606
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9607
        (match_operand:SI 2 "memory_operand" "m"))
9608
   (set (match_operand:SI 1 "s_register_operand" "=r")
9609
        (match_operand:SI 3 "memory_operand" "m"))]
9610
  "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9611
  "*
9612
  return emit_ldm_seq (operands, 2);
9613
  "
9614
)
9615
 
9616
(define_peephole
9617
  [(set (match_operand:SI 4 "memory_operand" "=m")
9618
        (match_operand:SI 0 "s_register_operand" "r"))
9619
   (set (match_operand:SI 5 "memory_operand" "=m")
9620
        (match_operand:SI 1 "s_register_operand" "r"))
9621
   (set (match_operand:SI 6 "memory_operand" "=m")
9622
        (match_operand:SI 2 "s_register_operand" "r"))
9623
   (set (match_operand:SI 7 "memory_operand" "=m")
9624
        (match_operand:SI 3 "s_register_operand" "r"))]
9625
  "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9626
  "*
9627
  return emit_stm_seq (operands, 4);
9628
  "
9629
)
9630
 
9631
(define_peephole
9632
  [(set (match_operand:SI 3 "memory_operand" "=m")
9633
        (match_operand:SI 0 "s_register_operand" "r"))
9634
   (set (match_operand:SI 4 "memory_operand" "=m")
9635
        (match_operand:SI 1 "s_register_operand" "r"))
9636
   (set (match_operand:SI 5 "memory_operand" "=m")
9637
        (match_operand:SI 2 "s_register_operand" "r"))]
9638
  "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9639
  "*
9640
  return emit_stm_seq (operands, 3);
9641
  "
9642
)
9643
 
9644
(define_peephole
9645
  [(set (match_operand:SI 2 "memory_operand" "=m")
9646
        (match_operand:SI 0 "s_register_operand" "r"))
9647
   (set (match_operand:SI 3 "memory_operand" "=m")
9648
        (match_operand:SI 1 "s_register_operand" "r"))]
9649
  "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9650
  "*
9651
  return emit_stm_seq (operands, 2);
9652
  "
9653
)
9654
 
9655
(define_split
9656
  [(set (match_operand:SI 0 "s_register_operand" "")
9657
        (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9658
                       (const_int 0))
9659
                (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9660
                         [(match_operand:SI 3 "s_register_operand" "")
9661
                          (match_operand:SI 4 "arm_rhs_operand" "")]))))
9662
   (clobber (match_operand:SI 5 "s_register_operand" ""))]
9663
  "TARGET_ARM"
9664
  [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9665
   (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9666
                              (match_dup 5)))]
9667
  ""
9668
)
9669
 
9670
;; This split can be used because CC_Z mode implies that the following
9671
;; branch will be an equality, or an unsigned inequality, so the sign
9672
;; extension is not needed.
9673
 
9674
(define_split
9675
  [(set (reg:CC_Z CC_REGNUM)
9676
        (compare:CC_Z
9677
         (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9678
                    (const_int 24))
9679
         (match_operand 1 "const_int_operand" "")))
9680
   (clobber (match_scratch:SI 2 ""))]
9681
  "TARGET_ARM
9682
   && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9683
       == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9684
  [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9685
   (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9686
  "
9687
  operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9688
  "
9689
)
9690
 
9691
(define_expand "prologue"
9692
  [(clobber (const_int 0))]
9693
  "TARGET_EITHER"
9694
  "if (TARGET_ARM)
9695
     arm_expand_prologue ();
9696
   else
9697
     thumb_expand_prologue ();
9698
  DONE;
9699
  "
9700
)
9701
 
9702
(define_expand "epilogue"
9703
  [(clobber (const_int 0))]
9704
  "TARGET_EITHER"
9705
  "
9706
  if (current_function_calls_eh_return)
9707
    emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9708
  if (TARGET_THUMB)
9709
    thumb_expand_epilogue ();
9710
  else if (USE_RETURN_INSN (FALSE))
9711
    {
9712
      emit_jump_insn (gen_return ());
9713
      DONE;
9714
    }
9715
  emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9716
        gen_rtvec (1,
9717
                gen_rtx_RETURN (VOIDmode)),
9718
        VUNSPEC_EPILOGUE));
9719
  DONE;
9720
  "
9721
)
9722
 
9723
;; Note - although unspec_volatile's USE all hard registers,
9724
;; USEs are ignored after relaod has completed.  Thus we need
9725
;; to add an unspec of the link register to ensure that flow
9726
;; does not think that it is unused by the sibcall branch that
9727
;; will replace the standard function epilogue.
9728
(define_insn "sibcall_epilogue"
9729
  [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9730
              (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9731
  "TARGET_ARM"
9732
  "*
9733
  if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9734
    return output_return_instruction (const_true_rtx, FALSE, FALSE);
9735
  return arm_output_epilogue (next_nonnote_insn (insn));
9736
  "
9737
;; Length is absolute worst case
9738
  [(set_attr "length" "44")
9739
   (set_attr "type" "block")
9740
   ;; We don't clobber the conditions, but the potential length of this
9741
   ;; operation is sufficient to make conditionalizing the sequence
9742
   ;; unlikely to be profitable.
9743
   (set_attr "conds" "clob")]
9744
)
9745
 
9746
(define_insn "*epilogue_insns"
9747
  [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9748
  "TARGET_EITHER"
9749
  "*
9750
  if (TARGET_ARM)
9751
    return arm_output_epilogue (NULL);
9752
  else /* TARGET_THUMB */
9753
    return thumb_unexpanded_epilogue ();
9754
  "
9755
  ; Length is absolute worst case
9756
  [(set_attr "length" "44")
9757
   (set_attr "type" "block")
9758
   ;; We don't clobber the conditions, but the potential length of this
9759
   ;; operation is sufficient to make conditionalizing the sequence
9760
   ;; unlikely to be profitable.
9761
   (set_attr "conds" "clob")]
9762
)
9763
 
9764
(define_expand "eh_epilogue"
9765
  [(use (match_operand:SI 0 "register_operand" ""))
9766
   (use (match_operand:SI 1 "register_operand" ""))
9767
   (use (match_operand:SI 2 "register_operand" ""))]
9768
  "TARGET_EITHER"
9769
  "
9770
  {
9771
    cfun->machine->eh_epilogue_sp_ofs = operands[1];
9772
    if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9773
      {
9774
        rtx ra = gen_rtx_REG (Pmode, 2);
9775
 
9776
        emit_move_insn (ra, operands[2]);
9777
        operands[2] = ra;
9778
      }
9779
    /* This is a hack -- we may have crystalized the function type too
9780
       early.  */
9781
    cfun->machine->func_type = 0;
9782
  }"
9783
)
9784
 
9785
;; This split is only used during output to reduce the number of patterns
9786
;; that need assembler instructions adding to them.  We allowed the setting
9787
;; of the conditions to be implicit during rtl generation so that
9788
;; the conditional compare patterns would work.  However this conflicts to
9789
;; some extent with the conditional data operations, so we have to split them
9790
;; up again here.
9791
 
9792
(define_split
9793
  [(set (match_operand:SI 0 "s_register_operand" "")
9794
        (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9795
                          [(match_operand 2 "" "") (match_operand 3 "" "")])
9796
                         (match_dup 0)
9797
                         (match_operand 4 "" "")))
9798
   (clobber (reg:CC CC_REGNUM))]
9799
  "TARGET_ARM && reload_completed"
9800
  [(set (match_dup 5) (match_dup 6))
9801
   (cond_exec (match_dup 7)
9802
              (set (match_dup 0) (match_dup 4)))]
9803
  "
9804
  {
9805
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9806
                                             operands[2], operands[3]);
9807
    enum rtx_code rc = GET_CODE (operands[1]);
9808
 
9809
    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9810
    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9811
    if (mode == CCFPmode || mode == CCFPEmode)
9812
      rc = reverse_condition_maybe_unordered (rc);
9813
    else
9814
      rc = reverse_condition (rc);
9815
 
9816
    operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9817
  }"
9818
)
9819
 
9820
(define_split
9821
  [(set (match_operand:SI 0 "s_register_operand" "")
9822
        (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9823
                          [(match_operand 2 "" "") (match_operand 3 "" "")])
9824
                         (match_operand 4 "" "")
9825
                         (match_dup 0)))
9826
   (clobber (reg:CC CC_REGNUM))]
9827
  "TARGET_ARM && reload_completed"
9828
  [(set (match_dup 5) (match_dup 6))
9829
   (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9830
              (set (match_dup 0) (match_dup 4)))]
9831
  "
9832
  {
9833
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9834
                                             operands[2], operands[3]);
9835
 
9836
    operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9837
    operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9838
  }"
9839
)
9840
 
9841
(define_split
9842
  [(set (match_operand:SI 0 "s_register_operand" "")
9843
        (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9844
                          [(match_operand 2 "" "") (match_operand 3 "" "")])
9845
                         (match_operand 4 "" "")
9846
                         (match_operand 5 "" "")))
9847
   (clobber (reg:CC CC_REGNUM))]
9848
  "TARGET_ARM && reload_completed"
9849
  [(set (match_dup 6) (match_dup 7))
9850
   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9851
              (set (match_dup 0) (match_dup 4)))
9852
   (cond_exec (match_dup 8)
9853
              (set (match_dup 0) (match_dup 5)))]
9854
  "
9855
  {
9856
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9857
                                             operands[2], operands[3]);
9858
    enum rtx_code rc = GET_CODE (operands[1]);
9859
 
9860
    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9861
    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9862
    if (mode == CCFPmode || mode == CCFPEmode)
9863
      rc = reverse_condition_maybe_unordered (rc);
9864
    else
9865
      rc = reverse_condition (rc);
9866
 
9867
    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9868
  }"
9869
)
9870
 
9871
(define_split
9872
  [(set (match_operand:SI 0 "s_register_operand" "")
9873
        (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9874
                          [(match_operand:SI 2 "s_register_operand" "")
9875
                           (match_operand:SI 3 "arm_add_operand" "")])
9876
                         (match_operand:SI 4 "arm_rhs_operand" "")
9877
                         (not:SI
9878
                          (match_operand:SI 5 "s_register_operand" ""))))
9879
   (clobber (reg:CC CC_REGNUM))]
9880
  "TARGET_ARM && reload_completed"
9881
  [(set (match_dup 6) (match_dup 7))
9882
   (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9883
              (set (match_dup 0) (match_dup 4)))
9884
   (cond_exec (match_dup 8)
9885
              (set (match_dup 0) (not:SI (match_dup 5))))]
9886
  "
9887
  {
9888
    enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9889
                                             operands[2], operands[3]);
9890
    enum rtx_code rc = GET_CODE (operands[1]);
9891
 
9892
    operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9893
    operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9894
    if (mode == CCFPmode || mode == CCFPEmode)
9895
      rc = reverse_condition_maybe_unordered (rc);
9896
    else
9897
      rc = reverse_condition (rc);
9898
 
9899
    operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9900
  }"
9901
)
9902
 
9903
(define_insn "*cond_move_not"
9904
  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9905
        (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9906
                          [(match_operand 3 "cc_register" "") (const_int 0)])
9907
                         (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9908
                         (not:SI
9909
                          (match_operand:SI 2 "s_register_operand" "r,r"))))]
9910
  "TARGET_ARM"
9911
  "@
9912
   mvn%D4\\t%0, %2
9913
   mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9914
  [(set_attr "conds" "use")
9915
   (set_attr "length" "4,8")]
9916
)
9917
 
9918
;; The next two patterns occur when an AND operation is followed by a
9919
;; scc insn sequence
9920
 
9921
(define_insn "*sign_extract_onebit"
9922
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9923
        (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9924
                         (const_int 1)
9925
                         (match_operand:SI 2 "const_int_operand" "n")))
9926
    (clobber (reg:CC CC_REGNUM))]
9927
  "TARGET_ARM"
9928
  "*
9929
    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9930
    output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9931
    return \"mvnne\\t%0, #0\";
9932
  "
9933
  [(set_attr "conds" "clob")
9934
   (set_attr "length" "8")]
9935
)
9936
 
9937
(define_insn "*not_signextract_onebit"
9938
  [(set (match_operand:SI 0 "s_register_operand" "=r")
9939
        (not:SI
9940
         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9941
                          (const_int 1)
9942
                          (match_operand:SI 2 "const_int_operand" "n"))))
9943
   (clobber (reg:CC CC_REGNUM))]
9944
  "TARGET_ARM"
9945
  "*
9946
    operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9947
    output_asm_insn (\"tst\\t%1, %2\", operands);
9948
    output_asm_insn (\"mvneq\\t%0, #0\", operands);
9949
    return \"movne\\t%0, #0\";
9950
  "
9951
  [(set_attr "conds" "clob")
9952
   (set_attr "length" "12")]
9953
)
9954
 
9955
;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9956
;; expressions.  For simplicity, the first register is also in the unspec
9957
;; part.
9958
(define_insn "*push_multi"
9959
  [(match_parallel 2 "multi_register_push"
9960
    [(set (match_operand:BLK 0 "memory_operand" "=m")
9961
          (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9962
                      UNSPEC_PUSH_MULT))])]
9963
  "TARGET_ARM"
9964
  "*
9965
  {
9966
    int num_saves = XVECLEN (operands[2], 0);
9967
 
9968
    /* For the StrongARM at least it is faster to
9969
       use STR to store only a single register.  */
9970
    if (num_saves == 1)
9971
      output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9972
    else
9973
      {
9974
        int i;
9975
        char pattern[100];
9976
 
9977
        strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9978
 
9979
        for (i = 1; i < num_saves; i++)
9980
          {
9981
            strcat (pattern, \", %|\");
9982
            strcat (pattern,
9983
                    reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9984
          }
9985
 
9986
        strcat (pattern, \"}\");
9987
        output_asm_insn (pattern, operands);
9988
      }
9989
 
9990
    return \"\";
9991
  }"
9992
  [(set_attr "type" "store4")]
9993
)
9994
 
9995
(define_insn "stack_tie"
9996
  [(set (mem:BLK (scratch))
9997
        (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9998
                     (match_operand:SI 1 "s_register_operand" "r")]
9999
                    UNSPEC_PRLG_STK))]
10000
  ""
10001
  ""
10002
  [(set_attr "length" "0")]
10003
)
10004
 
10005
;; Similarly for the floating point registers
10006
(define_insn "*push_fp_multi"
10007
  [(match_parallel 2 "multi_register_push"
10008
    [(set (match_operand:BLK 0 "memory_operand" "=m")
10009
          (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10010
                      UNSPEC_PUSH_MULT))])]
10011
  "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10012
  "*
10013
  {
10014
    char pattern[100];
10015
 
10016
    sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10017
    output_asm_insn (pattern, operands);
10018
    return \"\";
10019
  }"
10020
  [(set_attr "type" "f_store")]
10021
)
10022
 
10023
;; Special patterns for dealing with the constant pool
10024
 
10025
(define_insn "align_4"
10026
  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10027
  "TARGET_EITHER"
10028
  "*
10029
  assemble_align (32);
10030
  return \"\";
10031
  "
10032
)
10033
 
10034
(define_insn "align_8"
10035
  [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10036
  "TARGET_EITHER"
10037
  "*
10038
  assemble_align (64);
10039
  return \"\";
10040
  "
10041
)
10042
 
10043
(define_insn "consttable_end"
10044
  [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10045
  "TARGET_EITHER"
10046
  "*
10047
  making_const_table = FALSE;
10048
  return \"\";
10049
  "
10050
)
10051
 
10052
(define_insn "consttable_1"
10053
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10054
  "TARGET_THUMB"
10055
  "*
10056
  making_const_table = TRUE;
10057
  assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10058
  assemble_zeros (3);
10059
  return \"\";
10060
  "
10061
  [(set_attr "length" "4")]
10062
)
10063
 
10064
(define_insn "consttable_2"
10065
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10066
  "TARGET_THUMB"
10067
  "*
10068
  making_const_table = TRUE;
10069
  assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10070
  assemble_zeros (2);
10071
  return \"\";
10072
  "
10073
  [(set_attr "length" "4")]
10074
)
10075
 
10076
(define_insn "consttable_4"
10077
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10078
  "TARGET_EITHER"
10079
  "*
10080
  {
10081
    making_const_table = TRUE;
10082
    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10083
      {
10084
      case MODE_FLOAT:
10085
      {
10086
        REAL_VALUE_TYPE r;
10087
        REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10088
        assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10089
        break;
10090
      }
10091
      default:
10092
        assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10093
        break;
10094
      }
10095
    return \"\";
10096
  }"
10097
  [(set_attr "length" "4")]
10098
)
10099
 
10100
(define_insn "consttable_8"
10101
  [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10102
  "TARGET_EITHER"
10103
  "*
10104
  {
10105
    making_const_table = TRUE;
10106
    switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10107
      {
10108
       case MODE_FLOAT:
10109
        {
10110
          REAL_VALUE_TYPE r;
10111
          REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10112
          assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10113
          break;
10114
        }
10115
      default:
10116
        assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10117
        break;
10118
      }
10119
    return \"\";
10120
  }"
10121
  [(set_attr "length" "8")]
10122
)
10123
 
10124
;; Miscellaneous Thumb patterns
10125
 
10126
(define_expand "tablejump"
10127
  [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10128
              (use (label_ref (match_operand 1 "" "")))])]
10129
  "TARGET_THUMB"
10130
  "
10131
  if (flag_pic)
10132
    {
10133
      /* Hopefully, CSE will eliminate this copy.  */
10134
      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10135
      rtx reg2 = gen_reg_rtx (SImode);
10136
 
10137
      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10138
      operands[0] = reg2;
10139
    }
10140
  "
10141
)
10142
 
10143
;; NB never uses BX.
10144
(define_insn "*thumb_tablejump"
10145
  [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10146
   (use (label_ref (match_operand 1 "" "")))]
10147
  "TARGET_THUMB"
10148
  "mov\\t%|pc, %0"
10149
  [(set_attr "length" "2")]
10150
)
10151
 
10152
;; V5 Instructions,
10153
 
10154
(define_insn "clzsi2"
10155
  [(set (match_operand:SI 0 "s_register_operand" "=r")
10156
        (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10157
  "TARGET_ARM && arm_arch5"
10158
  "clz%?\\t%0, %1"
10159
  [(set_attr "predicable" "yes")])
10160
 
10161
(define_expand "ffssi2"
10162
  [(set (match_operand:SI 0 "s_register_operand" "")
10163
        (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10164
  "TARGET_ARM && arm_arch5"
10165
  "
10166
  {
10167
    rtx t1, t2, t3;
10168
 
10169
    t1 = gen_reg_rtx (SImode);
10170
    t2 = gen_reg_rtx (SImode);
10171
    t3 = gen_reg_rtx (SImode);
10172
 
10173
    emit_insn (gen_negsi2 (t1, operands[1]));
10174
    emit_insn (gen_andsi3 (t2, operands[1], t1));
10175
    emit_insn (gen_clzsi2 (t3, t2));
10176
    emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10177
    DONE;
10178
  }"
10179
)
10180
 
10181
(define_expand "ctzsi2"
10182
  [(set (match_operand:SI 0 "s_register_operand" "")
10183
        (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10184
  "TARGET_ARM && arm_arch5"
10185
  "
10186
  {
10187
    rtx t1, t2, t3;
10188
 
10189
    t1 = gen_reg_rtx (SImode);
10190
    t2 = gen_reg_rtx (SImode);
10191
    t3 = gen_reg_rtx (SImode);
10192
 
10193
    emit_insn (gen_negsi2 (t1, operands[1]));
10194
    emit_insn (gen_andsi3 (t2, operands[1], t1));
10195
    emit_insn (gen_clzsi2 (t3, t2));
10196
    emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10197
    DONE;
10198
  }"
10199
)
10200
 
10201
;; V5E instructions.
10202
 
10203
(define_insn "prefetch"
10204
  [(prefetch (match_operand:SI 0 "address_operand" "p")
10205
             (match_operand:SI 1 "" "")
10206
             (match_operand:SI 2 "" ""))]
10207
  "TARGET_ARM && arm_arch5e"
10208
  "pld\\t%a0")
10209
 
10210
;; General predication pattern
10211
 
10212
(define_cond_exec
10213
  [(match_operator 0 "arm_comparison_operator"
10214
    [(match_operand 1 "cc_register" "")
10215
     (const_int 0)])]
10216
  "TARGET_ARM"
10217
  ""
10218
)
10219
 
10220
(define_insn "prologue_use"
10221
  [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10222
  ""
10223
  "%@ %0 needed for prologue"
10224
)
10225
 
10226
 
10227
;; Patterns for exception handling
10228
 
10229
(define_expand "eh_return"
10230
  [(use (match_operand 0 "general_operand" ""))]
10231
  "TARGET_EITHER"
10232
  "
10233
  {
10234
    if (TARGET_ARM)
10235
      emit_insn (gen_arm_eh_return (operands[0]));
10236
    else
10237
      emit_insn (gen_thumb_eh_return (operands[0]));
10238
    DONE;
10239
  }"
10240
)
10241
 
10242
;; We can't expand this before we know where the link register is stored.
10243
(define_insn_and_split "arm_eh_return"
10244
  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10245
                    VUNSPEC_EH_RETURN)
10246
   (clobber (match_scratch:SI 1 "=&r"))]
10247
  "TARGET_ARM"
10248
  "#"
10249
  "&& reload_completed"
10250
  [(const_int 0)]
10251
  "
10252
  {
10253
    arm_set_return_address (operands[0], operands[1]);
10254
    DONE;
10255
  }"
10256
)
10257
 
10258
(define_insn_and_split "thumb_eh_return"
10259
  [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10260
                    VUNSPEC_EH_RETURN)
10261
   (clobber (match_scratch:SI 1 "=&l"))]
10262
  "TARGET_THUMB"
10263
  "#"
10264
  "&& reload_completed"
10265
  [(const_int 0)]
10266
  "
10267
  {
10268
    thumb_set_return_address (operands[0], operands[1]);
10269
    DONE;
10270
  }"
10271
)
10272
 
10273
 
10274
;; TLS support
10275
 
10276
(define_insn "load_tp_hard"
10277
  [(set (match_operand:SI 0 "register_operand" "=r")
10278
        (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10279
  "TARGET_HARD_TP"
10280
  "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10281
  [(set_attr "predicable" "yes")]
10282
)
10283
 
10284
;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10285
(define_insn "load_tp_soft"
10286
  [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10287
   (clobber (reg:SI LR_REGNUM))
10288
   (clobber (reg:SI IP_REGNUM))
10289
   (clobber (reg:CC CC_REGNUM))]
10290
  "TARGET_SOFT_TP"
10291
  "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10292
  [(set_attr "conds" "clob")]
10293
)
10294
 
10295
;; Load the FPA co-processor patterns
10296
(include "fpa.md")
10297
;; Load the Maverick co-processor patterns
10298
(include "cirrus.md")
10299
;; Load the Intel Wireless Multimedia Extension patterns
10300
(include "iwmmxt.md")
10301
;; Load the VFP co-processor patterns
10302
(include "vfp.md")
10303
 

powered by: WebSVN 2.1.0

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