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

Subversion Repositories openrisc

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

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

Line No. Rev Author Line
1 709 jeremybenn
;; FR30 machine description.
2
;; Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2007, 2010
3
;; Free Software Foundation, Inc.
4
;; Contributed by Cygnus Solutions.
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
;;{{{ Attributes
25
 
26
(define_attr "length" "" (const_int 2))
27
 
28
;; Used to distinguish between small memory model targets and big mode targets.
29
 
30
(define_attr "size" "small,big"
31
  (const (if_then_else (symbol_ref "TARGET_SMALL_MODEL")
32
                       (const_string "small")
33
                       (const_string "big"))))
34
 
35
 
36
;; Define an attribute to be used by the delay slot code.
37
;; An instruction by default is considered to be 'delayable'
38
;; that is, it can be placed into a delay slot, but it is not
39
;; itself a delayed branch type instruction.  An instruction
40
;; whose type is 'delayed' is one which has a delay slot, and
41
;; an instruction whose delay_type is 'other' is one which does
42
;; not have a delay slot, nor can it be placed into a delay slot.
43
 
44
(define_attr "delay_type" "delayable,delayed,other" (const_string "delayable"))
45
 
46
;;}}} 
47
;;{{{ Delay Slot Specifications
48
 
49
(define_delay (eq_attr "delay_type" "delayed")
50
  [(and (eq_attr "delay_type" "delayable")
51
        (eq_attr "length" "2"))
52
   (nil)
53
   (nil)]
54
)
55
 
56
(include "predicates.md")
57
(include "constraints.md")
58
 
59
;;}}}
60
;;{{{ Moves
61
 
62
;;{{{ Comment
63
 
64
;; Wrap moves in define_expand to prevent memory->memory moves from being
65
;; generated at the RTL level, which generates better code for most machines
66
;; which can't do mem->mem moves.
67
 
68
;; If operand 0 is a `subreg' with mode M of a register whose own mode is wider
69
;; than M, the effect of this instruction is to store the specified value in
70
;; the part of the register that corresponds to mode M.  The effect on the rest
71
;; of the register is undefined.
72
 
73
;; This class of patterns is special in several ways.  First of all, each of
74
;; these names *must* be defined, because there is no other way to copy a datum
75
;; from one place to another.
76
 
77
;; Second, these patterns are not used solely in the RTL generation pass.  Even
78
;; the reload pass can generate move insns to copy values from stack slots into
79
;; temporary registers.  When it does so, one of the operands is a hard
80
;; register and the other is an operand that can need to be reloaded into a
81
;; register.
82
 
83
;; Therefore, when given such a pair of operands, the pattern must
84
;; generate RTL which needs no reloading and needs no temporary
85
;; registers--no registers other than the operands.  For example, if
86
;; you support the pattern with a `define_expand', then in such a
87
;; case the `define_expand' mustn't call `force_reg' or any other such
88
;; function which might generate new pseudo registers.
89
 
90
;; This requirement exists even for subword modes on a RISC machine
91
;; where fetching those modes from memory normally requires several
92
;; insns and some temporary registers.  Look in `spur.md' to see how
93
;; the requirement can be satisfied.
94
 
95
;; During reload a memory reference with an invalid address may be passed as an
96
;; operand.  Such an address will be replaced with a valid address later in the
97
;; reload pass.  In this case, nothing may be done with the address except to
98
;; use it as it stands.  If it is copied, it will not be replaced with a valid
99
;; address.  No attempt should be made to make such an address into a valid
100
;; address and no routine (such as `change_address') that will do so may be
101
;; called.  Note that `general_operand' will fail when applied to such an
102
;; address.
103
;;
104
;; The global variable `reload_in_progress' (which must be explicitly declared
105
;; if required) can be used to determine whether such special handling is
106
;; required.
107
;;
108
;; The variety of operands that have reloads depends on the rest of
109
;; the machine description, but typically on a RISC machine these can
110
;; only be pseudo registers that did not get hard registers, while on
111
;; other machines explicit memory references will get optional
112
;; reloads.
113
;;
114
;; If a scratch register is required to move an object to or from memory, it
115
;; can be allocated using `gen_reg_rtx' prior to reload.  But this is
116
;; impossible during and after reload.  If there are cases needing scratch
117
;; registers after reload, you must define `SECONDARY_INPUT_RELOAD_CLASS' and
118
;; perhaps also `SECONDARY_OUTPUT_RELOAD_CLASS' to detect them, and provide
119
;; patterns `reload_inM' or `reload_outM' to handle them.
120
 
121
;; The constraints on a `moveM' must permit moving any hard register to any
122
;; other hard register provided that `HARD_REGNO_MODE_OK' permits mode M in
123
;; both registers and `REGISTER_MOVE_COST' applied to their classes returns a
124
;; value of 2.
125
 
126
;; It is obligatory to support floating point `moveM' instructions
127
;; into and out of any registers that can hold fixed point values,
128
;; because unions and structures (which have modes `SImode' or
129
;; `DImode') can be in those registers and they may have floating
130
;; point members.
131
 
132
;; There may also be a need to support fixed point `moveM' instructions in and
133
;; out of floating point registers.  Unfortunately, I have forgotten why this
134
;; was so, and I don't know whether it is still true.  If `HARD_REGNO_MODE_OK'
135
;; rejects fixed point values in floating point registers, then the constraints
136
;; of the fixed point `moveM' instructions must be designed to avoid ever
137
;; trying to reload into a floating point register.
138
 
139
;;}}}
140
;;{{{ Push and Pop
141
 
142
;; Push a register onto the stack
143
(define_insn "movsi_push"
144
  [(set (mem:SI (pre_dec:SI (reg:SI 15)))
145
        (match_operand:SI 0 "register_operand" "a"))]
146
  ""
147
  "st   %0, @-r15"
148
)
149
 
150
;; Pop a register off the stack
151
(define_insn "movsi_pop"
152
  [(set (match_operand:SI 0 "register_operand" "=a")
153
        (mem:SI (post_inc:SI (reg:SI 15))))]
154
  ""
155
  "ld   @r15+, %0"
156
)
157
 
158
;;}}}
159
;;{{{ 1 Byte Moves
160
 
161
(define_expand "movqi"
162
  [(set (match_operand:QI 0 "general_operand" "")
163
        (match_operand:QI 1 "general_operand" ""))]
164
  ""
165
  "
166
{
167
  if (!reload_in_progress
168
      && !reload_completed
169
      && GET_CODE (operands[0]) == MEM
170
      && (GET_CODE (operands[1]) == MEM
171
         || immediate_operand (operands[1], QImode)))
172
    operands[1] = copy_to_mode_reg (QImode, operands[1]);
173
}")
174
 
175
(define_insn "movqi_unsigned_register_load"
176
  [(set (match_operand:SI 0 "register_operand"              "=r")
177
        (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
178
  ""
179
  "ldub %1, %0"
180
)
181
 
182
(define_expand "movqi_signed_register_load"
183
  [(set (match_operand:SI 0 "register_operand"               "")
184
        (sign_extend:SI (match_operand:QI 1 "memory_operand" "")))]
185
  ""
186
  "
187
  emit_insn (gen_movqi_unsigned_register_load (operands[0], operands[1]));
188
  emit_insn (gen_extendqisi2 (operands[0], operands[0]));
189
  DONE;
190
  "
191
)
192
 
193
(define_insn "*movqi_internal"
194
  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,red,m,r")
195
        (match_operand:QI 1 "general_operand"       "i,red,r,rm"))]
196
  ""
197
  "@
198
   ldi:8\\t#%A1, %0
199
   mov  \\t%1, %0
200
   stb  \\t%1, %0
201
   ldub \\t%1, %0"
202
)
203
 
204
;;}}}
205
;;{{{ 2 Byte Moves
206
 
207
(define_expand "movhi"
208
  [(set (match_operand:HI 0 "general_operand" "")
209
        (match_operand:HI 1 "general_operand" ""))]
210
  ""
211
  "
212
{
213
  if (!reload_in_progress
214
      && !reload_completed
215
      && GET_CODE (operands[0]) == MEM
216
      && (GET_CODE (operands[1]) == MEM
217
         || immediate_operand (operands[1], HImode)))
218
    operands[1] = copy_to_mode_reg (HImode, operands[1]);
219
}")
220
 
221
(define_insn "movhi_unsigned_register_load"
222
  [(set (match_operand:SI 0 "register_operand" "=r")
223
        (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
224
  ""
225
  "lduh %1, %0"
226
)
227
 
228
(define_expand "movhi_signed_register_load"
229
  [(set (match_operand:SI 0 "register_operand" "")
230
        (sign_extend:SI (match_operand:HI 1 "memory_operand" "")))]
231
  ""
232
  "
233
  emit_insn (gen_movhi_unsigned_register_load (operands[0], operands[1]));
234
  emit_insn (gen_extendhisi2 (operands[0], operands[0]));
235
  DONE;
236
  "
237
)
238
 
239
(define_insn "*movhi_internal"
240
  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,red,m,r")
241
        (match_operand:HI 1 "general_operand"       "L,M,n,red,r,rm"))]
242
  ""
243
  "@
244
   ldi:8 \\t#%1, %0
245
   ldi:20\\t#%1, %0
246
   ldi:32\\t#%1, %0
247
   mov   \\t%1, %0
248
   sth   \\t%1, %0
249
   lduh  \\t%1, %0"
250
  [(set_attr "length" "*,4,6,*,*,*")]
251
)
252
 
253
;;}}}
254
;;{{{ 4 Byte Moves
255
 
256
;; If the destination is a MEM and the source is a
257
;; MEM or an CONST_INT move the source into a register.
258
(define_expand "movsi"
259
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
260
        (match_operand:SI 1 "general_operand" ""))]
261
  ""
262
  "{
263
  if (!reload_in_progress
264
      && !reload_completed
265
      && GET_CODE(operands[0]) == MEM
266
      && (GET_CODE (operands[1]) == MEM
267
          || immediate_operand (operands[1], SImode)))
268
     operands[1] = copy_to_mode_reg (SImode, operands[1]);
269
  }"
270
)
271
 
272
;; We can do some clever tricks when loading certain immediate
273
;; values.  We implement these tricks as define_splits, rather
274
;; than putting the code into the define_expand "movsi" above,
275
;; because if we put them there, they will be evaluated at RTL
276
;; generation time and then the combiner pass will come along
277
;; and replace the multiple insns that have been generated with
278
;; the original, slower, load insns.  (The combiner pass only
279
;; cares about reducing the number of instructions, it does not
280
;; care about instruction lengths or speeds).  Splits are
281
;; evaluated after the combine pass and before the scheduling
282
;; passes, so that they are the perfect place to put this
283
;; intelligence.
284
;;
285
;; XXX we probably ought to implement these for QI and HI mode
286
;; loads as well.
287
 
288
;; If we are loading a small negative constant we can save space
289
;; and time by loading the positive value and then sign extending it.
290
(define_split
291
  [(set (match_operand:SI 0 "register_operand"  "")
292
        (match_operand:SI 1 "const_int_operand" ""))]
293
   "INTVAL (operands[1]) <= -1 && INTVAL (operands[1]) >= -128
294
    && (GET_CODE (operands[0]) != SUBREG
295
        || SCALAR_INT_MODE_P (GET_MODE (XEXP (operands[0], 0))))"
296
   [(set (match_dup 0) (match_dup 1))
297
    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
298
   "{
299
   operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
300
   operands[2] = gen_lowpart (QImode, operands[0]);
301
   }"
302
)
303
 
304
;; If we are loading a large negative constant, one which does
305
;; not have any of its bottom 24 bit set, then we can save time
306
;; and space by loading the byte value and shifting it into place.
307
(define_split
308
  [(set (match_operand:SI 0 "register_operand"  "")
309
        (match_operand:SI 1 "const_int_operand" ""))]
310
   "(INTVAL (operands[1]) < 0) && ((INTVAL (operands[1]) & 0x00ffffff) == 0)"
311
   [(set (match_dup 0) (match_dup 2))
312
    (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 24)))
313
               (clobber (reg:CC 16))])]
314
   "{
315
   HOST_WIDE_INT val = INTVAL (operands[1]);
316
   operands[2] = GEN_INT (val >> 24);
317
   }"
318
)
319
 
320
;; If we are loading a large positive constant, one which has bits
321
;; in the top byte set, but whose set bits all lie within an 8 bit
322
;; range, then we can save time and space by loading the byte value
323
;; and shifting it into place.
324
(define_split
325
  [(set (match_operand:SI 0 "register_operand"  "")
326
        (match_operand:SI 1 "const_int_operand" ""))]
327
   "(INTVAL (operands[1]) > 0x00ffffff)
328
   && ((INTVAL (operands[1]) >> exact_log2 (INTVAL (operands[1]) & (- INTVAL (operands[1])))) < 0x100)"
329
   [(set (match_dup 0) (match_dup 2))
330
    (parallel [(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 3)))
331
               (clobber (reg:CC 16))])]
332
   "{
333
   HOST_WIDE_INT val = INTVAL (operands[1]);
334
   int shift = exact_log2 (val & ( - val));
335
   operands[2] = GEN_INT (val >> shift);
336
   operands[3] = GEN_INT (shift);
337
   }"
338
)
339
 
340
;; When TARGET_SMALL_MODEL is defined we assume that all symbolic
341
;; values are addresses which will fit in 20 bits.
342
 
343
(define_insn "movsi_internal"
344
  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,red,V,r,m")
345
        (match_operand:SI 1 "general_operand"       "L,M,n,i,rde,r,rm,r"))]
346
  ""
347
  "*
348
  {
349
    switch (which_alternative)
350
    {
351
    case 0: return   \"ldi:8 \\t#%1, %0\";
352
    case 1: return   \"ldi:20\\t#%1, %0\";
353
    case 2: return   \"ldi:32\\t#%1, %0\";
354
    case 3: if (TARGET_SMALL_MODEL)
355
              return \"ldi:20\\t%1, %0\";
356
            else
357
              return \"ldi:32\\t%1, %0\";
358
    case 4: return   \"mov   \\t%1, %0\";
359
    case 5: return   \"st    \\t%1, %0\";
360
    case 6: return   \"ld    \\t%1, %0\";
361
    case 7: return   \"st    \\t%1, %0\";
362
    default: gcc_unreachable ();
363
   }
364
  }"
365
  [(set (attr "length") (cond [(eq_attr "alternative" "1") (const_int 4)
366
                               (eq_attr "alternative" "2") (const_int 6)
367
                               (eq_attr "alternative" "3")
368
                                        (if_then_else (eq_attr "size" "small")
369
                                                      (const_int 4)
370
                                                      (const_int 6))]
371
                              (const_int 2)))]
372
)
373
 
374
;;}}}
375
;;{{{ 8 Byte Moves
376
 
377
;; Note - the FR30 does not have an 8 byte load/store instruction
378
;; but we have to support this pattern because some other patterns
379
;; (e.g. muldisi2) can produce a DImode result.
380
;; (This code is stolen from the M32R port.)
381
 
382
(define_expand "movdi"
383
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
384
        (match_operand:DI 1 "general_operand" ""))]
385
  ""
386
  "
387
  /* Everything except mem = const or mem = mem can be done easily.  */
388
 
389
  if (GET_CODE (operands[0]) == MEM)
390
    operands[1] = force_reg (DImode, operands[1]);
391
  "
392
)
393
 
394
;; We use an insn and a split so that we can generate
395
;; RTL rather than text from fr30_move_double().
396
 
397
(define_insn "*movdi_insn"
398
  [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,m,r")
399
        (match_operand:DI 1 "di_operand"               "r,m,r,nF"))]
400
  "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)"
401
  "#"
402
  [(set_attr "length" "4,8,12,12")]
403
)
404
 
405
(define_split
406
  [(set (match_operand:DI 0 "nonimmediate_di_operand" "")
407
        (match_operand:DI 1 "di_operand" ""))]
408
  "reload_completed"
409
  [(match_dup 2)]
410
  "operands[2] = fr30_move_double (operands);"
411
)
412
 
413
;;}}}
414
;;{{{ Load & Store Multiple Registers
415
 
416
;; The load multiple and store multiple patterns are implemented
417
;; as peepholes because the only time they are expected to occur
418
;; is during function prologues and epilogues.
419
 
420
(define_peephole
421
  [(set (mem:SI (pre_dec:SI (reg:SI 15)))
422
        (match_operand:SI 0 "high_register_operand" "h"))
423
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
424
        (match_operand:SI 1 "high_register_operand" "h"))
425
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
426
        (match_operand:SI 2 "high_register_operand" "h"))
427
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
428
        (match_operand:SI 3 "high_register_operand" "h"))]
429
  "fr30_check_multiple_regs (operands, 4, 1)"
430
  "stm1 (%0, %1, %2, %3)"
431
  [(set_attr "delay_type" "other")]
432
)
433
 
434
(define_peephole
435
  [(set (mem:SI (pre_dec:SI (reg:SI 15)))
436
        (match_operand:SI 0 "high_register_operand" "h"))
437
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
438
        (match_operand:SI 1 "high_register_operand" "h"))
439
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
440
        (match_operand:SI 2 "high_register_operand" "h"))]
441
  "fr30_check_multiple_regs (operands, 3, 1)"
442
  "stm1 (%0, %1, %2)"
443
  [(set_attr "delay_type" "other")]
444
)
445
 
446
(define_peephole
447
  [(set (mem:SI (pre_dec:SI (reg:SI 15)))
448
        (match_operand:SI 0 "high_register_operand" "h"))
449
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
450
        (match_operand:SI 1 "high_register_operand" "h"))]
451
  "fr30_check_multiple_regs (operands, 2, 1)"
452
  "stm1 (%0, %1)"
453
  [(set_attr "delay_type" "other")]
454
)
455
 
456
(define_peephole
457
  [(set (match_operand:SI 0 "high_register_operand" "h")
458
        (mem:SI (post_inc:SI (reg:SI 15))))
459
   (set (match_operand:SI 1 "high_register_operand" "h")
460
        (mem:SI (post_inc:SI (reg:SI 15))))
461
   (set (match_operand:SI 2 "high_register_operand" "h")
462
        (mem:SI (post_inc:SI (reg:SI 15))))
463
   (set (match_operand:SI 3 "high_register_operand" "h")
464
        (mem:SI (post_inc:SI (reg:SI 15))))]
465
  "fr30_check_multiple_regs (operands, 4, 0)"
466
  "ldm1 (%0, %1, %2, %3)"
467
  [(set_attr "delay_type" "other")]
468
)
469
 
470
(define_peephole
471
  [(set (match_operand:SI 0 "high_register_operand" "h")
472
        (mem:SI (post_inc:SI (reg:SI 15))))
473
   (set (match_operand:SI 1 "high_register_operand" "h")
474
        (mem:SI (post_inc:SI (reg:SI 15))))
475
   (set (match_operand:SI 2 "high_register_operand" "h")
476
        (mem:SI (post_inc:SI (reg:SI 15))))]
477
  "fr30_check_multiple_regs (operands, 3, 0)"
478
  "ldm1 (%0, %1, %2)"
479
  [(set_attr "delay_type" "other")]
480
)
481
 
482
(define_peephole
483
  [(set (match_operand:SI 0 "high_register_operand" "h")
484
        (mem:SI (post_inc:SI (reg:SI 15))))
485
   (set (match_operand:SI 1 "high_register_operand" "h")
486
        (mem:SI (post_inc:SI (reg:SI 15))))]
487
  "fr30_check_multiple_regs (operands, 2, 0)"
488
  "ldm1 (%0, %1)"
489
  [(set_attr "delay_type" "other")]
490
)
491
 
492
(define_peephole
493
  [(set (mem:SI (pre_dec:SI (reg:SI 15)))
494
        (match_operand:SI 0 "low_register_operand" "l"))
495
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
496
        (match_operand:SI 1 "low_register_operand" "l"))
497
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
498
        (match_operand:SI 2 "low_register_operand" "l"))
499
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
500
        (match_operand:SI 3 "low_register_operand" "l"))]
501
  "fr30_check_multiple_regs (operands, 4, 1)"
502
  "stm0 (%0, %1, %2, %3)"
503
  [(set_attr "delay_type" "other")]
504
)
505
 
506
(define_peephole
507
  [(set (mem:SI (pre_dec:SI (reg:SI 15)))
508
        (match_operand:SI 0 "low_register_operand" "l"))
509
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
510
        (match_operand:SI 1 "low_register_operand" "l"))
511
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
512
        (match_operand:SI 2 "low_register_operand" "l"))]
513
  "fr30_check_multiple_regs (operands, 3, 1)"
514
  "stm0 (%0, %1, %2)"
515
  [(set_attr "delay_type" "other")]
516
)
517
 
518
(define_peephole
519
  [(set (mem:SI (pre_dec:SI (reg:SI 15)))
520
        (match_operand:SI 0 "low_register_operand" "l"))
521
   (set (mem:SI (pre_dec:SI (reg:SI 15)))
522
        (match_operand:SI 1 "low_register_operand" "l"))]
523
  "fr30_check_multiple_regs (operands, 2, 1)"
524
  "stm0 (%0, %1)"
525
  [(set_attr "delay_type" "other")]
526
)
527
 
528
;;}}}
529
;;{{{ Floating Point Moves
530
 
531
;; Note - Patterns for SF mode moves are compulsory, but
532
;; patterns for DF are optional, as GCC can synthesize them.
533
 
534
(define_expand "movsf"
535
  [(set (match_operand:SF 0 "general_operand" "")
536
        (match_operand:SF 1 "general_operand" ""))]
537
  ""
538
  "{
539
  if (!reload_in_progress && !reload_completed
540
      && memory_operand (operands[0], SFmode)
541
      && memory_operand (operands[1], SFmode))
542
    operands[1] = copy_to_mode_reg (SFmode, operands[1]);
543
  }"
544
)
545
 
546
(define_insn "*movsf_internal"
547
  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,red,m,r")
548
        (match_operand:SF 1 "general_operand"      "Fn,i,rde,r,rm"))]
549
  ""
550
  "*
551
  {
552
    switch (which_alternative)
553
    {
554
    case 0: return   \"ldi:32\\t%1, %0\";
555
    case 1: if (TARGET_SMALL_MODEL)
556
              return \"ldi:20\\t%1, %0\";
557
            else
558
              return \"ldi:32\\t%1, %0\";
559
    case 2: return   \"mov   \\t%1, %0\";
560
    case 3: return   \"st    \\t%1, %0\";
561
    case 4: return   \"ld    \\t%1, %0\";
562
    default: gcc_unreachable ();
563
    }
564
  }"
565
  [(set (attr "length") (cond [(eq_attr "alternative" "0") (const_int 6)
566
                               (eq_attr "alternative" "1")
567
                                        (if_then_else (eq_attr "size" "small")
568
                                                      (const_int 4)
569
                                                      (const_int 6))]
570
                              (const_int 2)))]
571
)
572
 
573
(define_insn "*movsf_constant_store"
574
  [(set (match_operand:SF 0 "memory_operand"    "=m")
575
        (match_operand:SF 1 "immediate_operand" "F"))]
576
  ""
577
  "*
578
  {
579
  const char *    ldi_instr;
580
  const char *    tmp_reg;
581
  static char     buffer[100];
582
 
583
  ldi_instr = fr30_const_double_is_zero (operands[1]) ? \"ldi:8\" : \"ldi:32\";
584
 
585
  tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER];
586
 
587
  sprintf (buffer, \"%s\\t#%%1, %s\\t;\\n\\tst\\t%s, %%0\\t; Created by movsf_constant_store\",
588
    ldi_instr, tmp_reg, tmp_reg);
589
 
590
  return buffer;
591
  }"
592
  [(set_attr "length" "8")]
593
)
594
 
595
;;}}}
596
 
597
;;}}} 
598
;;{{{ Conversions
599
 
600
;; Signed conversions from a smaller integer to a larger integer
601
 
602
(define_insn "extendqisi2"
603
  [(set (match_operand:SI 0 "register_operand"                "=r")
604
        (sign_extend:SI (match_operand:QI 1 "register_operand" "0")))]
605
  ""
606
  "extsb        %0"
607
)
608
 
609
(define_insn "extendhisi2"
610
  [(set (match_operand:SI 0 "register_operand"                "=r")
611
        (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))]
612
  ""
613
  "extsh        %0"
614
)
615
 
616
;; Unsigned conversions from a smaller integer to a larger integer
617
 
618
(define_insn "zero_extendqisi2"
619
  [(set (match_operand:SI 0 "register_operand"                "=r")
620
        (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))]
621
  ""
622
  "extub        %0"
623
)
624
 
625
(define_insn "zero_extendhisi2"
626
  [(set (match_operand:SI 0 "register_operand"                "=r")
627
        (zero_extend:SI (match_operand:HI 1 "register_operand" "0")))]
628
  ""
629
  "extuh        %0"
630
)
631
 
632
;;}}} 
633
;;{{{ Arithmetic
634
 
635
;;{{{ Addition
636
 
637
;; This is a special pattern just for adjusting the stack size.
638
(define_insn "add_to_stack"
639
  [(set (reg:SI 15)
640
        (plus:SI (reg:SI 15)
641
                 (match_operand:SI 0 "stack_add_operand" "i")))]
642
  ""
643
  "addsp        %0"
644
)
645
 
646
;; We need some trickery to be able to handle the addition of
647
;; large (i.e. outside +/- 16) constants.  We need to be able to
648
;; handle this because reload assumes that it can generate add
649
;; instructions with arbitrary sized constants.
650
(define_expand "addsi3"
651
  [(set (match_operand:SI 0 "register_operand"           "")
652
        (plus:SI (match_operand:SI 1 "register_operand"  "")
653
                 (match_operand:SI 2 "nonmemory_operand" "")))]
654
  ""
655
  "{
656
  if (   GET_CODE (operands[2]) == REG
657
      || GET_CODE (operands[2]) == SUBREG)
658
    emit_insn (gen_addsi_regs (operands[0], operands[1], operands[2]));
659
  else if (GET_CODE (operands[2]) != CONST_INT)
660
    emit_insn (gen_addsi_big_int (operands[0], operands[1], operands[2]));
661
  else if (INTVAL (operands[2]) >= -16
662
           && INTVAL (operands[2]) <= 15
663
           && (!REG_P (operands[1])
664
               || !REGNO_PTR_FRAME_P (REGNO (operands[1]))
665
               || REGNO (operands[1]) == STACK_POINTER_REGNUM))
666
    emit_insn (gen_addsi_small_int (operands[0], operands[1], operands[2]));
667
  else
668
    emit_insn (gen_addsi_big_int (operands[0], operands[1], operands[2]));
669
  DONE;
670
  }"
671
)
672
 
673
(define_insn "addsi_regs"
674
  [(set (match_operand:SI 0 "register_operand"          "=r")
675
        (plus:SI (match_operand:SI 1 "register_operand" "%0")
676
                 (match_operand:SI 2 "register_operand"  "r")))]
677
  ""
678
  "addn %2, %0"
679
)
680
 
681
;; Do not allow an eliminable register in the source register.  It
682
;; might be eliminated in favor of the stack pointer, probably
683
;; increasing the offset, and so rendering the instruction illegal.
684
(define_insn "addsi_small_int"
685
  [(set (match_operand:SI 0 "register_operand"              "=r,r")
686
        (plus:SI (match_operand:SI 1 "register_operand"      "0,0")
687
                 (match_operand:SI 2 "add_immediate_operand" "I,J")))]
688
  "!REG_P (operands[1])
689
   || !REGNO_PTR_FRAME_P (REGNO (operands[1]))
690
   || REGNO (operands[1]) == STACK_POINTER_REGNUM"
691
  "@
692
   addn %2, %0
693
   addn2        %2, %0"
694
)
695
 
696
(define_expand "addsi_big_int"
697
  [(set (match_operand:SI 0 "register_operand"           "")
698
        (plus:SI (match_operand:SI 1 "register_operand"  "")
699
                 (match_operand:SI 2 "immediate_operand" "")))]
700
  ""
701
  "{
702
  /* Cope with the possibility that ops 0 and 1 are the same register.  */
703
  if (rtx_equal_p (operands[0], operands[1]))
704
    {
705
      if (reload_in_progress || reload_completed)
706
        {
707
          rtx reg = gen_rtx_REG (SImode, 0/*COMPILER_SCRATCH_REGISTER*/);
708
 
709
          emit_insn (gen_movsi (reg, operands[2]));
710
          emit_insn (gen_addsi_regs (operands[0], operands[0], reg));
711
        }
712
      else
713
        {
714
          operands[2] = force_reg (SImode, operands[2]);
715
          emit_insn (gen_addsi_regs (operands[0], operands[0], operands[2]));
716
        }
717
    }
718
  else
719
    {
720
      emit_insn (gen_movsi (operands[0], operands[2]));
721
      emit_insn (gen_addsi_regs (operands[0], operands[0], operands[1]));
722
    }
723
  DONE;
724
  }"
725
)
726
 
727
(define_insn "*addsi_for_reload"
728
  [(set (match_operand:SI 0 "register_operand"         "=&r,r,r")
729
        (plus:SI (match_operand:SI 1 "register_operand"  "r,r,r")
730
                 (match_operand:SI 2 "immediate_operand" "L,M,n")))]
731
  "reload_in_progress || reload_completed"
732
  "@
733
  ldi:8\\t#%2, %0  \\n\\taddn\\t%1, %0
734
  ldi:20\\t#%2, %0 \\n\\taddn\\t%1, %0
735
  ldi:32\\t#%2, %0 \\n\\taddn\\t%1, %0"
736
  [(set_attr "length" "4,6,8")]
737
)
738
 
739
;;}}}
740
;;{{{ Subtraction
741
 
742
(define_insn "subsi3"
743
  [(set (match_operand:SI 0 "register_operand"       "=r")
744
        (minus:SI (match_operand:SI 1 "register_operand" "0")
745
                  (match_operand:SI 2 "register_operand" "r")))]
746
  ""
747
  "subn %2, %0"
748
)
749
 
750
;;}}}
751
;;{{{ Multiplication
752
 
753
;; Signed multiplication producing 64-bit results from 32-bit inputs
754
(define_insn "mulsidi3"
755
  [(set (match_operand:DI 0 "register_operand"                             "=r")
756
           (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
757
                    (sign_extend:DI (match_operand:SI 2 "register_operand"  "r"))))
758
   (clobber (reg:CC 16))]
759
  ""
760
  "mul  %2, %1\\n\\tmov\\tmdh, %0\\n\\tmov\\tmdl, %p0"
761
  [(set_attr "length" "6")]
762
)
763
 
764
;; Unsigned multiplication producing 64-bit results from 32-bit inputs
765
(define_insn "umulsidi3"
766
  [(set (match_operand:DI 0 "register_operand"                             "=r")
767
           (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
768
                    (zero_extend:DI (match_operand:SI 2 "register_operand"  "r"))))
769
   (clobber (reg:CC 16))]
770
  ""
771
  "mulu %2, %1\\n\\tmov\\tmdh, %0\\n\\tmov\\tmdl, %p0"
772
  [(set_attr "length" "6")]
773
)
774
 
775
;; Signed multiplication producing 32-bit result from 16-bit inputs
776
(define_insn "mulhisi3"
777
  [(set (match_operand:SI 0 "register_operand"                             "=r")
778
           (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
779
                    (sign_extend:SI (match_operand:HI 2 "register_operand"  "r"))))
780
   (clobber (reg:CC 16))]
781
  ""
782
  "mulh %2, %1\\n\\tmov\\tmdl, %0"
783
  [(set_attr "length" "4")]
784
)
785
 
786
;; Unsigned multiplication producing 32-bit result from 16-bit inputs
787
(define_insn "umulhisi3"
788
  [(set (match_operand:SI 0 "register_operand"                             "=r")
789
           (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%r"))
790
                    (zero_extend:SI (match_operand:HI 2 "register_operand"  "r"))))
791
   (clobber (reg:CC 16))]
792
  ""
793
  "muluh        %2, %1\\n\\tmov\\tmdl, %0"
794
  [(set_attr "length" "4")]
795
)
796
 
797
;; Signed multiplication producing 32-bit result from 32-bit inputs
798
(define_insn "mulsi3"
799
  [(set (match_operand:SI 0 "register_operand"             "=r")
800
           (mult:SI (match_operand:SI 1 "register_operand" "%r")
801
                    (match_operand:SI 2 "register_operand"  "r")))
802
   (clobber (reg:CC 16))]
803
  ""
804
  "mul  %2, %1\\n\\tmov\\tmdl, %0"
805
  [(set_attr "length" "4")]
806
)
807
 
808
;;}}}
809
;;}}} 
810
;;{{{ Shifts
811
 
812
;; Arithmetic Shift Left
813
(define_insn "ashlsi3"
814
  [(set (match_operand:SI 0 "register_operand"            "=r,r,r")
815
        (ashift:SI (match_operand:SI 1 "register_operand"  "0,0,0")
816
                   (match_operand:SI 2 "nonmemory_operand" "r,I,K")))
817
   (clobber (reg:CC 16))]
818
  ""
819
  "@
820
  lsl   %2, %0
821
  lsl   %2, %0
822
  lsl2  %x2, %0"
823
)
824
 
825
;; Arithmetic Shift Right
826
(define_insn "ashrsi3"
827
  [(set (match_operand:SI 0 "register_operand"              "=r,r,r")
828
        (ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,0")
829
                     (match_operand:SI 2 "nonmemory_operand" "r,I,K")))
830
   (clobber (reg:CC 16))]
831
  ""
832
  "@
833
  asr   %2, %0
834
  asr   %2, %0
835
  asr2  %x2, %0"
836
)
837
 
838
;; Logical Shift Right
839
(define_insn "lshrsi3"
840
  [(set (match_operand:SI 0 "register_operand"              "=r,r,r")
841
        (lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,0")
842
                     (match_operand:SI 2 "nonmemory_operand" "r,I,K")))
843
   (clobber (reg:CC 16))]
844
  ""
845
  "@
846
  lsr   %2, %0
847
  lsr   %2, %0
848
  lsr2  %x2, %0"
849
)
850
 
851
;;}}} 
852
;;{{{ Logical Operations
853
 
854
;; Logical AND, 32-bit integers
855
(define_insn "andsi3"
856
  [(set (match_operand:SI 0 "register_operand"         "=r")
857
        (and:SI (match_operand:SI 1 "register_operand" "%r")
858
                (match_operand:SI 2 "register_operand"  "0")))
859
   (clobber (reg:CC 16))]
860
  ""
861
  "and  %1, %0"
862
)
863
 
864
;; Inclusive OR, 32-bit integers
865
(define_insn "iorsi3"
866
  [(set (match_operand:SI 0 "register_operand"         "=r")
867
        (ior:SI (match_operand:SI 1 "register_operand" "%r")
868
                (match_operand:SI 2 "register_operand"  "0")))
869
   (clobber (reg:CC 16))]
870
  ""
871
  "or   %1, %0"
872
)
873
 
874
;; Exclusive OR, 32-bit integers
875
(define_insn "xorsi3"
876
  [(set (match_operand:SI 0 "register_operand"         "=r")
877
        (xor:SI (match_operand:SI 1 "register_operand" "%r")
878
                (match_operand:SI 2 "register_operand"  "0")))
879
   (clobber (reg:CC 16))]
880
  ""
881
  "eor  %1, %0"
882
)
883
 
884
;; One's complement, 32-bit integers
885
(define_expand "one_cmplsi2"
886
  [(set (match_operand:SI 0 "register_operand"         "")
887
        (not:SI (match_operand:SI 1 "register_operand" "")))]
888
  ""
889
  "{
890
  if (rtx_equal_p (operands[0], operands[1]))
891
    {
892
      if (reload_in_progress || reload_completed)
893
        {
894
          rtx reg = gen_rtx_REG (SImode, 0/*COMPILER_SCRATCH_REGISTER*/);
895
 
896
          emit_insn (gen_movsi (reg, constm1_rtx));
897
          emit_insn (gen_xorsi3 (operands[0], operands[0], reg));
898
        }
899
      else
900
        {
901
          rtx reg = gen_reg_rtx (SImode);
902
 
903
          emit_insn (gen_movsi (reg, constm1_rtx));
904
          emit_insn (gen_xorsi3 (operands[0], operands[0], reg));
905
        }
906
    }
907
  else
908
    {
909
      emit_insn (gen_movsi_internal (operands[0], constm1_rtx));
910
      emit_insn (gen_xorsi3 (operands[0], operands[1], operands[0]));
911
    }
912
  DONE;
913
  }"
914
)
915
 
916
;;}}} 
917
;;{{{ Comparisons
918
 
919
;; The actual comparisons, generated by the cbranch and/or cstore expanders
920
 
921
(define_insn "*cmpsi_internal"
922
  [(set (reg:CC 16)
923
        (compare:CC (match_operand:SI 0 "register_operand"  "r,r,r")
924
                    (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
925
  ""
926
  "@
927
  cmp   %1, %0
928
  cmp   %1, %0
929
  cmp2  %1, %0"
930
)
931
 
932
;;}}} 
933
;;{{{ Branches
934
 
935
;; Define_expands called by the machine independent part of the compiler
936
;; to allocate a new comparison register
937
 
938
(define_expand "cbranchsi4"
939
  [(set (reg:CC 16)
940
        (compare:CC (match_operand:SI 1 "register_operand"  "")
941
                    (match_operand:SI 2 "nonmemory_operand" "")))
942
   (set (pc)
943
        (if_then_else (match_operator:CC 0 "ordered_comparison_operator"
944
                       [(reg:CC 16) (const_int 0)])
945
                      (label_ref (match_operand 3 "" ""))
946
                      (pc)))]
947
  ""
948
  ""
949
)
950
 
951
 
952
;; Actual branches.  We must allow for the (label_ref) and the (pc) to be
953
;; swapped.  If they are swapped, it reverses the sense of the branch.
954
 
955
;; This pattern matches the (branch-if-true) branches generated above.
956
;; It generates two different instruction sequences depending upon how
957
;; far away the destination is.
958
 
959
;; The calculation for the instruction length is derived as follows:
960
;; The branch instruction has a 9-bit signed displacement so we have
961
;; this inequality for the displacement:
962
;;
963
;;               -256 <= pc < 256
964
;; or
965
;;         -256 + 256 <= pc + 256 < 256 + 256
966
;; i.e.
967
;;                  0 <= pc + 256 < 512
968
;;
969
;; if we consider the displacement as an unsigned value, then negative
970
;; displacements become very large positive displacements, and the
971
;; inequality becomes:
972
;;
973
;;              pc + 256 < 512
974
;;
975
;; In order to allow for the fact that the real branch instruction works
976
;; from pc + 2, we increase the offset to 258.
977
;;
978
;; Note - we do not have to worry about whether the branch is delayed or
979
;; not, as branch shortening happens after delay slot reorganization.
980
 
981
(define_insn "*branch_true"
982
  [(set (pc)
983
        (if_then_else (match_operator:CC 0 "comparison_operator"
984
                                         [(reg:CC 16)
985
                                          (const_int 0)])
986
                      (label_ref (match_operand 1 "" ""))
987
                      (pc)))]
988
  ""
989
  "*
990
  {
991
    if (get_attr_length (insn) == 2)
992
      return \"b%b0%#\\t%l1\";
993
    else
994
      {
995
        static char   buffer [100];
996
        const char *  tmp_reg;
997
        const char *  ldi_insn;
998
 
999
        tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER];
1000
 
1001
        ldi_insn = TARGET_SMALL_MODEL ? \"ldi:20\" : \"ldi:32\";
1002
 
1003
        /* The code produced here is, for say the EQ case:
1004
 
1005
               Bne  1f
1006
               LDI  
1007
               JMP  r0
1008
             1:                                         */
1009
 
1010
        sprintf (buffer,
1011
          \"b%%B0\\t1f\\t;\\n\\t%s\\t%%l1, %s\\t;\\n\\tjmp%%#\\t@%s\\t;\\n1:\",
1012
          ldi_insn, tmp_reg, tmp_reg);
1013
 
1014
        return buffer;
1015
    }
1016
  }"
1017
  [(set (attr "length") (if_then_else
1018
                          (ltu
1019
                            (plus
1020
                              (minus
1021
                                (match_dup 1)
1022
                                (pc))
1023
                              (const_int 254))
1024
                            (const_int 506))
1025
                          (const_int 2)
1026
                          (if_then_else (eq_attr "size" "small")
1027
                                        (const_int 8)
1028
                                        (const_int 10))))
1029
   (set_attr "delay_type" "delayed")]
1030
)
1031
 
1032
 
1033
;; This pattern is a duplicate of the previous one, except that the
1034
;; branch occurs if the test is false, so the %B operator is used.
1035
(define_insn "*branch_false"
1036
  [(set (pc)
1037
        (if_then_else (match_operator:CC 0 "comparison_operator"
1038
                                         [(reg:CC 16)
1039
                                          (const_int 0)])
1040
                      (pc)
1041
                      (label_ref (match_operand 1 "" ""))))]
1042
  ""
1043
  "*
1044
  {
1045
    if (get_attr_length (insn) == 2)
1046
      return \"b%B0%#\\t%l1 \";
1047
    else
1048
      {
1049
        static char   buffer [100];
1050
        const char *  tmp_reg;
1051
        const char *  ldi_insn;
1052
 
1053
        tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER];
1054
 
1055
        ldi_insn = TARGET_SMALL_MODEL ? \"ldi:20\" : \"ldi:32\";
1056
 
1057
        sprintf (buffer,
1058
          \"b%%b0\\t1f\\t;\\n\\t%s\\t%%l1, %s\\t;\\n\\tjmp%%#\\t@%s\\t;\\n1:\",
1059
          ldi_insn, tmp_reg, tmp_reg);
1060
 
1061
        return buffer;
1062
      }
1063
  }"
1064
  [(set (attr "length") (if_then_else (ltu (plus (minus (match_dup 1) (pc))
1065
                                                 (const_int 254))
1066
                                           (const_int 506))
1067
                                      (const_int 2)
1068
                                      (if_then_else (eq_attr "size" "small")
1069
                                                    (const_int 8)
1070
                                                    (const_int 10))))
1071
   (set_attr "delay_type" "delayed")]
1072
)
1073
 
1074
;;}}} 
1075
;;{{{ Calls & Jumps
1076
 
1077
;; Subroutine call instruction returning no value.  Operand 0 is the function
1078
;; to call; operand 1 is the number of bytes of arguments pushed (in mode
1079
;; `SImode', except it is normally a `const_int'); operand 2 is the number of
1080
;; registers used as operands.
1081
 
1082
(define_insn "call"
1083
  [(call (match_operand 0 "call_operand" "Qm")
1084
         (match_operand 1 ""             "g"))
1085
   (clobber (reg:SI 17))]
1086
  ""
1087
  "call%#\\t%0"
1088
  [(set_attr "delay_type" "delayed")]
1089
)
1090
 
1091
;; Subroutine call instruction returning a value.  Operand 0 is the hard
1092
;; register in which the value is returned.  There are three more operands, the
1093
;; same as the three operands of the `call' instruction (but with numbers
1094
;; increased by one).
1095
 
1096
;; Subroutines that return `BLKmode' objects use the `call' insn.
1097
 
1098
(define_insn "call_value"
1099
  [(set (match_operand 0 "register_operand"  "=r")
1100
        (call (match_operand 1 "call_operand" "Qm")
1101
              (match_operand 2 ""             "g")))
1102
   (clobber (reg:SI 17))]
1103
  ""
1104
  "call%#\\t%1"
1105
  [(set_attr "delay_type" "delayed")]
1106
)
1107
 
1108
;; Normal unconditional jump.
1109
;; For a description of the computation of the length
1110
;; attribute see the branch patterns above.
1111
;;
1112
;; Although this instruction really clobbers r0, flow
1113
;; relies on jump being simplejump_p in several places
1114
;; and as r0 is fixed, this doesn't change anything
1115
(define_insn "jump"
1116
  [(set (pc) (label_ref (match_operand 0 "" "")))]
1117
  ""
1118
  "*
1119
  {
1120
    if (get_attr_length (insn) == 2)
1121
       return \"bra%#\\t%0\";
1122
    else
1123
      {
1124
        static char   buffer [100];
1125
        const char *  tmp_reg;
1126
        const char *  ldi_insn;
1127
 
1128
        tmp_reg = reg_names [COMPILER_SCRATCH_REGISTER];
1129
 
1130
        ldi_insn = TARGET_SMALL_MODEL ? \"ldi:20\" : \"ldi:32\";
1131
 
1132
        sprintf (buffer, \"%s\\t%%0, %s\\t;\\n\\tjmp%%#\\t@%s\\t;\",
1133
          ldi_insn, tmp_reg, tmp_reg);
1134
 
1135
        return buffer;
1136
      }
1137
  }"
1138
  [(set (attr "length") (if_then_else (ltu (plus (minus (match_dup 0) (pc))
1139
                                                (const_int 254))
1140
                                          (const_int 506))
1141
                                     (const_int 2)
1142
                                     (if_then_else (eq_attr "size" "small")
1143
                                                   (const_int 6)
1144
                                                   (const_int 8))))
1145
   (set_attr "delay_type" "delayed")]
1146
)
1147
 
1148
;; Indirect jump through a register
1149
(define_insn "indirect_jump"
1150
  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "r"))]
1151
  "GET_CODE (operands[0]) != MEM || GET_CODE (XEXP (operands[0], 0)) != PLUS"
1152
  "jmp%#\\t@%0"
1153
  [(set_attr "delay_type" "delayed")]
1154
)
1155
 
1156
(define_insn "tablejump"
1157
  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
1158
   (use (label_ref (match_operand 1 "" "")))]
1159
  ""
1160
  "jmp%#\\t@%0"
1161
  [(set_attr "delay_type" "delayed")]
1162
)
1163
 
1164
;;}}} 
1165
;;{{{ Function Prologues and Epilogues
1166
 
1167
;; Called after register allocation to add any instructions needed for the
1168
;; prologue.  Using a prologue insn is favored compared to putting all of the
1169
;; instructions in output_function_prologue(), since it allows the scheduler
1170
;; to intermix instructions with the saves of the caller saved registers.  In
1171
;; some cases, it might be necessary to emit a barrier instruction as the last
1172
;; insn to prevent such scheduling.
1173
(define_expand "prologue"
1174
  [(clobber (const_int 0))]
1175
  ""
1176
  "{
1177
  fr30_expand_prologue ();
1178
  DONE;
1179
  }"
1180
)
1181
 
1182
;; Called after register allocation to add any instructions needed for the
1183
;; epilogue.  Using an epilogue insn is favored compared to putting all of the
1184
;; instructions in output_function_epilogue(), since it allows the scheduler
1185
;; to intermix instructions with the restores of the caller saved registers.
1186
;; In some cases, it might be necessary to emit a barrier instruction as the
1187
;; first insn to prevent such scheduling.
1188
(define_expand "epilogue"
1189
  [(return)]
1190
  ""
1191
  "{
1192
  fr30_expand_epilogue ();
1193
  DONE;
1194
  }"
1195
)
1196
 
1197
(define_insn "return_from_func"
1198
  [(return)
1199
   (use (reg:SI 17))]
1200
  "reload_completed"
1201
  "ret%#"
1202
  [(set_attr "delay_type" "delayed")]
1203
)
1204
 
1205
(define_insn "leave_func"
1206
  [(set (reg:SI 15) (plus:SI (reg:SI 14) (const_int 4)))
1207
   (set (reg:SI 14) (mem:SI (minus:SI (reg:SI 15) (const_int 4))))]
1208
  "reload_completed"
1209
  "leave"
1210
)
1211
 
1212
(define_expand "enter_func"
1213
  [(parallel
1214
  [(set (mem:SI (minus:SI (match_dup 1)
1215
                          (const_int 4)))
1216
        (match_dup 2))
1217
   (set (match_dup 2)
1218
        (minus:SI (match_dup 1)
1219
                  (const_int 4)))
1220
   (set (match_dup 1)
1221
        (minus:SI (match_dup 1)
1222
                  (match_operand:SI 0 "immediate_operand")))]
1223
  )]
1224
  ""
1225
{
1226
  operands[1] = stack_pointer_rtx;
1227
  operands[2] = hard_frame_pointer_rtx;
1228
})
1229
 
1230
(define_insn "*enter_func"
1231
  [(set (mem:SI (minus:SI (reg:SI 15)
1232
                          (const_int 4)))
1233
        (reg:SI 14))
1234
   (set (reg:SI 14)
1235
        (minus:SI (reg:SI 15)
1236
                  (const_int 4)))
1237
   (set (reg:SI 15)
1238
        (minus:SI (reg:SI 15)
1239
                  (match_operand 0 "immediate_operand" "i")))]
1240
  "reload_completed"
1241
  "enter        #%0"
1242
  [(set_attr "delay_type" "other")]
1243
)
1244
 
1245
;;}}} 
1246
;;{{{ Miscellaneous
1247
 
1248
;; No operation, needed in case the user uses -g but not -O.
1249
(define_insn "nop"
1250
  [(const_int 0)]
1251
  ""
1252
  "nop"
1253
)
1254
 
1255
;; Pseudo instruction that prevents the scheduler from moving code above this
1256
;; point.
1257
(define_insn "blockage"
1258
  [(unspec_volatile [(const_int 0)] 0)]
1259
  ""
1260
  ""
1261
  [(set_attr "length" "0")]
1262
)
1263
;;}}} 
1264
 
1265
;; Local Variables:
1266
;; mode: md
1267
;; folded-file: t
1268
;; End:

powered by: WebSVN 2.1.0

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