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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 709 jeremybenn
;; Machine description of the Adaptiva epiphany cpu for GNU C compiler
2
;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007, 2009, 2010,
3
;; 2011 Free Software Foundation, Inc.
4
;; Contributed by Embecosm on behalf of Adapteva, Inc.
5
 
6
;; This file is part of GCC.
7
 
8
;; GCC is free software; you can redistribute it and/or modify
9
;; it under the terms of the GNU General Public License as published by
10
;; the Free Software Foundation; either version 3, or (at your option)
11
;; any later version.
12
 
13
;; GCC is distributed in the hope that it will be useful,
14
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
;; GNU General Public License for more details.
17
 
18
;; You should have received a copy of the GNU General Public License
19
;; along with GCC; see the file COPYING3.  If not see
20
;; .
21
 
22
;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
23
 
24
(define_constants
25
  [(GPR_0                        0)
26
   (GPR_FP                      11)
27
   (GPR_IP                      12)
28
   (GPR_SP                      13)
29
   (GPR_LR                      14)
30
   (GPR_16                      16)
31
   (GPR_18                      18)
32
   (GPR_20                      20)
33
   (ARG_POINTER_REGNUM          64)
34
   (FRAME_POINTER_REGNUM        65)
35
   (CC_REGNUM                   66)   ;; 66 or 17
36
   (CCFP_REGNUM                 67)   ;; 67 or 18
37
   (CONFIG_REGNUM               68)
38
   (STATUS_REGNUM               69)
39
   (LC_REGNUM                   70)
40
   (LS_REGNUM                   71)
41
   (LE_REGNUM                   72)
42
   (IRET_REGNUM                 73)
43
   (FP_NEAREST_REGNUM           74)
44
   (FP_TRUNCATE_REGNUM          75)
45
   (FP_ANYFP_REGNUM             76)
46
   (UNKNOWN_REGNUM              77) ; used for addsi3_r and friends
47
   ; We represent the return address as an unspec rather than a reg.
48
   ; If we used a reg, we could use register elimination, but eliminating
49
   ; to GPR_LR would make the latter visible to dataflow, thus making it
50
   ; harder to determine when it must be saved.
51
   (UNSPEC_RETURN_ADDR           0)
52
   (UNSPEC_FP_MODE               1)
53
 
54
   (UNSPECV_GID                  0)
55
   (UNSPECV_GIE                  1)])
56
 
57
;; Insn type.  Used to default other attribute values.
58
 
59
(define_attr "type"
60
  "move,load,store,cmove,unary,compare,shift,mul,uncond_branch,branch,call,fp,fp_int,misc,sfunc,fp_sfunc,flow"
61
  (const_string "misc"))
62
 
63
;; Length (in # bytes)
64
 
65
(define_attr "length" "" (const_int 4))
66
 
67
;; The length here is the length of a single asm.
68
 
69
(define_asm_attributes
70
  [(set_attr "length" "4")
71
   (set_attr "type" "misc")])
72
 
73
;; pipeline model; so far we have only one.
74
(define_attr "pipe_model" "epiphany" (const_string "epiphany"))
75
 
76
(define_attr "rounding" "trunc,nearest"
77
  (cond [(ne (symbol_ref "TARGET_ROUND_NEAREST") (const_int 0))
78
         (const_string "nearest")]
79
        (const_string "trunc")))
80
 
81
(define_attr "fp_mode" "round_unknown,round_nearest,round_trunc,int,caller,none"
82
  (cond [(eq_attr "type" "fp,fp_sfunc")
83
         (symbol_ref "(enum attr_fp_mode) epiphany_normal_fp_rounding")
84
         (eq_attr "type" "call")
85
         (symbol_ref "(enum attr_fp_mode) epiphany_normal_fp_mode")
86
         (eq_attr "type" "fp_int")
87
         (const_string "int")]
88
        (const_string "none")))
89
 
90
(include "epiphany-sched.md")
91
 
92
(include "predicates.md")
93
(include "constraints.md")
94
 
95
;; modes that are held in a single register, and hence, a word.
96
(define_mode_iterator WMODE [SI SF HI QI V2HI V4QI])
97
(define_mode_iterator WMODE2 [SI SF HI QI V2HI V4QI])
98
 
99
;; modes that are held in a two single registers
100
(define_mode_iterator DWMODE [DI DF V2SI V2SF V4HI V8QI])
101
 
102
;; Double-word mode made up of two single-word mode values.
103
(define_mode_iterator DWV2MODE [V2SI V2SF])
104
(define_mode_attr vmode_part [(V2SI "si") (V2SF "sf")])
105
(define_mode_attr vmode_PART [(V2SI "SI") (V2SF "SF")])
106
(define_mode_attr vmode_fp_type [(V2SI "fp_int") (V2SF "fp")])
107
(define_mode_attr vmode_ccmode [(V2SI "CC") (V2SF "CC_FP")])
108
(define_mode_attr vmode_cc [(V2SI "CC_REGNUM") (V2SF "CCFP_REGNUM")])
109
 
110
;; Move instructions.
111
 
112
(define_expand "mov"
113
  [(set (match_operand:WMODE 0 "general_operand" "")
114
        (match_operand:WMODE 1 "general_operand" ""))]
115
  ""
116
{
117
  if (mode == V4QImode || mode == V2HImode)
118
    {
119
      operands[0] = simplify_gen_subreg (SImode, operands[0], mode, 0);
120
      operands[1] = simplify_gen_subreg (SImode, operands[1], mode, 0);
121
      emit_insn (gen_movsi (operands[0], operands[1]));
122
      DONE;
123
    }
124
  if (GET_CODE (operands[0]) == MEM)
125
    operands[1] = force_reg (mode, operands[1]);
126
  if (mode == SImode
127
      && (operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx))
128
    {
129
      rtx reg = operands[0];
130
 
131
      if (!REG_P (reg))
132
        reg = gen_reg_rtx (SImode);
133
      emit_insn (gen_move_frame (reg, operands[1]));
134
      operands[1] = reg;
135
      if (operands[0] == reg)
136
        DONE;
137
    }
138
})
139
 
140
(define_insn "*movqi_insn"
141
  [(set (match_operand:QI 0 "move_dest_operand" "=Rcs,   r,  r,r,m")
142
        (match_operand:QI 1 "move_src_operand"   "Rcs,rU16,Cal,m,r"))]
143
;; ??? Needed?
144
  "gpr_operand (operands[0], QImode)
145
   || gpr_operand (operands[1], QImode)"
146
  "@
147
   mov %0,%1
148
   mov %0,%1
149
   mov %0,%1
150
   ldrb %0,%1
151
   strb %1,%0"
152
  [(set_attr "type" "move,move,move,load,store")])
153
 
154
(define_insn_and_split "*movhi_insn"
155
  [(set (match_operand:HI 0 "move_dest_operand" "=r,  r,r,m")
156
        (match_operand:HI 1 "move_src_operand""rU16,Cal,m,r"))]
157
  "gpr_operand (operands[0], HImode)
158
   || gpr_operand (operands[1], HImode)"
159
  "@
160
   mov %0,%1
161
   mov %0,%%low(%1); %1
162
   ldrh %0,%c1
163
   strh %1,%c0"
164
  "reload_completed && CONSTANT_P (operands[1])
165
   && !satisfies_constraint_U16 (operands[1]) && TARGET_SPLIT_LOHI"
166
  [(set (match_dup 2) (match_dup 3))]
167
  "operands[2] = simplify_gen_subreg (SImode, operands[0], HImode, 0);
168
   operands[3] = simplify_gen_subreg (SImode, operands[1], HImode, 0);"
169
  [(set_attr "type" "move,move,load,store")])
170
 
171
;; We use a special pattern for a move from the frame pointer to
172
;; show the flag clobber that is needed when this move is changed
173
;; to an add by register elimination.
174
;; ??? A pseudo register might be equivalent to a function invariant,
175
;; and thus placed by reload into reg_equiv_invariant; if the pseudo
176
;; does not get a hard register, we then end up with the function
177
;; invariant in its place, i.e. an unexpected clobber of the flags
178
;; register.
179
;;
180
;; N.B. operand 1 is an operand so that reload will perform elimination.
181
;;
182
;; The post-reload pattern recognition and splitting is done in frame_move_1.
183
(define_insn "move_frame"
184
  [(set (match_operand:SI 0 "gpr_operand" "=r")
185
        (match_operand:SI 1 "register_operand" "r"))
186
   (clobber (reg:CC CC_REGNUM))]
187
  "operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx"
188
  "#")
189
 
190
(define_insn "movsi_high"
191
  [(set (match_operand:SI 0 "gpr_operand" "+r")
192
        (ior:SI (and:SI (match_dup 0) (const_int 65535))
193
                (high:SI (match_operand:SI 1 "move_src_operand" "i"))))]
194
  ""
195
  "movt %0, %%high(%1)"
196
  [(set_attr "type" "move")
197
   (set_attr "length" "4")])
198
 
199
(define_insn "movsi_lo_sum"
200
  [(set (match_operand:SI 0 "gpr_operand" "=r")
201
        (lo_sum:SI (const_int 0)
202
                   (match_operand:SI 1 "move_src_operand" "i")))]
203
  ""
204
  "mov %0, %%low(%1)"
205
  [(set_attr "type" "move")
206
   (set_attr "length" "4")])
207
 
208
(define_insn_and_split "*movsi_insn"
209
  [(set (match_operand:SI 0 "move_dest_operand"
210
         "=   r,  r,  r,  r,  r,   r,   m,  r,  Rct")
211
        (match_operand:SI 1 "move_src_operand"
212
         "rU16Rra,Cm1,Cl1,Cr1,Cal,mSra,rRra,Rct,r"))]
213
  "gpr_operand (operands[0], SImode)
214
   || gpr_operand (operands[1], SImode)
215
   || satisfies_constraint_Sra (operands[1])"
216
{
217
  switch (which_alternative)
218
    {
219
    case 0: return "mov %0,%1";
220
    case 1: return "add %0,%-,(1+%1)";
221
    case 2: operands[1] = GEN_INT (exact_log2 (-INTVAL (operands[1])));
222
      return "lsl %0,%-,%1";
223
    case 3: operands[1] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
224
      return "lsr %0,%-,%1";
225
    case 4: return "mov %0,%%low(%1)\;movt %0,%%high(%1) ; %1";
226
    case 5: return "ldr %0,%C1";
227
    case 6: return "str %1,%C0";
228
    case 7: return "movfs %0,%1";
229
    case 8: return "movts %0,%1";
230
    default: gcc_unreachable ();
231
    }
232
}
233
  "reload_completed && CONSTANT_P (operands[1])
234
   && !satisfies_constraint_U16 (operands[1])
235
   && !satisfies_constraint_Cm1 (operands[1])
236
   && !satisfies_constraint_Cl1 (operands[1])
237
   && !satisfies_constraint_Cr1 (operands[1])
238
   && TARGET_SPLIT_LOHI"
239
  [(match_dup 2) (match_dup 3)]
240
  "operands[2] = gen_movsi_lo_sum (operands[0], operands[1]);
241
   operands[3] = gen_movsi_high (operands[0], operands[1]);"
242
  [(set_attr "type" "move,misc,misc,misc,move,load,store,flow,flow")
243
   (set_attr "length" "4,4,4,4,8,4,4,4,4")])
244
 
245
(define_split
246
  [(set (match_operand:SI 0 "nonimmediate_operand")
247
        (unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR))]
248
  "reload_completed && !MACHINE_FUNCTION (cfun)->lr_clobbered"
249
  [(set (match_dup 0) (reg:SI GPR_LR))])
250
 
251
(define_split
252
  [(set (match_operand:SI 0 "gpr_operand")
253
        (unspec:SI [(const_int 0)] UNSPEC_RETURN_ADDR))]
254
  "reload_completed"
255
  [(set (match_dup 0) (match_dup 1))]
256
{
257
  emit_insn (gen_reload_insi_ra (operands[0], operands[1]));
258
  DONE;
259
})
260
 
261
(define_expand "reload_insi_ra"
262
  [(set (match_operand:SI 0 "gpr_operand" "r") (match_operand:SI 1 "" "Sra"))]
263
  ""
264
{
265
  rtx addr
266
    = (frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx);
267
 
268
  addr = plus_constant (addr, MACHINE_FUNCTION (cfun)->lr_slot_offset);
269
  operands[1] = gen_frame_mem (SImode, addr);
270
})
271
 
272
;; If the frame pointer elimination offset is zero, we'll use this pattern.
273
;; Note that the splitter can accept any gpr in operands[1]; this is
274
;; necessary, (e.g. for compile/20021015-1.c -O0,)
275
;; because when register elimination cannot be done with the constant
276
;; as an immediate operand of the add instruction, reload will resort to
277
;; loading the constant into a reload register, using gen_add2_insn to add
278
;; the stack pointer, and then use the reload register as new source in
279
;; the move_frame pattern.
280
(define_insn_and_split "*move_frame_1"
281
  [(set (match_operand:SI 0 "gpr_operand" "=r")
282
        (match_operand:SI 1 "gpr_operand" "r"))
283
   (clobber (reg:CC CC_REGNUM))]
284
  "(reload_in_progress || reload_completed)
285
   && (operands[1] == stack_pointer_rtx
286
       || operands[1] == hard_frame_pointer_rtx)"
287
  "#"
288
  "reload_in_progress || reload_completed"
289
  [(set (match_dup 0) (match_dup 1))])
290
 
291
(define_expand "mov"
292
  [(set (match_operand:DWMODE 0 "general_operand" "")
293
        (match_operand:DWMODE 1 "general_operand" ""))]
294
  ""
295
  "
296
{
297
  if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
298
      || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
299
    {
300
      if (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)
301
        {
302
          rtx o0l, o0h, o1l, o1h;
303
 
304
          o0l = simplify_gen_subreg (SImode, operands[0], mode, 0);
305
          o0h = simplify_gen_subreg (SImode, operands[0], mode,
306
                                     UNITS_PER_WORD);
307
          o1l = simplify_gen_subreg (SImode, operands[1], mode, 0);
308
          o1h = simplify_gen_subreg (SImode, operands[1], mode,
309
                                     UNITS_PER_WORD);
310
          if (reg_overlap_mentioned_p (o0l, o1h))
311
            {
312
              emit_move_insn (o0h, o1h);
313
              emit_move_insn (o0l, o1l);
314
            }
315
          else
316
            {
317
              emit_move_insn (o0l, o1l);
318
              emit_move_insn (o0h, o1h);
319
            }
320
          DONE;
321
        }
322
      /* lower_subreg has a tendency to muck up vectorized code.
323
         To protect the wide memory accesses, we must use same-size
324
         subregs.  */
325
      if (epiphany_vect_align != 4 /* == 8 */
326
          && !reload_in_progress
327
          && (GET_CODE (operands[0]) == MEM || GET_CODE (operands[1]) == MEM)
328
          && (GET_CODE (operands[0]) != SUBREG
329
              || (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0])))
330
                  != GET_MODE_SIZE (mode)
331
                  && GET_CODE (operands[1]) != SUBREG)))
332
        {
333
          operands[0]
334
            = simplify_gen_subreg (DImode, operands[0], mode, 0);
335
          operands[1]
336
            = simplify_gen_subreg (DImode, operands[1], mode, 0);
337
          emit_insn (gen_movdi (operands[0], operands[1]));
338
          DONE;
339
        }
340
    }
341
  /* Everything except mem = const or mem = mem can be done easily.  */
342
 
343
  if (GET_CODE (operands[0]) == MEM)
344
    operands[1] = force_reg (mode, operands[1]);
345
}")
346
 
347
(define_insn_and_split "*mov_insn"
348
  [(set (match_operand:DWMODE 0 "move_dest_operand"      "=r,   r,r,m")
349
        (match_operand:DWMODE 1 "move_double_src_operand" "r,CalE,m,r"))]
350
  "(gpr_operand (operands[0], mode)
351
    || gpr_operand (operands[1], mode))"
352
  "@
353
   #
354
   #
355
   ldrd %0,%X1
356
   strd %1,%X0"
357
  "reload_completed
358
   && ((!MEM_P (operands[0]) && !MEM_P (operands[1]))
359
       || epiphany_vect_align == 4)"
360
  [(set (match_dup 2) (match_dup 3))
361
   (set (match_dup 4) (match_dup 5))]
362
{
363
  int word0 = 0, word1 = UNITS_PER_WORD;
364
 
365
  if (post_modify_operand (operands[0], mode)
366
      || post_modify_operand (operands[1], mode))
367
    word0 = UNITS_PER_WORD, word1 = 0;
368
 
369
  operands[2] = simplify_gen_subreg (SImode, operands[0], mode, word0);
370
  operands[3] = simplify_gen_subreg (SImode, operands[1], mode, word0);
371
  operands[4] = simplify_gen_subreg (SImode, operands[0], mode, word1);
372
  operands[5] = simplify_gen_subreg (SImode, operands[1], mode, word1);
373
  if (post_modify_operand (operands[0], mode))
374
    operands[2]
375
      = change_address (operands[2], VOIDmode,
376
                        plus_constant (XEXP (XEXP (operands[0], 0), 0),
377
                                       UNITS_PER_WORD));
378
  if (post_modify_operand (operands[1], mode))
379
    operands[3]
380
      = change_address (operands[3], VOIDmode,
381
                        plus_constant (XEXP (XEXP (operands[1], 0), 0),
382
                                       UNITS_PER_WORD));
383
}
384
  [(set_attr "type" "move,move,load,store")
385
   (set_attr "length" "8,16,4,4")])
386
 
387
 
388
(define_insn_and_split "*movsf_insn"
389
  [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
390
        (match_operand:SF 1 "move_src_operand"   "r,E,m,r"))]
391
  "gpr_operand (operands[0], SFmode)
392
   || gpr_operand (operands[1], SFmode)"
393
  "@
394
   mov %0,%1
395
   mov %0,%%low(%1)\;movt %0,%%high(%1) ; %1
396
   ldr %0,%C1
397
   str %1,%C0"
398
  "reload_completed && CONSTANT_P (operands[1]) && TARGET_SPLIT_LOHI"
399
  [(set (match_dup 2) (match_dup 3))]
400
  "operands[2] = simplify_gen_subreg (SImode, operands[0], SFmode, 0);
401
   operands[3] = simplify_gen_subreg (SImode, operands[1], SFmode, 0);"
402
  [(set_attr "type" "move,move,load,store")
403
   (set_attr "length" "4,8,4,4")])
404
 
405
(define_expand "addsi3"
406
  [(set (match_operand:SI 0 "add_reg_operand" "")
407
        (plus:SI (match_operand:SI 1 "add_reg_operand" "")
408
                 (match_operand:SI 2 "add_operand" "")))]
409
  ""
410
  "
411
{
412
  if (reload_in_progress || reload_completed)
413
    emit_insn (gen_addsi3_r (operands[0], operands[1], operands[2]));
414
  else
415
    emit_insn (gen_addsi3_i (operands[0], operands[1], operands[2]));
416
  DONE;
417
}")
418
 
419
(define_insn "addsi3_i"
420
  [(set (match_operand:SI 0 "add_reg_operand" "=r")
421
        (plus:SI (match_operand:SI 1 "add_reg_operand" "%r")
422
                 (match_operand:SI 2 "add_operand" "rL")))
423
   (clobber (reg:CC CC_REGNUM))]
424
  ""
425
  "add %0,%1,%2"
426
[(set_attr "type" "misc")])
427
 
428
; We use a clobber of UNKNOWN_REGNUM here so that the peephole optimizers
429
; can identify the unresolved flags clobber problem, and also to
430
; avoid unwanted matches.
431
;
432
; At -O0 / -O1 we don't peephole all instances away.  We could get better
433
; debug unwinding through the emitted code if we added a splitter.
434
(define_insn "addsi3_r"
435
  [(set (match_operand:SI 0 "gpr_operand" "=r")
436
        (plus:SI (match_operand:SI 1 "gpr_operand" "%r")
437
                 (match_operand:SI 2 "nonmemory_operand" "rCar")))
438
   (clobber (reg:CC UNKNOWN_REGNUM))]
439
  "reload_in_progress || reload_completed"
440
{
441
  int scratch = (0x17
442
                 ^ (true_regnum (operands[0]) & 1)
443
                 ^ (true_regnum (operands[1]) & 2)
444
                 ^ (true_regnum (operands[2]) & 4));
445
  asm_fprintf (asm_out_file, "\tstr r%d,[sp,#0]\n", scratch);
446
  asm_fprintf (asm_out_file, "\tmovfs r%d,status\n", scratch);
447
  output_asm_insn ("add %0,%1,%2", operands);
448
  asm_fprintf (asm_out_file, "\tmovts status,r%d\n", scratch);
449
  asm_fprintf (asm_out_file, "\tldr r%d,[sp,#0]\n", scratch);
450
  return "";
451
}
452
  [(set_attr "length" "20")
453
   (set_attr "type" "misc")])
454
 
455
;; reload uses gen_addsi2 because it doesn't understand the need for
456
;; the clobber.
457
(define_peephole2
458
  [(set (match_operand:SI 0 "gpr_operand" "")
459
        (match_operand:SI 1 "const_int_operand" ""))
460
   (parallel [(set (match_dup 0)
461
                   (plus:SI (match_dup 0)
462
                            (match_operand:SI 2 "gpr_operand")))
463
              (clobber (reg:CC UNKNOWN_REGNUM))])]
464
  "satisfies_constraint_L (operands[1])
465
   || ((operands[2] == stack_pointer_rtx
466
        || (operands[2] == hard_frame_pointer_rtx && frame_pointer_needed))
467
       && !peep2_regno_dead_p (2, CC_REGNUM)
468
       && satisfies_constraint_Car (operands[1]))"
469
  [(parallel [(set (match_dup 0)
470
                   (plus:SI (match_dup 2) (match_dup 1)))
471
              (clobber (reg:CC UNKNOWN_REGNUM))])]
472
  ;; FIXME:
473
  ;; need this patch: http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html
474
  ;; "peep2_rescan = true;"
475
)
476
 
477
(define_peephole2
478
  [(match_parallel 5 ""
479
     [(set (match_operand 3 "cc_operand" "") (match_operand 4 "" ""))])
480
   (parallel [(set (match_operand:SI 0 "gpr_operand" "")
481
                   (plus:SI (match_operand:SI 1 "gpr_operand" "")
482
                            (match_operand:SI 2 "nonmemory_operand" "")))
483
              (clobber (reg:CC UNKNOWN_REGNUM))])]
484
  "REGNO (operands[3]) == CC_REGNUM
485
   && (gpr_operand (operands[2], SImode)
486
       || satisfies_constraint_L (operands[2]))
487
   && !reg_overlap_mentioned_p (operands[0], operands[5])
488
   && !reg_set_p (operands[1], operands[5])
489
   && !reg_set_p (operands[2], operands[5])"
490
  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
491
                   (plus:SI (match_operand:SI 1 "gpr_operand" "")
492
                            (match_operand:SI 2 "nonmemory_operand" "")))
493
              (clobber (reg:CC CC_REGNUM))])
494
   (match_dup 5)]
495
  "")
496
 
497
(define_peephole2
498
  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
499
                   (plus:SI (match_operand:SI 1 "gpr_operand" "")
500
                            (match_operand:SI 2 "nonmemory_operand" "")))
501
              (clobber (reg:CC UNKNOWN_REGNUM))])]
502
  "peep2_regno_dead_p (1, CC_REGNUM)
503
   && (gpr_operand (operands[2], SImode)
504
       || satisfies_constraint_L (operands[2]))"
505
  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
506
                   (plus:SI (match_operand:SI 1 "gpr_operand" "")
507
                            (match_operand:SI 2 "nonmemory_operand" "")))
508
              (clobber (reg:CC CC_REGNUM))])]
509
  "")
510
 
511
(define_peephole2
512
  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
513
                   (plus:SI (reg:SI GPR_SP)
514
                            (match_operand:SI 1 "nonmemory_operand" "")))
515
              (clobber (reg:CC UNKNOWN_REGNUM))])]
516
  "(REG_P (operands[1]) && !reg_overlap_mentioned_p (operands[0], operands[1]))
517
   || RTX_OK_FOR_OFFSET_P (mode, operands[1])"
518
  [(set (match_dup 0) (reg:SI GPR_SP))
519
   (set (mem:WMODE (post_modify (match_dup 0)
520
                                (plus:SI (match_dup 0) (match_dup 1))))
521
        (reg:WMODE GPR_SP))]
522
  "")
523
 
524
 
525
 
526
(define_peephole2
527
  [(parallel [(set (match_operand:SI 0 "gpr_operand" "")
528
                   (plus:SI (reg:SI GPR_FP)
529
                            (match_operand:SI 1 "nonmemory_operand" "")))
530
              (clobber (reg:CC UNKNOWN_REGNUM))])
531
   (match_scratch:WMODE 2 "r")]
532
  "frame_pointer_needed
533
   && ((REG_P (operands[1])
534
        && !reg_overlap_mentioned_p (operands[0], operands[1]))
535
       || RTX_OK_FOR_OFFSET_P (mode, operands[1]))"
536
  [(set (match_dup 0) (reg:SI GPR_FP))
537
   (set (match_dup 2)
538
        (mem:WMODE (post_modify (match_dup 0)
539
                                (plus:SI (match_dup 0) (match_dup 1)))))]
540
  "")
541
 
542
(define_insn "subsi3"
543
  [(set (match_operand:SI 0 "gpr_operand" "=r")
544
        (minus:SI (match_operand:SI 1 "add_reg_operand" "r")
545
                  (match_operand:SI 2 "arith_operand" "rL")))
546
   (clobber (reg:CC CC_REGNUM))]
547
  ""
548
  "sub %0,%1,%2"
549
  [(set_attr "type" "misc")])
550
 
551
; After mode-switching, floating point operations, fp_sfuncs and calls
552
; must exhibit the use of the control register, lest the setting of the
553
; control register could be deleted or moved.  OTOH a use of a hard register
554
; greatly coundounds optimizers like the rtl loop optimizers or combine.
555
; Therefore, we put an extra pass immediately after the mode switching pass
556
; that inserts the USEs of the control registers, and sets a flag in struct
557
; machine_function that float_operation can henceforth only match with that
558
; USE.
559
 
560
;; Addition
561
(define_expand "addsf3"
562
  [(parallel
563
     [(set (match_operand:SF 0 "gpr_operand" "")
564
           (plus:SF (match_operand:SF 1 "gpr_operand" "")
565
                    (match_operand:SF 2 "gpr_operand" "")))
566
      (clobber (reg:CC_FP CCFP_REGNUM))])])
567
 
568
(define_insn "*addsf3_i"
569
  [(match_parallel 3 "float_operation"
570
     [(set (match_operand:SF 0 "gpr_operand" "=r")
571
           (plus:SF (match_operand:SF 1 "gpr_operand" "%r")
572
                    (match_operand:SF 2 "gpr_operand" "r")))
573
      (clobber (reg:CC_FP CCFP_REGNUM))])]
574
  ""
575
  "fadd %0,%1,%2"
576
  [(set_attr "type" "fp")])
577
 
578
;; Subtraction
579
(define_expand "subsf3"
580
  [(parallel
581
     [(set (match_operand:SF 0 "gpr_operand" "")
582
           (minus:SF (match_operand:SF 1 "gpr_operand" "")
583
                     (match_operand:SF 2 "gpr_operand" "")))
584
      (clobber (reg:CC_FP CCFP_REGNUM))])])
585
 
586
(define_insn "*subsf3_i"
587
  [(match_parallel 3 "float_operation"
588
     [(set (match_operand:SF 0 "gpr_operand" "=r")
589
           (minus:SF (match_operand:SF 1 "gpr_operand" "r")
590
                     (match_operand:SF 2 "gpr_operand" "r")))
591
      (clobber (reg:CC_FP CCFP_REGNUM))])]
592
  ""
593
  "fsub %0,%1,%2"
594
  [(set_attr "type" "fp")])
595
 
596
(define_expand "subsf3_f"
597
  [(parallel
598
     [(set (reg:CC_FP CCFP_REGNUM)
599
           (compare:CC_FP (match_operand:SF 1 "gpr_operand" "r")
600
                          (match_operand:SF 2 "gpr_operand" "r")))
601
      (set (match_operand:SF 0 "gpr_operand" "=r")
602
           (minus:SF (match_dup 1) (match_dup 2)))])]
603
  "!TARGET_SOFT_CMPSF")
604
 
605
(define_insn "*subsf3_f_i"
606
  [(match_parallel 3 "float_operation"
607
     [(set (reg:CC_FP CCFP_REGNUM)
608
           (compare:CC_FP (match_operand:SF 1 "gpr_operand" "r")
609
                          (match_operand:SF 2 "gpr_operand" "r")))
610
      (set (match_operand:SF 0 "gpr_operand" "=r")
611
           (minus:SF (match_dup 1) (match_dup 2)))])]
612
  "!TARGET_SOFT_CMPSF"
613
  "fsub %0,%1,%2"
614
  [(set_attr "type" "fp")])
615
 
616
; There is an fabs instruction, but it has longer latency.
617
(define_expand "abssf2"
618
  [(set (match_operand:SF 0 "gpr_operand" "")
619
        (abs:SF (match_operand:SF 1 "gpr_operand" "")))]
620
  ""
621
  "
622
{
623
  rtx op1 = copy_to_mode_reg (SImode, simplify_gen_subreg (SImode, operands[1],
624
                                                           SFmode, 0));
625
  rtx op0 = simplify_gen_subreg (SImode, operands[0], SFmode, 0);
626
 
627
  emit_insn (gen_ashlsi3 (op1, op1, const1_rtx));
628
  emit_insn (gen_lshrsi3 (op0, op1, const1_rtx));
629
  DONE;
630
}")
631
 
632
;; Multiplication
633
(define_expand "mulsf3"
634
  [(parallel
635
     [(set (match_operand:SF 0 "gpr_operand" "")
636
           (mult:SF (match_operand:SF 1 "gpr_operand" "")
637
                    (match_operand:SF 2 "gpr_operand" "")))
638
      (clobber (reg:CC_FP CCFP_REGNUM))])])
639
 
640
(define_insn "*mulsf3_i"
641
  [(match_parallel 3 "float_operation"
642
     [(set (match_operand:SF 0 "gpr_operand" "=r")
643
           (mult:SF (match_operand:SF 1 "gpr_operand" "%r")
644
                    (match_operand:SF 2 "gpr_operand" "r")))
645
      (clobber (reg:CC_FP CCFP_REGNUM))])]
646
  ""
647
  "fmul %0,%1,%2"
648
  [(set_attr "type" "fp")])
649
 
650
;; Division
651
(define_expand "divsf3"
652
  [(set (match_operand:SF 0 "gpr_operand" "")
653
        (div:SF (match_operand:SF 1 "gpr_operand" "")
654
                (match_operand:SF 2 "gpr_operand" "")))]
655
  "flag_reciprocal_math"
656
{
657
  rtx one = CONST1_RTX (SFmode);
658
  rtx dst = operands[0];
659
 
660
  if (rtx_equal_p (dst, operands[1]))
661
    {
662
      emit_move_insn (dst, one);
663
      DONE;
664
    }
665
  else if (!register_operand (dst, SFmode) && can_create_pseudo_p ())
666
    dst = gen_reg_rtx (SFmode);
667
  emit_insn (gen_recipsf2 (dst, one, operands[2],
668
                           sfunc_symbol (\"__fast_recipsf2\")));
669
  emit_insn (gen_mulsf3 (operands[0], operands[1], dst));
670
  DONE;
671
})
672
 
673
;; Before reload, keep the hard reg usage to clobbers so that the loop
674
;; optimizers can more easily move this insn.
675
;; It would be nicer to use a constraint for a GPR_0 - only register class,
676
;; but sched1 can still cause trouble then, and there is no guarantee of
677
;; better register allocations.
678
;; Neither is there when using the opposite strategy - putting explicit
679
;; hard register references into pre-reload rtl.
680
(define_expand "recipsf2"
681
  [(parallel
682
     [(set (match_operand:SF 0 "gpr_operand" "")
683
           (div:SF (match_operand:SF 1 "const_float_1_operand" "")
684
                   (match_operand:SF 2 "move_src_operand" "")))
685
      (use (match_operand:SI 3 "move_src_operand" ""))
686
      (clobber (reg:SF 0))
687
      (clobber (reg:SI 1))
688
      (clobber (reg:SF GPR_IP))
689
      (clobber (reg:DI GPR_16))
690
      (clobber (reg:DI GPR_18))
691
      (clobber (reg:SI GPR_20))
692
      (clobber (reg:SI GPR_LR))
693
      (clobber (reg:CC CC_REGNUM))
694
      (clobber (reg:CC_FP CCFP_REGNUM))])])
695
 
696
(define_insn_and_split "*recipsf2_1"
697
  [(match_parallel 4 "float_operation"
698
     [(set (match_operand:SF 0 "gpr_operand" "=r,r")
699
           (div:SF (match_operand:SF 1 "const_float_1_operand" "")
700
                   (match_operand:SF 2 "move_src_operand" "rU16m,rU16mCal")))
701
      (use (match_operand:SI 3 "move_src_operand" "rU16m,rU16mCal"))
702
      (clobber (reg:SF 0))
703
      (clobber (reg:SI 1))
704
      (clobber (reg:SF GPR_IP))
705
      (clobber (reg:DI GPR_16))
706
      (clobber (reg:DI GPR_18))
707
      (clobber (reg:SI GPR_20))
708
      (clobber (reg:SI GPR_LR))
709
      (clobber (reg:CC CC_REGNUM))
710
      (clobber (reg:CC_FP CCFP_REGNUM))])]
711
  "flag_reciprocal_math"
712
  "#"
713
  "&& reload_completed"
714
  [(set (reg:SI 1) (match_dup 3))
715
   (set (reg:SF 0) (match_dup 2))
716
   (parallel
717
     [(set (reg:SF 0)
718
           (div:SF (match_dup 1)
719
                   (reg:SF 0)))
720
      (use (reg:SI 1))
721
      (clobber (reg:SI GPR_IP))
722
      (clobber (reg:DI GPR_16))
723
      (clobber (reg:DI GPR_18))
724
      (clobber (reg:SI GPR_20))
725
      (clobber (reg:SI GPR_LR))
726
      (clobber (reg:CC CC_REGNUM))
727
      (clobber (reg:CC_FP CCFP_REGNUM))
728
      (match_dup 5)
729
      (match_dup 6)])
730
   (set (match_dup 0) (reg:SF 0))]
731
  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
732
   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
733
  [(set_attr "type" "fp_sfunc")
734
   (set_attr "length" "16,24")])
735
 
736
(define_insn "*recipsf2_2"
737
  [(match_parallel 1 "float_operation"
738
     [(set (reg:SF 0)
739
           (div:SF (match_operand:SF 0 "const_float_1_operand" "")
740
                   (reg:SF 0)))
741
      (use (reg:SI 1))
742
      (clobber (reg:SI GPR_IP))
743
      (clobber (reg:DI GPR_16))
744
      (clobber (reg:DI GPR_18))
745
      (clobber (reg:SI GPR_20))
746
      (clobber (reg:SI GPR_LR))
747
      (clobber (reg:CC CC_REGNUM))
748
      (clobber (reg:CC_FP CCFP_REGNUM))])]
749
  "flag_reciprocal_math"
750
  "jalr r1"
751
  [(set_attr "type" "fp_sfunc")])
752
 
753
 
754
;; Fused multiply-add
755
(define_expand "fmasf4"
756
  [(parallel
757
     [(set (match_operand:SF 0 "gpr_operand" "")
758
           (fma:SF (match_operand:SF 1 "gpr_operand" "")
759
                   (match_operand:SF 2 "gpr_operand" "")
760
                   (match_operand:SF 3 "gpr_operand" "")))
761
      (clobber (reg:CC_FP CCFP_REGNUM))])]
762
  "")
763
 
764
; The multiply operands are commutative, but since they have the
765
; same constraints, there is no point in telling reload about this.
766
(define_insn "*fmadd"
767
  [(match_parallel 4 "float_operation"
768
     [(set (match_operand:SF 0 "gpr_operand" "=r")
769
           (fma:SF (match_operand:SF 1 "gpr_operand" "r")
770
                   (match_operand:SF 2 "gpr_operand" "r")
771
                   (match_operand:SF 3 "gpr_operand" "0")))
772
      (clobber (reg:CC_FP CCFP_REGNUM))])]
773
  ""
774
  "fmadd %0,%1,%2"
775
  [(set_attr "type" "fp")])
776
 
777
; Once vetorization consistently works for this port, should check
778
; if the fmadd / fmsub patterns still serve a purpose.  With the
779
; introduction of fma / fnma handling by the SSA optimizers,
780
; at least scalars should be handled by these optimizers, would
781
; have to see how well they do on vectors from auto-vectorization.
782
;
783
; combiner pattern, also used by vector combiner pattern
784
(define_expand "maddsf"
785
  [(parallel
786
     [(set (match_operand:SF 0 "gpr_operand" "=r")
787
           (plus:SF (mult:SF (match_operand:SF 1 "gpr_operand" "r")
788
                             (match_operand:SF 2 "gpr_operand" "r"))
789
                    (match_operand:SF 3 "gpr_operand" "0")))
790
      (clobber (reg:CC_FP CCFP_REGNUM))])]
791
  "TARGET_FUSED_MADD")
792
 
793
(define_insn "*maddsf_combine"
794
  [(match_parallel 4 "float_operation"
795
     [(set (match_operand:SF 0 "gpr_operand" "=r")
796
           (plus:SF (mult:SF (match_operand:SF 1 "gpr_operand" "r")
797
                             (match_operand:SF 2 "gpr_operand" "r"))
798
                    (match_operand:SF 3 "gpr_operand" "0")))
799
      (clobber (reg:CC_FP CCFP_REGNUM))])]
800
  "TARGET_FUSED_MADD"
801
  "fmadd %0,%1,%2"
802
  [(set_attr "type" "fp")])
803
 
804
;; Fused multiply-sub
805
(define_expand "fnmasf4"
806
  [(parallel
807
     [(set (match_operand:SF 0 "gpr_operand" "")
808
           (fma:SF (neg:SF (match_operand:SF 1 "gpr_operand" ""))
809
                   (match_operand:SF 2 "gpr_operand" "")
810
                   (match_operand:SF 3 "gpr_operand" "")))
811
      (clobber (reg:CC_FP CCFP_REGNUM))])]
812
  "")
813
 
814
(define_insn "*fmsub"
815
  [(match_parallel 4 "float_operation"
816
     [(set (match_operand:SF 0 "gpr_operand" "=r")
817
           (fma:SF (neg:SF (match_operand:SF 1 "gpr_operand" "r"))
818
                   (match_operand:SF 2 "gpr_operand" "r")
819
                   (match_operand:SF 3 "gpr_operand" "0")))
820
      (clobber (reg:CC_FP CCFP_REGNUM))])]
821
  ""
822
  "fmsub %0,%1,%2"
823
  [(set_attr "type" "fp")])
824
 
825
(define_insn "*fmsub_combine"
826
  [(match_parallel 4 "float_operation"
827
     [(set (match_operand:SF 0 "gpr_operand" "=r")
828
           (minus:SF  (match_operand:SF 3 "gpr_operand" "0")
829
                      (mult:SF (match_operand:SF 1 "gpr_operand" "r")
830
                               (match_operand:SF 2 "gpr_operand" "r"))))
831
      (clobber (reg:CC_FP CCFP_REGNUM))])]
832
  "TARGET_FUSED_MADD"
833
  "fmsub %0,%1,%2"
834
  [(set_attr "type" "fp")])
835
 
836
;; float / integer conversions
837
 
838
(define_expand "floatsisf2"
839
  [(parallel
840
     [(set (match_operand:SF 0 "gpr_operand" "")
841
           (float:SF (match_operand:SI 1 "gpr_operand" "")))
842
      (clobber (reg:CC_FP CCFP_REGNUM))])])
843
 
844
(define_insn "*floatsisf2_i"
845
  [(match_parallel 2 "float_operation"
846
     [(set (match_operand:SF 0 "gpr_operand" "=r")
847
           (float:SF (match_operand:SI 1 "gpr_operand" "r")))
848
      (clobber (reg:CC_FP CCFP_REGNUM))])]
849
  ""
850
  "float %0, %1"
851
  [(set_attr "type" "fp")])
852
 
853
(define_expand "floatsisf2_cmp"
854
  [(parallel
855
     [(set (reg:CC_FP CCFP_REGNUM)
856
           (compare:CC_FP (float:SF (match_operand:SF 1 "gpr_operand" "r"))
857
                          (match_dup 2)))
858
      (set (match_operand:SF 0 "gpr_operand" "=r")
859
           (float:SF (match_dup 1)))])]
860
  ""
861
  "operands[2] = CONST0_RTX (SFmode);")
862
 
863
(define_insn "*floatsisf2_cmp_i"
864
  [(match_parallel 3 "float_operation"
865
     [(set (reg:CC_FP CCFP_REGNUM)
866
           (compare:CC_FP (float:SF (match_operand:SF 1 "gpr_operand" "r"))
867
                          (match_operand:SF 2 "const0_operand" "")))
868
      (set (match_operand:SF 0 "gpr_operand" "=r")
869
           (float:SF (match_dup 1)))])]
870
  ""
871
  "float %0, %1"
872
  [(set_attr "type" "fp")])
873
 
874
(define_expand "floatunssisf2"
875
  [(set (match_operand:SF 0 "gpr_operand" "")
876
        (float:SF (match_operand:SI 1 "gpr_operand" "")))]
877
  "epiphany_normal_fp_rounding == /*FP_MODE_ROUND_TRUNC*/ 2"
878
{
879
  rtx cst = force_reg (SImode, gen_int_mode (0xb0800000, SImode));
880
  rtx tmp = gen_reg_rtx (SImode);
881
  rtx cmp = gen_rtx_GTU (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx);
882
 
883
  if (reg_overlap_mentioned_p (operands[0], operands[1]))
884
    operands[1] = copy_to_mode_reg (SImode, operands[1]);
885
  emit_insn (gen_floatsisf2 (operands[0], operands[1]));
886
  emit_insn (gen_ashrsi3 (tmp, operands[1], GEN_INT (8)));
887
  emit_insn (gen_sub_f (tmp, tmp, cst));
888
  emit_insn (gen_movsfcc (operands[0], cmp,
889
                          simplify_gen_subreg (SFmode, tmp, SImode, 0),
890
                          operands[0]));
891
  DONE;
892
})
893
 
894
(define_expand "fix_truncsfsi2"
895
  [(parallel
896
     [(set (match_operand:SI 0 "gpr_operand" "")
897
           (fix:SI (match_operand:SF 1 "gpr_operand" "")))
898
      (clobber (reg:CC_FP CCFP_REGNUM))])])
899
 
900
(define_insn "*fix_truncsfsi2_i"
901
  [(match_parallel 2 "float_operation"
902
     [(set (match_operand:SI 0 "gpr_operand" "=r")
903
           (fix:SI (match_operand:SF 1 "gpr_operand" "r")))
904
      (clobber (reg:CC_FP CCFP_REGNUM))])]
905
  ""
906
  "fix %0, %1"
907
  [(set_attr "type" "fp")
908
   (set_attr "fp_mode" "round_trunc")])
909
 
910
(define_expand "fixuns_truncsfsi2"
911
  [(set (match_operand:SI 0 "gpr_operand" "")
912
        (unsigned_fix:SI (match_operand:SF 1 "gpr_operand" "")))]
913
  ""
914
{
915
  if (reg_overlap_mentioned_p (operands[0], operands[1]))
916
    operands[1] = copy_to_mode_reg (SImode, operands[1]);
917
  if (TARGET_SOFT_CMPSF || optimize_function_for_speed_p (cfun))
918
    {
919
      rtx op1si;
920
      /* By toggling what it to be bit31 before the shift, we get a chance to
921
         use a short movt insn.  */
922
      rtx bit31 = force_reg (SImode, GEN_INT (0x800000));
923
      rtx tmp = gen_reg_rtx (SImode);
924
      rtx limit = force_reg (SImode, gen_int_mode (0x4f000000, SImode));
925
      rtx cmp
926
        = gen_rtx_GE (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx);
927
 
928
      op1si = simplify_gen_subreg (SImode, operands[1], SFmode, 0);
929
      emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
930
      emit_insn (gen_subsi3 (tmp, op1si, bit31));
931
      emit_insn (gen_ashlsi3 (tmp, tmp, GEN_INT (8)));
932
      emit_insn (gen_cmpsi_cc_insn (op1si, limit));
933
      emit_insn (gen_movsicc (operands[0], cmp, tmp, operands[0]));
934
    }
935
  else
936
    {
937
      REAL_VALUE_TYPE offset;
938
      rtx limit;
939
      rtx tmp = gen_reg_rtx (SFmode);
940
      rtx label = gen_label_rtx ();
941
      rtx bit31;
942
      rtx cc1 = gen_rtx_REG (CC_FPmode, CCFP_REGNUM);
943
      rtx cmp = gen_rtx_LT (VOIDmode, cc1, CONST0_RTX (SFmode));
944
 
945
      real_2expN (&offset, 31, SFmode);
946
      limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode);
947
      limit = force_reg (SFmode, limit);
948
      emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
949
      emit_insn (gen_subsf3_f (tmp, operands[1], limit));
950
      emit_jump_insn (gen_branch_insn (label, cmp, cc1));
951
      bit31 = force_reg (SImode, gen_int_mode (0x80000000, SImode));
952
      emit_insn (gen_fix_truncsfsi2 (operands[0], tmp));
953
      emit_insn (gen_xorsi3 (operands[0], operands[0], bit31));
954
      emit_label (label);
955
    }
956
  DONE;
957
})
958
 
959
(define_insn "*iadd"
960
  [(match_parallel 3 "float_operation"
961
     [(set (match_operand:SI 0 "gpr_operand" "=r")
962
           (plus:SI (match_operand:SI 1 "gpr_operand" "%r")
963
                    (match_operand:SI 2 "gpr_operand" "r")))
964
      (clobber (reg:CC_FP CCFP_REGNUM))])]
965
  ""
966
  "iadd %0, %1, %2"
967
  [(set_attr "type" "fp_int")])
968
 
969
(define_insn "*isub"
970
  [(match_parallel 3 "float_operation"
971
     [(set (match_operand:SI 0 "gpr_operand" "=r")
972
           (minus:SI (match_operand:SI 1 "gpr_operand" "r")
973
                     (match_operand:SI 2 "gpr_operand" "r")))
974
      (clobber (reg:CC_FP CCFP_REGNUM))])]
975
  ""
976
  "isub %0, %1, %2"
977
  [(set_attr "type" "fp_int")])
978
 
979
(define_expand "mulsi3"
980
  [(parallel
981
     [(set (match_operand:SI 0 "gpr_operand" "")
982
           (mult:SI (match_operand:SI 1 "gpr_operand" "")
983
                    (match_operand:SI 2 "gpr_operand" "")))
984
      (clobber (reg:CC_FP CCFP_REGNUM))])])
985
 
986
(define_insn "*imul"
987
  [(match_parallel 3 "float_operation"
988
     [(set (match_operand:SI 0 "gpr_operand" "=r")
989
           (mult:SI (match_operand:SI 1 "gpr_operand" "%r")
990
                    (match_operand:SI 2 "gpr_operand" "r")))
991
      (clobber (reg:CC_FP CCFP_REGNUM))])]
992
  ""
993
  "imul %0, %1, %2"
994
  [(set_attr "type" "fp_int")])
995
 
996
; combiner pattern, also used by vector combiner pattern
997
(define_expand "maddsi"
998
  [(parallel
999
     [(set (match_operand:SI 0 "gpr_operand" "=r")
1000
           (plus:SI (mult:SI (match_operand:SI 1 "gpr_operand" "r")
1001
                             (match_operand:SI 2 "gpr_operand" "r"))
1002
                    (match_operand:SI 3 "gpr_operand" "0")))
1003
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1004
  "")
1005
 
1006
(define_insn "*maddsi_combine"
1007
  [(match_parallel 4 "float_operation"
1008
     [(set (match_operand:SI 0 "gpr_operand" "=r")
1009
           (plus:SI (mult:SI (match_operand:SI 1 "gpr_operand" "r")
1010
                             (match_operand:SI 2 "gpr_operand" "r"))
1011
                    (match_operand:SI 3 "gpr_operand" "0")))
1012
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1013
  ""
1014
  "imsub %0, %1, %2"
1015
  [(set_attr "type" "fp_int")])
1016
 
1017
(define_insn "*imsub"
1018
  [(match_parallel 4 "float_operation"
1019
     [(set (match_operand:SI 0 "gpr_operand" "=r")
1020
           (minus:SI (match_operand:SI 3 "gpr_operand" "0")
1021
                     (mult:SI (match_operand:SI 1 "gpr_operand" "r")
1022
                              (match_operand:SI 2 "gpr_operand" "r"))))
1023
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1024
  ""
1025
  "imsub %0, %1, %2"
1026
  [(set_attr "type" "fp_int")])
1027
 
1028
(define_expand "divsi3"
1029
  [(parallel
1030
     [(set (match_operand:SI 0 "move_dest_operand" "")
1031
           (div:SI (match_operand:SI 1 "move_src_operand" "")
1032
                   (match_operand:SI 2 "move_src_operand" "")))
1033
      (use (match_dup 3))
1034
      (clobber (reg:SI 0))
1035
      (clobber (reg:SI 1))
1036
      (clobber (reg:SI GPR_IP))
1037
      (clobber (reg:DI GPR_16))
1038
      (clobber (reg:DI GPR_18))
1039
      (clobber (reg:SI GPR_20))
1040
      (clobber (reg:SI GPR_LR))
1041
      (clobber (reg:CC CC_REGNUM))
1042
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1043
  ""
1044
  "operands[3] = sfunc_symbol (\"__divsi3\");")
1045
 
1046
;; Before reload, keep the hard reg usage to clobbers so that the loop
1047
;; optimizers can more easily move this insn.
1048
(define_insn_and_split "*divsi3_1"
1049
  [(match_parallel 4 "float_operation"
1050
     [(set (match_operand:SI 0 "move_dest_operand" "=r,r")
1051
           (div:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")
1052
                   (match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))
1053
      (use (match_operand:SI 3 "call_address_operand" "Csy,r"))
1054
      (clobber (reg:SI 0))
1055
      (clobber (reg:SI 1))
1056
      (clobber (reg:SI GPR_IP))
1057
      (clobber (reg:DI GPR_16))
1058
      (clobber (reg:DI GPR_18))
1059
      (clobber (reg:SI GPR_20))
1060
      (clobber (reg:SI GPR_LR))
1061
      (clobber (reg:CC CC_REGNUM))
1062
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1063
  ""
1064
  "#"
1065
  "&& reload_completed"
1066
  [(set (reg:SI 0) (match_dup 1))
1067
   (set (reg:SI 1) (match_dup 2))
1068
   (parallel
1069
     [(set (reg:SI 0) (div:SI (reg:SI 0) (reg:SI 1)))
1070
      (use (match_dup 3))
1071
      (clobber (reg:SI 1))
1072
      (clobber (reg:SI GPR_IP))
1073
      (clobber (reg:DI GPR_16))
1074
      (clobber (reg:DI GPR_18))
1075
      (clobber (reg:SI GPR_20))
1076
      (clobber (reg:SI GPR_LR))
1077
      (clobber (reg:CC CC_REGNUM))
1078
      (clobber (reg:CC_FP CCFP_REGNUM))
1079
      (match_dup 5)
1080
      (match_dup 6)])
1081
   (set (match_dup 0) (reg:SI 0))]
1082
  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
1083
   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
1084
  [(set_attr "type" "fp_sfunc")
1085
   (set_attr "length" "16,24")])
1086
 
1087
(define_insn "*divsi3_2"
1088
  [(match_parallel 1 "float_operation"
1089
     [(set (reg:SI 0) (div:SI (reg:SI 0) (reg:SI 1)))
1090
      (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1091
      (clobber (reg:SI 1))
1092
      (clobber (reg:SI GPR_IP))
1093
      (clobber (reg:DI GPR_16))
1094
      (clobber (reg:DI GPR_18))
1095
      (clobber (reg:SI GPR_20))
1096
      (clobber (reg:SI GPR_LR))
1097
      (clobber (reg:CC CC_REGNUM))
1098
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1099
  ""
1100
  "%f0"
1101
  [(set_attr "type" "fp_sfunc")])
1102
 
1103
(define_expand "udivsi3"
1104
  [(parallel
1105
     [(set (match_operand:SI 0 "move_dest_operand" "")
1106
           (udiv:SI (match_operand:SI 1 "move_src_operand" "")
1107
                    (match_operand:SI 2 "move_src_operand" "")))
1108
      (use (match_dup 3))
1109
      (clobber (reg:SI 0))
1110
      (clobber (reg:SI 1))
1111
      (clobber (reg:SI GPR_IP))
1112
      (clobber (reg:DI GPR_16))
1113
      (clobber (reg:SI GPR_18))
1114
      (clobber (reg:SI GPR_LR))
1115
      (clobber (reg:CC CC_REGNUM))
1116
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1117
  ""
1118
  "operands[3] = sfunc_symbol (\"__udivsi3\");")
1119
 
1120
;; Before reload, keep the hard reg usage to clobbers so that the loop
1121
;; optimizers can more easily move this insn.
1122
(define_insn_and_split "*udivsi3_1"
1123
  [(match_parallel 4 "float_operation"
1124
     [(set (match_operand:SI 0 "move_dest_operand" "=r,r")
1125
           (udiv:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")
1126
                    (match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))
1127
      (use (match_operand:SI 3 "call_address_operand" "Csy,r"))
1128
      (clobber (reg:SI 0))
1129
      (clobber (reg:SI 1))
1130
      (clobber (reg:SI GPR_IP))
1131
      (clobber (reg:DI GPR_16))
1132
      (clobber (reg:SI GPR_18))
1133
      (clobber (reg:SI GPR_LR))
1134
      (clobber (reg:CC CC_REGNUM))
1135
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1136
  ""
1137
  "#"
1138
  "&& reload_completed"
1139
  [(set (reg:SI 0) (match_dup 1))
1140
   (set (reg:SI 1) (match_dup 2))
1141
   (parallel
1142
     [(set (reg:SI 0) (udiv:SI (reg:SI 0) (reg:SI 1)))
1143
      (use (match_dup 3))
1144
      (clobber (reg:SI 1))
1145
      (clobber (reg:SI GPR_IP))
1146
      (clobber (reg:DI GPR_16))
1147
      (clobber (reg:SI GPR_18))
1148
      (clobber (reg:SI GPR_LR))
1149
      (clobber (reg:CC CC_REGNUM))
1150
      (clobber (reg:CC_FP CCFP_REGNUM))
1151
      (match_dup 5)
1152
      (match_dup 6)])
1153
   (set (match_dup 0) (reg:SI 0))]
1154
  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
1155
   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
1156
  [(set_attr "type" "fp_sfunc")
1157
   (set_attr "length" "16,24")])
1158
 
1159
(define_insn "*udivsi3_2"
1160
  [(match_parallel 1 "float_operation"
1161
     [(set (reg:SI 0) (udiv:SI (reg:SI 0) (reg:SI 1)))
1162
      (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1163
      (clobber (reg:SI 1))
1164
      (clobber (reg:SI GPR_IP))
1165
      (clobber (reg:DI GPR_16))
1166
      (clobber (reg:SI GPR_18))
1167
      (clobber (reg:SI GPR_LR))
1168
      (clobber (reg:CC CC_REGNUM))
1169
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1170
  ""
1171
  "%f0"
1172
  [(set_attr "type" "fp_sfunc")])
1173
 
1174
(define_expand "modsi3"
1175
  [(parallel
1176
     [(set (match_operand:SI 0 "move_dest_operand" "")
1177
           (mod:SI (match_operand:SI 1 "move_src_operand" "")
1178
                   (match_operand:SI 2 "move_src_operand" "")))
1179
      (use (match_dup 3))
1180
      (clobber (reg:SI 0))
1181
      (clobber (reg:SI 1))
1182
      (clobber (reg:SI 2))
1183
      (clobber (reg:SI GPR_IP))
1184
      (clobber (reg:DI GPR_16))
1185
      (clobber (reg:DI GPR_18))
1186
      (clobber (reg:SI GPR_LR))
1187
      (clobber (reg:CC CC_REGNUM))
1188
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1189
  ""
1190
  "operands[3] = sfunc_symbol (\"__modsi3\");")
1191
 
1192
;; Before reload, keep the hard reg usage to clobbers so that the loop
1193
;; optimizers can more easily move this insn.
1194
(define_insn_and_split "*modsi3_1"
1195
  [(match_parallel 4 "float_operation"
1196
     [(set (match_operand:SI 0 "move_dest_operand" "=r,r")
1197
           (mod:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")
1198
                   (match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))
1199
      (use (match_operand:SI 3 "call_address_operand" "Csy,r"))
1200
      (clobber (reg:SI 0))
1201
      (clobber (reg:SI 1))
1202
      (clobber (reg:SI 2))
1203
      (clobber (reg:SI GPR_IP))
1204
      (clobber (reg:DI GPR_16))
1205
      (clobber (reg:DI GPR_18))
1206
      (clobber (reg:SI GPR_LR))
1207
      (clobber (reg:CC CC_REGNUM))
1208
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1209
  ""
1210
  "#"
1211
  "&& reload_completed"
1212
  [(set (reg:SI 0) (match_dup 1))
1213
   (set (reg:SI 1) (match_dup 2))
1214
   (parallel
1215
     [(set (reg:SI 0) (mod:SI (reg:SI 0) (reg:SI 1)))
1216
      (use (match_dup 3))
1217
      (clobber (reg:SI 2))
1218
      (clobber (reg:SI GPR_IP))
1219
      (clobber (reg:DI GPR_16))
1220
      (clobber (reg:DI GPR_18))
1221
      (clobber (reg:SI GPR_LR))
1222
      (clobber (reg:CC CC_REGNUM))
1223
      (clobber (reg:CC_FP CCFP_REGNUM))
1224
      (match_dup 5)
1225
      (match_dup 6)])
1226
   (set (match_dup 0) (reg:SI 0))]
1227
  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
1228
   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
1229
  [(set_attr "type" "fp_sfunc")
1230
   (set_attr "length" "16,24")])
1231
 
1232
(define_insn "*modsi3_2"
1233
  [(match_parallel 1 "float_operation"
1234
     [(set (reg:SI 0) (mod:SI (reg:SI 0) (reg:SI 1)))
1235
      (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1236
      (clobber (reg:SI 2))
1237
      (clobber (reg:SI GPR_IP))
1238
      (clobber (reg:DI GPR_16))
1239
      (clobber (reg:DI GPR_18))
1240
      (clobber (reg:SI GPR_LR))
1241
      (clobber (reg:CC CC_REGNUM))
1242
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1243
  ""
1244
  "%f0"
1245
  [(set_attr "type" "fp_sfunc")])
1246
 
1247
(define_expand "umodsi3"
1248
  [(parallel
1249
     [(set (match_operand:SI 0 "move_dest_operand" "")
1250
           (umod:SI (match_operand:SI 1 "move_src_operand" "")
1251
                    (match_operand:SI 2 "move_src_operand" "")))
1252
      (use (match_dup 3))
1253
      (clobber (reg:SI 0))
1254
      (clobber (reg:SI 1))
1255
      (clobber (reg:SI 2))
1256
      (clobber (reg:SI GPR_IP))
1257
      (clobber (reg:DI GPR_16))
1258
      (clobber (reg:SI GPR_LR))
1259
      (clobber (reg:CC CC_REGNUM))
1260
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1261
  ""
1262
  "operands[3] = sfunc_symbol (\"__umodsi3\");")
1263
 
1264
;; Before reload, keep the hard reg usage to clobbers so that the loop
1265
;; optimizers can more easily move this insn.
1266
(define_insn_and_split "*umodsi3_1"
1267
  [(match_parallel 4 "float_operation"
1268
     [(set (match_operand:SI 0 "move_dest_operand" "=r,r")
1269
           (umod:SI (match_operand:SI 1 "move_src_operand" "rU16m,rU16mCal")
1270
                    (match_operand:SI 2 "move_src_operand" "rU16m,rU16mCal")))
1271
      (use (match_operand:SI 3 "call_address_operand" "Csy,r"))
1272
      (clobber (reg:SI 0))
1273
      (clobber (reg:SI 1))
1274
      (clobber (reg:SI 2))
1275
      (clobber (reg:SI GPR_IP))
1276
      (clobber (reg:DI GPR_16))
1277
      (clobber (reg:SI GPR_LR))
1278
      (clobber (reg:CC CC_REGNUM))
1279
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1280
  ""
1281
  "#"
1282
  "&& reload_completed"
1283
  [(set (reg:SI 0) (match_dup 1))
1284
   (set (reg:SI 1) (match_dup 2))
1285
   (parallel
1286
     [(set (reg:SI 0) (umod:SI (reg:SI 0) (reg:SI 1)))
1287
      (use (match_dup 3))
1288
      (clobber (reg:SI 2))
1289
      (clobber (reg:SI GPR_IP))
1290
      (clobber (reg:DI GPR_16))
1291
      (clobber (reg:SI GPR_LR))
1292
      (clobber (reg:CC CC_REGNUM))
1293
      (clobber (reg:CC_FP CCFP_REGNUM))
1294
      (match_dup 5)
1295
      (match_dup 6)])
1296
   (set (match_dup 0) (reg:SI 0))]
1297
  "operands[5] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
1298
   operands[6] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);"
1299
  [(set_attr "type" "fp_sfunc")
1300
   (set_attr "length" "16,24")])
1301
 
1302
(define_insn "*umodsi3_2"
1303
  [(match_parallel 1 "float_operation"
1304
     [(set (reg:SI 0) (umod:SI (reg:SI 0) (reg:SI 1)))
1305
      (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1306
      (clobber (reg:SI 2))
1307
      (clobber (reg:SI GPR_IP))
1308
      (clobber (reg:DI GPR_16))
1309
      (clobber (reg:SI GPR_LR))
1310
      (clobber (reg:CC CC_REGNUM))
1311
      (clobber (reg:CC_FP CCFP_REGNUM))])]
1312
  ""
1313
  "%f0"
1314
  [(set_attr "type" "fp_sfunc")])
1315
 
1316
; Disable interrupts.
1317
; Any earlier values read from CONFIG_REGNUM are out of date, since interrupts
1318
; might have changed settings that we do not want to mess with.
1319
(define_insn "gid"
1320
  [(set (reg:SI CONFIG_REGNUM)
1321
        (unspec_volatile:SI [(const_int 0)] UNSPECV_GID))]
1322
  ""
1323
  "gid"
1324
  [(set_attr "type" "flow")])
1325
 
1326
; Enable interrupts.
1327
; Present CONTROL_REGNUM here to make sure it is live before the
1328
; actual uses in floating point insns / calls are inserted.
1329
; FWIW, interrupts also do mind what is in the control register.
1330
(define_insn "gie"
1331
  [(unspec_volatile [(reg:SI CONFIG_REGNUM)] UNSPECV_GIE)]
1332
  ""
1333
  "gie"
1334
  [(set_attr "type" "flow")])
1335
 
1336
; Floating point instructions require manipulating the control register.
1337
; Manipulating the control register needs aritmetic.
1338
; Arithmetic clobbers flags.
1339
; The flags are in the status register, which also contains the alternate
1340
; flag and the interrupt enable/disable bits.
1341
; saving/restoring status and mixing up the order with gid/gie could
1342
; lead to disaster.
1343
; Usually, saving/restoring the status is unnecessary, and will be optimized
1344
; away.  But when we really need it, we must make sure that we don't change
1345
; anything but the flags.
1346
; N.B.: We could make the constant easier to load by inverting it, but
1347
; then we'd need to clobber the saved value - and that would make optimizing
1348
; away unneeded saves/restores harder / less likely.
1349
(define_expand "movcc"
1350
  [(parallel [(set (match_operand:CC 0 "cc_move_operand"  "")
1351
                   (match_operand:CC 1 "cc_move_operand" ""))
1352
              (use (match_dup 2))
1353
              (clobber (match_scratch:SI 3                 "=X, &r"))])]
1354
  ""
1355
  "operands[2] = gen_int_mode (~0x10f0, SImode);")
1356
 
1357
(define_insn "*movcc_i"
1358
  [(set (match_operand:CC 0 "cc_move_operand"  "=r,Rcc")
1359
        (match_operand:CC 1 "cc_move_operand" "Rcc,  r"))
1360
   (use (match_operand:SI 2 "nonmemory_operand"  "X,  r"))
1361
   (clobber (match_scratch:SI 3                 "=X, &r"))]
1362
  ""
1363
  "@
1364
   movfs %0,status
1365
   movfs %3,status\;eor %3,%3,%1\;and %3,%3,%2\;eor %3,%3,%1\;movts status,%3"
1366
  [(set_attr "type" "flow")
1367
   (set_attr "length" "20,4")])
1368
 
1369
(define_insn_and_split "set_fp_mode"
1370
  [(set (reg:SI FP_NEAREST_REGNUM)
1371
        (match_operand:SI 0 "set_fp_mode_operand" "rCfm"))
1372
   (set (reg:SI FP_TRUNCATE_REGNUM) (match_dup 0))
1373
   (set (reg:SI FP_ANYFP_REGNUM)
1374
        (match_operand:SI 1 "set_fp_mode_operand" "rCfm"))
1375
   (use (match_operand:SI 2 "gpr_operand" "r"))
1376
   (clobber (reg:CC CC_REGNUM))
1377
   (clobber (match_scratch:SI 3 "=&r"))]
1378
  ""
1379
  "#"
1380
  "reload_completed || !rtx_equal_p (operands[0], operands[1])"
1381
  [(const_int 0)]
1382
{
1383
  if (!reload_completed)
1384
    emit_note (NOTE_INSN_DELETED);
1385
  else
1386
    epiphany_expand_set_fp_mode (operands);
1387
  DONE;
1388
})
1389
 
1390
 
1391
;; Boolean instructions.
1392
;;
1393
;; We don't define the DImode versions as expand_binop does a good enough job.
1394
 
1395
(define_insn "andsi3"
1396
  [(set (match_operand:SI 0 "gpr_operand" "=r")
1397
        (and:SI (match_operand:SI 1 "gpr_operand" "r")
1398
                (match_operand:SI 2 "gpr_operand" "r")))
1399
   (clobber (reg:CC CC_REGNUM))]
1400
  ""
1401
  "and %0,%1,%2")
1402
 
1403
(define_insn "iorsi3"
1404
  [(set (match_operand:SI 0 "gpr_operand" "=r")
1405
        (ior:SI (match_operand:SI 1 "gpr_operand" "r")
1406
                (match_operand:SI 2 "gpr_operand" "r")))
1407
   (clobber (reg:CC CC_REGNUM))]
1408
  ""
1409
  "orr %0,%1,%2")
1410
 
1411
(define_insn "xorsi3"
1412
  [(set (match_operand:SI 0 "gpr_operand" "=r")
1413
        (xor:SI (match_operand:SI 1 "gpr_operand" "r")
1414
                (match_operand:SI 2 "gpr_operand" "r")))
1415
   (clobber (reg:CC CC_REGNUM))]
1416
  ""
1417
  "eor %0,%1,%2")
1418
 
1419
(define_expand "one_cmplsi2"
1420
  [(set (match_operand:SI 0 "gpr_operand" "")
1421
        (xor:SI (match_operand:SI 1 "gpr_operand" "")
1422
                (match_dup 2)))]
1423
  ""
1424
{
1425
  if (epiphany_m1reg >= 0)
1426
    emit_insn (gen_one_cmplsi2_i (operands[0], operands[1]));
1427
  else
1428
    emit_insn (gen_xorsi3 (operands[0], operands[1],
1429
                           force_reg (SImode, GEN_INT (-1))));
1430
  DONE;
1431
})
1432
 
1433
; Note that folding this pattern into the xorsi3 pattern would make combine
1434
; less effective.
1435
(define_insn "one_cmplsi2_i"
1436
  [(set (match_operand:SI 0 "gpr_operand" "=r")
1437
        (not:SI (match_operand:SI 1 "gpr_operand" "r")))
1438
   (clobber (reg:CC CC_REGNUM))]
1439
  "epiphany_m1reg >= 0"
1440
  "eor %0,%1,%-")
1441
 
1442
;; Shift instructions.
1443
;; In principle we could support arbitrary symbolic values as shift constant
1444
;; (truncating the value appropriately), but that would require a suitable
1445
;; relocation and assembler & linker support.
1446
(define_insn "ashrsi3"
1447
  [(set (match_operand:SI 0 "gpr_operand" "=r,r")
1448
        (ashiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")
1449
                     (match_operand:SI 2 "arith_operand" "r,K")))
1450
   (clobber (reg:CC CC_REGNUM))]
1451
  ""
1452
  "asr %0,%1,%2"
1453
  [(set_attr "length" "4")
1454
   (set_attr "type" "shift")])
1455
 
1456
(define_insn "ashrsi3_tst"
1457
  [(set (reg:CC CC_REGNUM)
1458
        (compare:CC
1459
          (ashiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")
1460
                       (match_operand:SI 2 "arith_operand" "r,K"))
1461
        (const_int 0)))
1462
   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1463
        (ashiftrt:SI (match_dup 1) (match_dup 2)))]
1464
  ""
1465
  "asr %0,%1,%2"
1466
  [(set_attr "length" "4")
1467
   (set_attr "type" "shift")])
1468
 
1469
;; Logical Shift Right
1470
(define_insn "lshrsi3"
1471
  [(set (match_operand:SI 0 "gpr_operand" "=r,r")
1472
        (lshiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")
1473
                     (match_operand:SI 2 "arith_operand" "r,K")))
1474
   (clobber (reg:CC CC_REGNUM))]
1475
  ""
1476
  "lsr %0,%1,%2"
1477
  [(set_attr "length" "4")
1478
   (set_attr "type" "shift")])
1479
 
1480
(define_insn "lshrsi3_tst"
1481
  [(set (reg:CC CC_REGNUM)
1482
        (compare:CC
1483
          (lshiftrt:SI (match_operand:SI 1 "gpr_operand" "r,r")
1484
                       (match_operand:SI 2 "arith_operand" "r,K"))
1485
        (const_int 0)))
1486
   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1487
        (lshiftrt:SI (match_dup 1) (match_dup 2)))]
1488
  ""
1489
  "lsr %0,%1,%2"
1490
  [(set_attr "length" "4")
1491
   (set_attr "type" "shift")])
1492
 
1493
;; Logical/Arithmetic Shift Left
1494
(define_insn "ashlsi3"
1495
  [(set (match_operand:SI 0 "gpr_operand" "=r,r")
1496
        (ashift:SI (match_operand:SI 1 "gpr_operand" "r,r")
1497
                   (match_operand:SI 2 "arith_operand" "r,K")))
1498
   (clobber (reg:CC CC_REGNUM))]
1499
  ""
1500
  "lsl %0,%1,%2"
1501
  [(set_attr "length" "4")
1502
   (set_attr "type" "shift")])
1503
 
1504
(define_insn "*ashlsi_btst"
1505
  [(set (reg:CC_N_NE CC_REGNUM)
1506
        (compare:CC_N_NE
1507
          (zero_extract:SI (match_operand:SI 1 "gpr_operand" "r")
1508
                           (const_int 1)
1509
                           (match_operand 2 "const_int_operand" "K"))
1510
          (const_int 0)))
1511
   (clobber (match_scratch:SI 0 "=r"))]
1512
  ""
1513
{
1514
  rtx xop[3];
1515
 
1516
  xop[0] = operands[0];
1517
  xop[1] = operands[1];
1518
  xop[2] = GEN_INT (31-INTVAL (operands[2]));
1519
  output_asm_insn ("lsl %0,%1,%2", xop);
1520
  return "";
1521
})
1522
 
1523
;; zero extensions
1524
(define_insn_and_split "zero_extendqisi2"
1525
  [(set (match_operand:SI 0 "register_operand" "=r,r")
1526
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))
1527
   (clobber (reg:CC CC_REGNUM))]
1528
  ""
1529
  "@
1530
   #
1531
   ldrb %0,%1"
1532
  "reload_completed
1533
   ? true_regnum (operands[1]) >= 0
1534
   : REG_P (operands[1]) && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER"
1535
  [(parallel [(set (match_dup 0) (ashift:SI (match_dup 2) (const_int 24)))
1536
              (clobber (reg:CC CC_REGNUM))])
1537
   (parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))
1538
              (clobber (reg:CC CC_REGNUM))])]
1539
  "operands[2] = simplify_gen_subreg (SImode, operands[1], QImode, 0);")
1540
 
1541
(define_insn "zero_extendhisi2"
1542
  [(set (match_operand:SI 0 "register_operand" "=r,r")
1543
        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,m")))]
1544
  ""
1545
  "@
1546
   movt %0, 0
1547
   ldrh %0,%c1")
1548
 
1549
 
1550
;; Compare instructions.
1551
 
1552
(define_insn "cmpsi_cc_insn"
1553
  [(set (reg:CC CC_REGNUM)
1554
        (compare:CC (match_operand:SI 0 "add_reg_operand" "r,r")
1555
                    (match_operand:SI 1 "arith_operand" "r,L")))
1556
   (clobber (match_scratch:SI 2 "=r,r"))]
1557
  ""
1558
  "sub %2,%0,%1"
1559
  [(set_attr "type" "compare")])
1560
 
1561
(define_insn "sub_f"
1562
  [(set (reg:CC CC_REGNUM)
1563
        (compare:CC (match_operand:SI 1 "gpr_operand"  "r,r")
1564
                    (match_operand:SI 2 "arith_operand" "r,L")))
1565
   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1566
        (minus:SI (match_dup 1) (match_dup 2)))]
1567
  ""
1568
  "sub %0,%1,%2"
1569
  [(set_attr "type" "compare")])
1570
 
1571
(define_insn "*sub_f_add_imm"
1572
  [(set (reg:CC CC_REGNUM)
1573
        (compare:CC (match_operand:SI 1 "gpr_operand"  "r")
1574
                    (match_operand:SI 2 "arith_int_operand" "L")))
1575
   (set (match_operand:SI 0 "gpr_operand" "=r")
1576
        (plus:SI (match_dup 1) (match_operand:SI 3 "const_int_operand" "L")))]
1577
  "INTVAL (operands[2]) == -INTVAL (operands[3])"
1578
  "sub %0,%1,%2"
1579
  [(set_attr "type" "compare")])
1580
 
1581
(define_expand "abssi2"
1582
  [(set (match_dup 2) (const_int 0))
1583
   (parallel [(set (reg:CC CC_REGNUM)
1584
                   (compare:CC (match_dup 2)
1585
                               (match_operand:SI 1 "nonmemory_operand" "")))
1586
              (set (match_dup 3)
1587
                   (minus:SI (match_dup 2) (match_dup 1)))])
1588
   (set (match_operand:SI 0 "gpr_operand" "=r")
1589
        (if_then_else:SI (gt:SI (reg:CC CC_REGNUM) (const_int 0))
1590
                         (match_dup 3)
1591
                         (match_dup 1)))]
1592
  "TARGET_CMOVE"
1593
  "operands[2] = gen_reg_rtx (SImode); operands[3] = gen_reg_rtx (SImode);")
1594
 
1595
(define_insn "*add_c"
1596
  [(set (reg:CC_C_LTU CC_REGNUM)
1597
        (compare:CC_C_LTU
1598
          (plus:SI (match_operand:SI 1 "gpr_operand" "%r,r")
1599
                   (match_operand:SI 2 "arith_operand" "r,L"))
1600
          (match_dup 1)))
1601
   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1602
        (plus:SI (match_dup 1) (match_dup 2)))]
1603
  ""
1604
  "add %0,%1,%2"
1605
  [(set_attr "type" "compare")])
1606
 
1607
(define_insn "*add_c_rev"
1608
  [(set (reg:CC_C_LTU CC_REGNUM)
1609
        (compare:CC_C_LTU
1610
          (plus:SI (match_operand:SI 1 "gpr_operand" "%r,r")
1611
                   (match_operand:SI 2 "arith_operand" "r,L"))
1612
          (match_dup 1)))
1613
   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1614
        (plus:SI (match_dup 2) (match_dup 1)))]
1615
  ""
1616
  "add %0,%1,%2"
1617
  [(set_attr "type" "compare")])
1618
 
1619
(define_insn "*sub_c"
1620
  [(set (reg:CC_C_GTU CC_REGNUM)
1621
        (compare:CC_C_GTU
1622
          (minus:SI (match_operand:SI 1 "gpr_operand"  "r,r")
1623
                    (match_operand:SI 2 "arith_operand" "r,L"))
1624
          (match_dup 1)))
1625
   (set (match_operand:SI 0 "gpr_operand" "=r,r")
1626
        (minus:SI (match_dup 1) (match_dup 2)))]
1627
  ""
1628
  "sub %0,%1,%2"
1629
  [(set_attr "type" "compare")])
1630
 
1631
(define_insn "*sub_c_void"
1632
  [(set (reg:CC_C_GTU CC_REGNUM)
1633
        (compare:CC_C_GTU
1634
          (minus:SI (match_operand:SI 1 "gpr_operand"  "r,r")
1635
                    (match_operand:SI 2 "arith_operand" "r,L"))
1636
          (match_dup 1)))
1637
   (clobber (match_scratch:SI 0 "=r,r"))]
1638
  ""
1639
  "sub %0,%1,%2"
1640
  [(set_attr "type" "compare")])
1641
 
1642
; floating point comparisons
1643
 
1644
(define_insn "*cmpsf_cc_insn"
1645
  [(match_parallel 3 "float_operation"
1646
     [(set (reg:CC_FP CCFP_REGNUM)
1647
           (compare:CC_FP (match_operand:SF 0 "gpr_operand" "r")
1648
                          (match_operand:SF 1 "gpr_operand" "r")))
1649
      (clobber (match_scratch:SF 2 "=r"))])]
1650
  "!TARGET_SOFT_CMPSF"
1651
  "fsub %2,%0,%1"
1652
  [(set_attr "type" "fp")
1653
   (set_attr "fp_mode" "round_unknown")])
1654
 
1655
;; ??? do we have to relax the operand0 predicate to immediate_operand
1656
;; to allow the rtl loop optimizer to generate comparisons?  OTOH
1657
;; we want call_address_operand to enforce valid operands so that
1658
;; combine won't do silly things, allowing instruction scheduling to do
1659
;; a proper job.
1660
(define_insn "*cmpsf_eq"
1661
  [(set (reg:CC_FP_EQ CC_REGNUM) (compare:CC_FP_EQ (reg:SF 0) (reg:SF 1)))
1662
   (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1663
   (clobber (reg:SI GPR_IP))
1664
   (clobber (reg:SI GPR_LR))]
1665
  "TARGET_SOFT_CMPSF"
1666
  "%f0"
1667
  [(set_attr "type" "sfunc")])
1668
 
1669
(define_insn "*cmpsf_gte"
1670
  [(set (reg:CC_FP_GTE CC_REGNUM) (compare:CC_FP_GTE (reg:SF 0) (reg:SF 1)))
1671
   (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1672
   (clobber (reg:SI GPR_IP))
1673
   (clobber (reg:SI GPR_LR))]
1674
  "TARGET_SOFT_CMPSF"
1675
  "%f0"
1676
  [(set_attr "type" "sfunc")])
1677
 
1678
(define_insn "*cmpsf_ord"
1679
  [(set (reg:CC_FP_ORD CC_REGNUM) (compare:CC_FP_ORD (reg:SF 0) (reg:SF 1)))
1680
   (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1681
   (clobber (reg:SI GPR_IP))
1682
   (clobber (reg:SI GPR_16))
1683
   (clobber (reg:SI GPR_LR))]
1684
  "TARGET_SOFT_CMPSF"
1685
  "%f0"
1686
  [(set_attr "type" "sfunc")])
1687
 
1688
(define_insn "*cmpsf_uneq"
1689
  [(set (reg:CC_FP_UNEQ CC_REGNUM) (compare:CC_FP_UNEQ (reg:SF 0) (reg:SF 1)))
1690
   (use (match_operand:SI 0 "call_address_operand" "Csy,r"))
1691
   (clobber (reg:SI GPR_IP))
1692
   (clobber (reg:SI GPR_16))
1693
   (clobber (reg:SI GPR_LR))]
1694
  "TARGET_SOFT_CMPSF"
1695
  "%f0"
1696
  [(set_attr "type" "sfunc")])
1697
 
1698
;; conditional moves
1699
 
1700
(define_expand "movcc"
1701
  [(set (match_operand:WMODE 0 "gpr_operand" "")
1702
        (if_then_else:WMODE (match_operand 1 "comparison_operator" "")
1703
                            (match_operand:WMODE 2 "gpr_operand" "")
1704
                            (match_operand:WMODE 3 "gpr_operand" "")))]
1705
  "TARGET_CMOVE"
1706
{
1707
  rtx cmp_op0 = XEXP (operands[1], 0);
1708
  rtx cmp_op1 = XEXP (operands[1], 1);
1709
  enum machine_mode cmp_in_mode;
1710
  enum rtx_code code = GET_CODE (operands[1]);
1711
 
1712
  cmp_in_mode = GET_MODE (cmp_op0);
1713
  if (cmp_in_mode == VOIDmode)
1714
    cmp_in_mode = GET_MODE (cmp_op1);
1715
  if (cmp_in_mode == VOIDmode)
1716
    cmp_in_mode = SImode;
1717
  /* If the operands are a better match when reversed, swap them now.
1718
     This allows combine to see the proper comparison codes.  */
1719
  if (rtx_equal_p (operands[0], operands[2])
1720
      && !rtx_equal_p (operands[0], operands[3]))
1721
    {
1722
      rtx tmp = operands[2]; operands[2] = operands[3]; operands[3] = tmp;
1723
      code = (FLOAT_MODE_P (GET_MODE (cmp_op0))
1724
              ? reverse_condition_maybe_unordered (code)
1725
              : reverse_condition (code));
1726
    }
1727
 
1728
  if (proper_comparison_operator (operands[1], VOIDmode))
1729
    operands[1] = gen_rtx_fmt_ee (code, cmp_in_mode, cmp_op0, cmp_op1);
1730
  else
1731
    {
1732
      if (!currently_expanding_to_rtl)
1733
        {
1734
          /* ???  It would seem safest to FAIL here, but that would defeat
1735
             the purpose of having an if-conversion pass; its logic currently
1736
             assumes that the backend should be safe to insert condition code
1737
             setting instructions, as the same condition codes were presumably
1738
             set by the if-conversion input code.  */
1739
        }
1740
      /* What mode to give as first operand to gen_compare_reg here is
1741
         debatable.  VOIDmode would be minimalist; telling gen_compare_reg
1742
         to use the mode of CC_REGNUM (or putting it on the comparison
1743
         operator afterwards) is also a logical choice.  OTOH, by using
1744
         mode, we have mode combine opportunities with flag setting
1745
         operations - if we get some.  */
1746
      operands[1]
1747
        = gen_compare_reg (mode, code, cmp_in_mode, cmp_op0, cmp_op1);
1748
    }
1749
})
1750
 
1751
(define_insn "*movcc_insn"
1752
  [(set (match_operand:WMODE 0 "gpr_operand" "=r")
1753
        (if_then_else:WMODE (match_operator 3 "proper_comparison_operator"
1754
                              [(match_operand 4 "cc_operand") (const_int 0)])
1755
                            (match_operand:WMODE 1 "gpr_operand" "r")
1756
                            (match_operand:WMODE 2 "gpr_operand" "0")))]
1757
  "TARGET_CMOVE"
1758
  "mov%d3 %0,%1"
1759
  [(set_attr "type" "cmove")])
1760
 
1761
(define_peephole2
1762
  [(parallel [(set (match_operand:WMODE 0 "gpr_operand" "")
1763
                   (match_operand:WMODE 1 "" ""))
1764
              (clobber (match_operand 8 "cc_operand"))])
1765
   (match_operand 2 "" "")
1766
   (set (match_operand:WMODE2 3 "gpr_operand" "")
1767
        (match_operand:WMODE2 9 "gpr_operand" ""))
1768
   (set (match_dup 3)
1769
        (if_then_else:WMODE2 (match_operator 5 "proper_comparison_operator"
1770
                               [(match_operand 6 "cc_operand")
1771
                                (match_operand 7 "const0_operand")])
1772
                             (match_operand:WMODE2 4 "nonmemory_operand" "")
1773
                             (match_dup 3)))]
1774
  "REGNO (operands[0]) == REGNO (operands[9])
1775
   && peep2_reg_dead_p (3, operands[0])
1776
   && !reg_set_p (operands[0], operands[2])
1777
   && !reg_set_p (operands[3], operands[2])
1778
   && !reg_overlap_mentioned_p (operands[3], operands[2])"
1779
  [(parallel [(set (match_dup 10) (match_dup 1))
1780
              (clobber (match_dup 8))])
1781
   (match_dup 2)
1782
   (set (match_dup 3)
1783
        (if_then_else:WMODE2 (match_dup 5) (match_dup 4) (match_dup 3)))]
1784
{
1785
  operands[10] = simplify_gen_subreg (mode, operands[3],
1786
                                      mode, 0);
1787
  replace_rtx (operands[2], operands[9], operands[3]);
1788
  replace_rtx (operands[2], operands[0], operands[10]);
1789
  gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[2]));
1790
})
1791
 
1792
(define_peephole2
1793
  [(parallel [(set (match_operand 6 "cc_operand") (match_operand 2 "" ""))
1794
              (set (match_operand:WMODE 0 "gpr_operand" "")
1795
                   (match_operand:WMODE 1 "" ""))])
1796
   (set (match_operand:WMODE2 3 "gpr_operand" "")
1797
        (match_operand:WMODE2 4 "gpr_operand"))
1798
   (set (match_dup 3)
1799
        (if_then_else:WMODE2 (match_operator 5 "proper_comparison_operator"
1800
                               [(match_dup 6)
1801
                               (match_operand:WMODE 7 "const0_operand")])
1802
                            (match_operand:WMODE2 8 "gpr_operand")
1803
                            (match_dup 3)))]
1804
  "REGNO (operands[0]) == REGNO (operands[8])
1805
   && REVERSIBLE_CC_MODE (GET_MODE (operands[6]))
1806
   && peep2_reg_dead_p (3, operands[6])
1807
   && peep2_reg_dead_p (3, operands[0])
1808
   && !reg_overlap_mentioned_p (operands[4], operands[3])"
1809
  [(parallel [(set (match_dup 6) (match_dup 2))
1810
              (set (match_dup 9) (match_dup 1))])
1811
   (set (match_dup 3)
1812
        (if_then_else:WMODE2 (match_dup 5) (match_dup 4) (match_dup 3)))]
1813
  "
1814
{
1815
  operands[5]
1816
    = gen_rtx_fmt_ee (REVERSE_CONDITION (GET_CODE (operands[5]),
1817
                                         GET_MODE (operands[6])),
1818
                      GET_MODE (operands[5]), operands[6], operands[7]);
1819
  operands[9] = simplify_gen_subreg (mode, operands[3],
1820
                                     mode, 0);
1821
}")
1822
 
1823
;; These control RTL generation for conditional jump insns
1824
 
1825
;; To signal to can_compare_p that the cbranchs?4 patterns work,
1826
;; they must allow const0_rtx for both comparison operands
1827
(define_expand "cbranchsi4"
1828
  [(set (reg CC_REGNUM)
1829
        (compare (match_operand:SI 1 "add_operand" "")
1830
                 (match_operand:SI 2 "arith_operand" "")))
1831
   (set (pc)
1832
        (if_then_else
1833
              (match_operator 0 "ordered_comparison_operator" [(reg CC_REGNUM)
1834
                                                               (const_int 0)])
1835
              (label_ref (match_operand 3 "" ""))
1836
              (pc)))]
1837
  ""
1838
{
1839
  rtx cmp = gen_compare_reg (VOIDmode, GET_CODE (operands[0]), SImode,
1840
                             operands[1], operands[2]);
1841
  emit_jump_insn (gen_branch_insn (operands[3], cmp, XEXP (cmp, 0)));
1842
  DONE;
1843
})
1844
 
1845
(define_expand "cbranchsf4"
1846
  [(set (reg CC_REGNUM)
1847
        (compare (match_operand:SF 1 "arith_operand" "")
1848
                 (match_operand:SF 2 "arith_operand" "")))
1849
   (set (pc)
1850
        (if_then_else
1851
              (match_operator 0 "comparison_operator" [(reg CC_REGNUM)
1852
                                                       (const_int 0)])
1853
              (label_ref (match_operand 3 "" ""))
1854
              (pc)))]
1855
  ""
1856
{
1857
  rtx cmp = gen_compare_reg (VOIDmode, GET_CODE (operands[0]), SFmode,
1858
                             operands[1], operands[2]);
1859
  emit_jump_insn (gen_branch_insn (operands[3], cmp, XEXP (cmp, 0)));
1860
  DONE;
1861
})
1862
 
1863
;; Now match both normal and inverted jump.
1864
 
1865
(define_insn "branch_insn"
1866
  [(set (pc)
1867
        (if_then_else (match_operator 1 "proper_comparison_operator"
1868
                                      [(match_operand 2 "cc_operand")
1869
                                       (const_int 0)])
1870
                      (label_ref (match_operand 0 "" ""))
1871
                      (pc)))]
1872
  ""
1873
  "b%d1 %l0"
1874
  [(set_attr "type" "branch")])
1875
 
1876
(define_insn "*rev_branch_insn"
1877
  [(set (pc)
1878
        (if_then_else (match_operator 1 "proper_comparison_operator"
1879
                                      [(reg CC_REGNUM) (const_int 0)])
1880
                      (pc)
1881
                      (label_ref (match_operand 0 "" ""))))]
1882
  ""
1883
  "b%D1 %l0"
1884
  [(set_attr "type" "branch")])
1885
 
1886
;; Unconditional and other jump instructions.
1887
 
1888
(define_insn "jump"
1889
  [(set (pc) (label_ref (match_operand 0 "" "")))]
1890
  ""
1891
  "b %l0"
1892
  [(set_attr "type" "uncond_branch")])
1893
 
1894
(define_insn "indirect_jump"
1895
  [(set (pc) (match_operand:SI 0 "gpr_operand" "r"))]
1896
  ""
1897
  "jr %0"
1898
  [(set_attr "type" "uncond_branch")])
1899
 
1900
(define_expand "tablejump"
1901
  [(parallel [(set (pc) (match_operand:SI 0 "gpr_operand" ""))
1902
              (use (label_ref (match_operand 1 "" "")))])]
1903
  ""
1904
{
1905
  /* In PIC mode, the table entries are stored PC relative.
1906
     Convert the relative address to an absolute address.  */
1907
  if (flag_pic)
1908
    {
1909
      rtx op1 = gen_rtx_LABEL_REF (Pmode, operands[1]);
1910
 
1911
      operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
1912
                                         op1, NULL_RTX, 0, OPTAB_DIRECT);
1913
    }
1914
})
1915
 
1916
(define_insn "*tablejump_internal"
1917
  [(set (pc) (match_operand:SI 0 "gpr_operand" "r"))
1918
   (use (label_ref (match_operand 1 "" "")))]
1919
  ""
1920
  "jr %0;"
1921
  [(set_attr "type" "uncond_branch")])
1922
 
1923
(define_insn "*tablejump_hi_internal"
1924
  [(set (pc) (match_operand:HI 0 "gpr_operand" "r"))
1925
   (use (label_ref (match_operand 1 "" "")))]
1926
  "optimize_size && TARGET_SMALL16"
1927
  "jr %0;"
1928
  [(set_attr "type" "uncond_branch")])
1929
 
1930
 
1931
(define_expand "call"
1932
  ;; operands[1] is stack_size_rtx
1933
  ;; operands[2] is next_arg_register
1934
  [(parallel [(call (match_operand:SI 0 "call_operand" "")
1935
                    (match_operand 1 "" ""))
1936
             (clobber (reg:SI GPR_LR))])]
1937
  ""
1938
{
1939
  bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[0]);
1940
 
1941
  if (!call_operand (operands[1], VOIDmode))
1942
    operands[0]
1943
      = change_address (operands[0], VOIDmode,
1944
                        copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
1945
  if (epiphany_uninterruptible_p (current_function_decl)
1946
      != target_uninterruptible)
1947
    {
1948
      emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());
1949
      emit_call_insn
1950
        (gen_rtx_PARALLEL
1951
          (VOIDmode,
1952
           gen_rtvec (2, gen_rtx_CALL (VOIDmode, operands[0], operands[1]),
1953
                         gen_rtx_CLOBBER (VOIDmode,
1954
                                          gen_rtx_REG (SImode, GPR_LR)))));
1955
      emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());
1956
      DONE;
1957
    }
1958
})
1959
 
1960
(define_insn "*call_i"
1961
  [(match_parallel 2 "float_operation"
1962
     [(call (mem:SI (match_operand:SI 0 "call_address_operand" "Csy,r"))
1963
            (match_operand 1 "" ""))
1964
      (clobber (reg:SI GPR_LR))])]
1965
  ""
1966
  "%f0"
1967
  [(set_attr "type" "call")])
1968
 
1969
(define_expand "sibcall"
1970
  ;; operands[1] is stack_size_rtx
1971
  ;; operands[2] is next_arg_register
1972
  [(parallel [(call (match_operand:SI 0 "call_operand" "")
1973
                    (match_operand 1 "" ""))
1974
             (return)])]
1975
  ""
1976
{
1977
  bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[0]);
1978
 
1979
  if (!call_operand (operands[1], VOIDmode))
1980
    operands[0]
1981
      = change_address (operands[0], VOIDmode,
1982
                        copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
1983
  if (epiphany_uninterruptible_p (current_function_decl)
1984
      != target_uninterruptible)
1985
    {
1986
      emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());
1987
      emit_call_insn
1988
        (gen_rtx_PARALLEL
1989
          (VOIDmode,
1990
           gen_rtvec (2, gen_rtx_CALL (VOIDmode, operands[0], operands[1]),
1991
                         ret_rtx)));
1992
      emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());
1993
      DONE;
1994
    }
1995
})
1996
 
1997
(define_insn "*sibcall_i"
1998
  [(call (mem:SI (match_operand:SI 0 "call_address_operand" "Csy,Rsc"))
1999
         (match_operand 1 "" ""))
2000
   (return)]
2001
  ""
2002
  "@
2003
   b %0
2004
   jr %0"
2005
  [(set_attr "type" "call")])
2006
 
2007
(define_expand "call_value"
2008
  ;; operand 2 is stack_size_rtx
2009
  ;; operand 3 is next_arg_register
2010
  [(parallel [(set (match_operand 0 "gpr_operand" "=r")
2011
                   (call (match_operand:SI 1 "call_operand" "")
2012
                         (match_operand 2 "" "")))
2013
             (clobber (reg:SI GPR_LR))])]
2014
  ""
2015
{
2016
  bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[1]);
2017
 
2018
  if (!call_operand (operands[1], VOIDmode))
2019
    operands[1]
2020
      = change_address (operands[1], VOIDmode,
2021
                        copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
2022
  if (epiphany_uninterruptible_p (current_function_decl)
2023
      != target_uninterruptible)
2024
    {
2025
      emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());
2026
      emit_call_insn
2027
        (gen_rtx_PARALLEL
2028
          (VOIDmode,
2029
           gen_rtvec (2, gen_rtx_SET
2030
                           (VOIDmode, operands[0],
2031
                            gen_rtx_CALL (VOIDmode, operands[1], operands[2])),
2032
                         gen_rtx_CLOBBER (VOIDmode,
2033
                                          gen_rtx_REG (SImode, GPR_LR)))));
2034
      emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());
2035
      DONE;
2036
    }
2037
})
2038
 
2039
(define_insn "*call_value_i"
2040
  [(match_parallel 3 "float_operation"
2041
     [(set (match_operand 0 "gpr_operand" "=r,r")
2042
           (call (mem:SI (match_operand:SI 1 "call_address_operand" "Csy,r"))
2043
                 (match_operand 2 "" "")))
2044
      (clobber (reg:SI GPR_LR))])]
2045
  ""
2046
  "%f1"
2047
  [(set_attr "type" "call")
2048
   (set_attr "length" "4")])
2049
 
2050
(define_expand "sibcall_value"
2051
  ;; operand 2 is stack_size_rtx
2052
  ;; operand 3 is next_arg_register
2053
  [(parallel [(set (match_operand 0 "gpr_operand" "=r")
2054
                   (call (match_operand:SI 1 "call_operand" "")
2055
                         (match_operand 2 "" "")))
2056
             (return)])]
2057
  ""
2058
{
2059
  bool target_uninterruptible = epiphany_call_uninterruptible_p (operands[1]);
2060
 
2061
  if (!call_operand (operands[1], VOIDmode))
2062
    operands[1]
2063
      = change_address (operands[1], VOIDmode,
2064
                        copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
2065
  if (epiphany_uninterruptible_p (current_function_decl)
2066
      != target_uninterruptible)
2067
    {
2068
      emit_insn (target_uninterruptible ? gen_gid (): gen_gie ());
2069
      emit_call_insn
2070
        (gen_rtx_PARALLEL
2071
          (VOIDmode,
2072
           gen_rtvec (2, gen_rtx_SET
2073
                           (VOIDmode, operands[0],
2074
                            gen_rtx_CALL (VOIDmode, operands[1], operands[2])),
2075
                         ret_rtx)));
2076
      emit_insn (target_uninterruptible ? gen_gie (): gen_gid ());
2077
      DONE;
2078
    }
2079
})
2080
 
2081
(define_insn "*sibcall_value_i"
2082
  [(set (match_operand 0 "gpr_operand" "=r,r")
2083
        (call (mem:SI (match_operand:SI 1 "call_address_operand" "Csy,Rsc"))
2084
              (match_operand 2 "" "")))
2085
   (return)]
2086
  ""
2087
  "@
2088
   b %1
2089
   jr %1"
2090
  [(set_attr "type" "call")
2091
   (set_attr "length" "4")])
2092
 
2093
(define_expand "prologue"
2094
  [(pc)]
2095
  ""
2096
{
2097
  epiphany_expand_prologue ();
2098
  DONE;
2099
})
2100
 
2101
(define_expand "epilogue"
2102
  [(pc)]
2103
  ""
2104
{
2105
  epiphany_expand_epilogue (0);
2106
  DONE;
2107
})
2108
 
2109
(define_expand "sibcall_epilogue"
2110
  [(pc)]
2111
  ""
2112
{
2113
  epiphany_expand_epilogue (1);
2114
  DONE;
2115
})
2116
 
2117
; Since the demise of REG_N_SETS, it is no longer possible to find out
2118
; in the prologue / epilogue expanders how many times lr is set.
2119
; Using df_regs_ever_live_p to decide if lr needs saving means that
2120
; any explicit use of lr will cause it to be saved; hence we cannot
2121
; represent the blink use in return / sibcall instructions themselves, and
2122
; instead have to show it in EPILOGUE_USES.
2123
(define_insn "return_i"
2124
  [(return)]
2125
  "reload_completed"
2126
  "rts"
2127
  [(set_attr "type" "uncond_branch")])
2128
 
2129
(define_insn "return_internal_interrupt"
2130
  [(return)
2131
   (unspec_volatile [(const_int 0)] 1)]
2132
  ""
2133
  "rti"
2134
  [(set_attr "type" "uncond_branch")])
2135
 
2136
(define_insn "stack_adjust_add"
2137
  [(set (reg:SI GPR_SP)
2138
        (plus:SI (reg:SI GPR_SP) (match_operand:SI 0 "arith_operand" "rL")))
2139
   (clobber (reg:CC CC_REGNUM))
2140
   (clobber (reg:SI STATUS_REGNUM))
2141
   (clobber (match_operand:BLK 1 "memory_operand" "=m"))]
2142
  "reload_completed"
2143
  "add sp,sp,%0")
2144
 
2145
(define_insn "stack_adjust_mov"
2146
  [(set (reg:SI GPR_SP) (reg:SI GPR_FP))
2147
   (clobber (match_operand:BLK 0 "memory_operand" "=m"))]
2148
  "reload_completed"
2149
  "mov sp,fp"
2150
  [(set_attr "type" "move")])
2151
 
2152
(define_insn "stack_adjust_str"
2153
  [(set (match_operand 0 "stacktop_operand" "=m")
2154
        (match_operand 1 "any_gpr_operand" "r"))
2155
   (set (reg:SI GPR_SP)
2156
        (plus:SI (reg:SI GPR_SP) (match_operand:SI 2 "nonmemory_operand" "rn")))
2157
   (clobber (match_operand:BLK 3 "memory_operand" "=m"))]
2158
  "reload_completed"
2159
{
2160
  return (GET_MODE_SIZE (GET_MODE (operands[0])) <= 4
2161
          ? \"str %1,%0,%C2\" : \"strd %1,%0,%X2\");
2162
}
2163
  [(set_attr "type" "store")])
2164
 
2165
(define_insn "stack_adjust_ldr"
2166
  [(set (match_operand:SI 0 "gpr_operand" "=r")
2167
        (match_operand:SI 1 "stacktop_operand" "m"))
2168
   (set (reg:SI GPR_SP)
2169
        (plus:SI (reg:SI GPR_SP) (match_operand:SI 2 "nonmemory_operand" "rn")))
2170
   (clobber (match_operand:BLK 3 "memory_operand" "=m"))]
2171
  "reload_completed"
2172
  "ldr %0,%1,%C2"
2173
  [(set_attr "type" "load")])
2174
 
2175
;; Define some fake vector operations so that the vectorizer is happy to use
2176
;; 64 bit loads/stores.
2177
(define_expand "vec_unpacks_lo_v4hi"
2178
  [(match_operand:V2SI 0 "gpr_operand")
2179
   (match_operand:V4HI 1 "gpr_operand")]
2180
  ""
2181
{
2182
  rtx in = simplify_gen_subreg (SImode, operands[1], V4HImode, 0);
2183
  rtx outl = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);
2184
  rtx outh
2185
    = simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);
2186
 
2187
  if (reg_overlap_mentioned_p (outl, in))
2188
    in = copy_to_mode_reg (SImode, in);
2189
  emit_insn (gen_ashlsi3 (outl, in, GEN_INT (16)));
2190
  emit_insn (gen_ashrsi3 (outl, outl, GEN_INT (16)));
2191
  emit_insn (gen_ashrsi3 (outh, in, GEN_INT (16)));
2192
  DONE;
2193
})
2194
 
2195
(define_expand "vec_unpacks_hi_v4hi"
2196
  [(match_operand:V2SI 0 "gpr_operand")
2197
   (match_operand:V4HI 1 "gpr_operand")]
2198
  ""
2199
{
2200
  rtx in = simplify_gen_subreg (SImode, operands[1], V4HImode, UNITS_PER_WORD);
2201
  rtx outl = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);
2202
  rtx outh
2203
    = simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);
2204
 
2205
  if (reg_overlap_mentioned_p (outl, in))
2206
    in = copy_to_mode_reg (SImode, in);
2207
  emit_insn (gen_ashlsi3 (outl, in, GEN_INT (16)));
2208
  emit_insn (gen_ashrsi3 (outl, outl, GEN_INT (16)));
2209
  emit_insn (gen_ashrsi3 (outh, in, GEN_INT (16)));
2210
  DONE;
2211
})
2212
 
2213
(define_code_iterator addsub [plus minus])
2214
 
2215
(define_code_iterator alu_binop
2216
  [plus minus and ior xor])
2217
 
2218
(define_code_attr insn_opname
2219
  [(plus "add") (minus "sub") (mult "mul") (div "div")
2220
   (and "and") (ior "ior") (xor "xor")])
2221
 
2222
; You might think that this would work better as a define_expand, but
2223
; again lower_subreg pessimizes the code if it sees indiviudual operations.
2224
; We need to keep inputs and outputs as register pairs if we want to
2225
; get sensible register allocation for double-word load and store operations.
2226
(define_insn_and_split "v2si3"
2227
  [(set (match_operand:V2SI 0 "gpr_operand" "=r")
2228
        (alu_binop:V2SI (match_operand:V2SI 1 "gpr_operand" "r")
2229
                        (match_operand:V2SI 2 "gpr_operand" "r")))
2230
   (clobber (reg:CC CC_REGNUM))]
2231
  ""
2232
  "#"
2233
  "reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"
2234
  [(const_int 0)]
2235
{
2236
  rtx o0l, o0h, o1l, o1h, o2l, o2h;
2237
 
2238
  o0l = simplify_gen_subreg (SImode, operands[0], V2SImode, 0);
2239
  o0h = simplify_gen_subreg (SImode, operands[0], V2SImode, UNITS_PER_WORD);
2240
  o1l = simplify_gen_subreg (SImode, operands[1], V2SImode, 0);
2241
  o1h = simplify_gen_subreg (SImode, operands[1], V2SImode, UNITS_PER_WORD);
2242
  o2l = simplify_gen_subreg (SImode, operands[2], V2SImode, 0);
2243
  o2h = simplify_gen_subreg (SImode, operands[2], V2SImode, UNITS_PER_WORD);
2244
  if (reg_overlap_mentioned_p (o0l, o1h))
2245
    o1h = copy_to_mode_reg (SImode, o1h);
2246
  if (reg_overlap_mentioned_p (o0l, o2h))
2247
    o2h = copy_to_mode_reg (SImode, o2h);
2248
  emit_insn (gen_si3 (o0l, o1l, o2l));
2249
  emit_insn (gen_si3 (o0h, o1h, o2h));
2250
  DONE;
2251
}
2252
  [(set_attr "length" "8")])
2253
 
2254
(define_expand "v2sf3"
2255
  [(parallel
2256
     [(set (match_operand:V2SF 0 "gpr_operand" "")
2257
           (addsub:V2SF (match_operand:V2SF 1 "gpr_operand" "")
2258
                        (match_operand:V2SF 2 "gpr_operand" "")))
2259
      (clobber (reg:CC_FP CCFP_REGNUM))])])
2260
 
2261
(define_insn_and_split "v2sf3_i"
2262
  [(match_parallel 3 "float_operation"
2263
     [(set (match_operand:V2SF 0 "gpr_operand" "=r")
2264
           (addsub:V2SF (match_operand:V2SF 1 "gpr_operand" "r")
2265
                        (match_operand:V2SF 2 "gpr_operand" "r")))
2266
      (clobber (reg:CC_FP CCFP_REGNUM))])]
2267
  ""
2268
  "#"
2269
  "reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"
2270
  [(parallel
2271
     [(set (match_dup 4) (addsub:SF (match_dup 5) (match_dup 6)))
2272
      (clobber (reg:CC_FP CCFP_REGNUM))
2273
      (match_dup 10)
2274
      (match_dup 11)])
2275
   (parallel
2276
     [(set (match_dup 7) (addsub:SF (match_dup 8) (match_dup 9)))
2277
      (clobber (reg:CC_FP CCFP_REGNUM))
2278
      (match_dup 10)
2279
      (match_dup 11)])]
2280
{
2281
  operands[4] = simplify_gen_subreg (SFmode, operands[0], V2SFmode, 0);
2282
  operands[5] = simplify_gen_subreg (SFmode, operands[1], V2SFmode, 0);
2283
  operands[6] = simplify_gen_subreg (SFmode, operands[2], V2SFmode, 0);
2284
  operands[7]
2285
    = simplify_gen_subreg (SFmode, operands[0], V2SFmode, UNITS_PER_WORD);
2286
  operands[8]
2287
    = simplify_gen_subreg (SFmode, operands[1], V2SFmode, UNITS_PER_WORD);
2288
  operands[9]
2289
    = simplify_gen_subreg (SFmode, operands[2], V2SFmode, UNITS_PER_WORD);
2290
  if (!reload_completed)
2291
    {
2292
      if (reg_overlap_mentioned_p (operands[4], operands[8]))
2293
        operands[8] = copy_to_mode_reg (SFmode, operands[8]);
2294
      if (reg_overlap_mentioned_p (operands[4], operands[9]))
2295
        operands[9] = copy_to_mode_reg (SFmode, operands[9]);
2296
      emit_insn (gen_sf3 (operands[4], operands[5], operands[6]));
2297
      emit_insn (gen_sf3 (operands[7], operands[8], operands[9]));
2298
      DONE;
2299
    }
2300
  gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[8]));
2301
  gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[9]));
2302
  operands[10] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 2);
2303
  operands[11] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 1);
2304
}
2305
  [(set_attr "length" "8")
2306
   (set_attr "type" "fp")])
2307
 
2308
(define_expand "mul3"
2309
  [(parallel
2310
     [(set (match_operand:DWV2MODE 0 "gpr_operand" "")
2311
           (mult:DWV2MODE (match_operand:DWV2MODE 1 "gpr_operand" "")
2312
                          (match_operand:DWV2MODE 2 "gpr_operand" "")))
2313
      (clobber (reg:CC_FP CCFP_REGNUM))])])
2314
 
2315
(define_insn_and_split "mul3_i"
2316
  [(match_parallel 3 "float_operation"
2317
     [(set (match_operand:DWV2MODE 0 "gpr_operand" "=r")
2318
           (mult:DWV2MODE (match_operand:DWV2MODE 1 "gpr_operand" "r")
2319
                          (match_operand:DWV2MODE 2 "gpr_operand" "r")))
2320
      (clobber (reg:CC_FP CCFP_REGNUM))])]
2321
  ""
2322
  "#"
2323
  "reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"
2324
  [(parallel
2325
     [(set (match_dup 4) (mult: (match_dup 5) (match_dup 6)))
2326
      (clobber (reg:CC_FP CCFP_REGNUM))
2327
      (match_dup 10)
2328
      (match_dup 11)])
2329
   (parallel
2330
     [(set (match_dup 7) (mult: (match_dup 8) (match_dup 9)))
2331
      (clobber (reg:CC_FP CCFP_REGNUM))
2332
      (match_dup 10)
2333
      (match_dup 11)])]
2334
{
2335
  operands[4]
2336
    = simplify_gen_subreg (mode, operands[0], mode, 0);
2337
  operands[5]
2338
    = simplify_gen_subreg (mode, operands[1], mode, 0);
2339
  operands[6]
2340
    = simplify_gen_subreg (mode, operands[2], mode, 0);
2341
  operands[7] = simplify_gen_subreg (mode, operands[0],
2342
                                     mode, UNITS_PER_WORD);
2343
  operands[8] = simplify_gen_subreg (mode, operands[1],
2344
                                     mode, UNITS_PER_WORD);
2345
  operands[9] = simplify_gen_subreg (mode, operands[2],
2346
                                     mode, UNITS_PER_WORD);
2347
  if (!reload_completed)
2348
    {
2349
      if (reg_overlap_mentioned_p (operands[4], operands[8]))
2350
        operands[8] = copy_to_mode_reg (mode, operands[8]);
2351
      if (reg_overlap_mentioned_p (operands[4], operands[9]))
2352
        operands[9] = copy_to_mode_reg (mode, operands[9]);
2353
      emit_insn (gen_mul3 (operands[4], operands[5], operands[6]));
2354
      emit_insn (gen_mul3 (operands[7], operands[8], operands[9]));
2355
      DONE;
2356
    }
2357
  gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[8]));
2358
  gcc_assert (!reg_overlap_mentioned_p (operands[4], operands[9]));
2359
  operands[10] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 2);
2360
  operands[11] = XVECEXP (operands[3], 0, XVECLEN (operands[3], 0) - 1);
2361
}
2362
  [(set_attr "length" "8")
2363
   (set_attr "type" "")])
2364
 
2365
(define_insn_and_split "*fmadd_combine"
2366
  [(match_parallel 4 "float_operation"
2367
     [(set (match_operand:DWV2MODE 0 "gpr_operand" "=r")
2368
           (plus:DWV2MODE (mult:
2369
                                (match_operand: 1 "gpr_operand" "r")
2370
                                (match_operand: 2 "gpr_operand" "r"))
2371
                          (match_operand: 3 "gpr_operand" "0")))
2372
      (clobber (reg:CC_FP CCFP_REGNUM))])]
2373
  "TARGET_FUSED_MADD || mode == V2SImode"
2374
  "#"
2375
  "reload_completed || (epiphany_vect_align == 4 && TARGET_SPLIT_VECMOVE_EARLY)"
2376
  [(parallel
2377
     [(set (match_dup 5)
2378
           (plus: (mult: (match_dup 6) (match_dup 7))
2379
                              (match_dup 8)))
2380
      (clobber (reg:CC_FP CCFP_REGNUM))
2381
      (match_dup 13)
2382
      (match_dup 14)])
2383
   (parallel
2384
     [(set (match_dup 9)
2385
           (plus: (mult: (match_dup 10) (match_dup 11))
2386
                              (match_dup 12)))
2387
      (clobber (reg:CC_FP CCFP_REGNUM))
2388
      (match_dup 13)
2389
      (match_dup 14)])]
2390
{
2391
  operands[5]
2392
    = simplify_gen_subreg (mode, operands[0], mode, 0);
2393
  operands[6]
2394
    = simplify_gen_subreg (mode, operands[1], mode, 0);
2395
  operands[7]
2396
    = simplify_gen_subreg (mode, operands[2], mode, 0);
2397
  operands[8]
2398
    = simplify_gen_subreg (mode, operands[3], mode, 0);
2399
  operands[9] = simplify_gen_subreg (mode, operands[0],
2400
                                     mode, UNITS_PER_WORD);
2401
  operands[10] = simplify_gen_subreg (mode, operands[1],
2402
                                      mode, UNITS_PER_WORD);
2403
  operands[11] = simplify_gen_subreg (mode, operands[2],
2404
                                      mode, UNITS_PER_WORD);
2405
  operands[12] = simplify_gen_subreg (mode, operands[3],
2406
                                      mode, UNITS_PER_WORD);
2407
  if (!reload_completed)
2408
    {
2409
      if (reg_overlap_mentioned_p (operands[5], operands[10]))
2410
        operands[10] = copy_to_mode_reg (mode, operands[10]);
2411
      if (reg_overlap_mentioned_p (operands[5], operands[11]))
2412
        operands[11] = copy_to_mode_reg (mode, operands[11]);
2413
      if (reg_overlap_mentioned_p (operands[5], operands[12]))
2414
        operands[12] = copy_to_mode_reg (mode, operands[12]);
2415
      emit_insn (gen_madd (operands[5], operands[6], operands[7],
2416
                                       operands[8]));
2417
      emit_insn (gen_madd (operands[9], operands[10], operands[11],
2418
                                       operands[12]));
2419
      DONE;
2420
    }
2421
  gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[10]));
2422
  gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[11]));
2423
  gcc_assert (!reg_overlap_mentioned_p (operands[5], operands[12]));
2424
  operands[13] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 2);
2425
  operands[14] = XVECEXP (operands[4], 0, XVECLEN (operands[4], 0) - 1);
2426
}
2427
  [(set_attr "length" "8")
2428
   (set_attr "type" "")])
2429
 
2430
(define_expand "vec_set"
2431
  [(match_operand:DWV2MODE 0 "register_operand")
2432
   (match_operand: 1 "register_operand")
2433
   (match_operand 2 "const_int_operand" "")]
2434
  ""
2435
{
2436
  operands[0]
2437
    = simplify_gen_subreg (mode, operands[0], mode,
2438
                           UNITS_PER_WORD * INTVAL (operands[2]));
2439
  emit_move_insn (operands[0], operands[1]);
2440
  DONE;
2441
})
2442
 
2443
(define_insn "nop"
2444
  [(const_int 0)]
2445
  ""
2446
  "nop"
2447
  [(set_attr "type" "flow")])

powered by: WebSVN 2.1.0

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