xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/microblaze/microblaze.md (revision aef5eb5f59cdfe8314f1b5f78ac04eb144e44010)
1;; microblaze.md -- Machine description for Xilinx MicroBlaze processors.
2;; Copyright (C) 2009-2019 Free Software Foundation, Inc.
3
4;; Contributed by Michael Eager <eager@eagercon.com>.
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;; <http://www.gnu.org/licenses/>.  */
21
22(include "constraints.md")
23(include "predicates.md")
24
25;;----------------------------------------------------
26;; Constants
27;;----------------------------------------------------
28(define_constants [
29  (R_SP        1)       ;; Stack pointer reg
30  (R_SR       15)       ;; Sub-routine return addr reg
31  (R_IR       14)       ;; Interrupt return addr reg
32  (R_DR       16)       ;; Debug trap return addr reg
33  (R_ER       17)       ;; Exception return addr reg
34  (R_TMP      18)       ;; Assembler temporary reg
35  (R_GOT      20)       ;; GOT ptr reg
36  (MB_PIPE_3   0)       ;; Microblaze 3-stage pipeline
37  (MB_PIPE_5   1)       ;; Microblaze 5-stage pipeline
38  (UNSPEC_SET_GOT       101)    ;;
39  (UNSPEC_GOTOFF        102)    ;; GOT offset
40  (UNSPEC_PLT           103)    ;; jump table
41  (UNSPEC_CMP		104)    ;; signed compare
42  (UNSPEC_CMPU		105)    ;; unsigned compare
43  (UNSPEC_TLS           106)    ;; jump table
44  (UNSPEC_SET_TEXT      107)    ;; set text start
45  (UNSPEC_TEXT          108)    ;; data text relative
46])
47
48(define_c_enum "unspec" [
49  UNSPEC_IPREFETCH
50])
51
52;;----------------------------------------------------
53;; Instruction Attributes
54;;----------------------------------------------------
55
56;; Classification of each insn.
57;; branch	conditional branch
58;; jump		unconditional jump
59;; call		unconditional call
60;; load		load instruction(s)
61;; store	store instruction(s)
62;; move		data movement within same register set
63;; arith	integer arithmetic instruction
64;; darith	double precision integer arithmetic instructions
65;; imul		integer multiply
66;; idiv		integer divide
67;; icmp		integer compare
68;; Xfadd		floating point add/subtract
69;; Xfmul		floating point multiply
70;; Xfmadd	floating point multiply-add
71;; Xfdiv		floating point divide
72;; Xfabs		floating point absolute value
73;; Xfneg		floating point negation
74;; Xfcmp		floating point compare
75;; Xfcvt		floating point convert
76;; Xfsqrt	floating point square root
77;; multi	multiword sequence (or user asm statements)
78;; nop		no operation
79;; bshift 	Shift operations
80
81(define_attr "type"
82  "unknown,branch,jump,call,load,store,move,arith,darith,imul,idiv,icmp,multi,nop,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,bshift,fadd,frsub,fmul,fdiv,fcmp,fsl,fsqrt,fcvt,trap"
83  (const_string "unknown"))
84
85;; Main data type used by the insn
86(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown"))
87
88;; # instructions (4 bytes each)
89(define_attr "length" "" (const_int 4))
90
91(define_code_iterator any_return [return simple_return])
92
93;; <optab> expands to the name of the optab for a particular code.
94(define_code_attr optab [(return "return")
95			 (simple_return "simple_return")])
96
97
98;;----------------------------------------------------
99;; Attribute describing the processor.
100;;----------------------------------------------------
101
102;; Describe a user's asm statement.
103(define_asm_attributes
104  [(set_attr "type" "multi")])
105
106;; whether or not generating calls to position independent functions
107(define_attr "abicalls" "no,yes"
108  (const (symbol_ref "microblaze_abicalls_attr")))
109
110;;----------------------------------------------------------------
111;; Microblaze DFA Pipeline description
112;;----------------------------------------------------------------
113
114;;-----------------------------------------------------------------
115/*
116   This is description of pipeline hazards based on DFA.  The
117   following constructions can be used for this:
118
119   o define_cpu_unit string [string]) describes a cpu functional unit
120     (separated by comma).
121
122     1st operand: Names of cpu function units.
123     2nd operand: Name of automaton (see comments for
124     DEFINE_AUTOMATON).
125
126     All define_reservations and define_cpu_units should have unique
127     names which cannot be "nothing".
128
129   o (exclusion_set string string) means that each CPU function unit
130     in the first string cannot be reserved simultaneously with each
131     unit whose name is in the second string and vise versa.  CPU
132     units in the string are separated by commas. For example, it is
133     useful for description CPU with fully pipelined floating point
134     functional unit which can execute simultaneously only single
135     floating point insns or only double floating point insns.
136
137   o (presence_set string string) means that each CPU function unit in
138     the first string cannot be reserved unless at least one of units
139     whose names are in the second string is reserved.  This is an
140     asymmetric relation.  CPU units in the string are separated by
141     commas.  For example, it is useful for description that slot1 is
142     reserved after slot0 reservation for a VLIW processor.
143
144   o (absence_set string string) means that each CPU function unit in
145     the first string cannot be reserved only if each unit whose name
146     is in the second string is not reserved.  This is an asymmetric
147     relation (actually exclusion set is analogous to this one but it
148     is symmetric).  CPU units in the string are separated by commas.
149     For example, it is useful for description that slot0 cannot be
150     reserved after slot1 or slot2 reservation for a VLIW processor.
151
152   o (define_bypass number out_insn_names in_insn_names) names bypass with
153     given latency (the first number) from insns given by the first
154     string (see define_insn_reservation) into insns given by the
155     second string.  Insn names in the strings are separated by
156     commas.
157
158   o (define_automaton string) describes names of an automaton
159     generated and used for pipeline hazards recognition.  The names
160     are separated by comma.  Actually it is possibly to generate the
161     single automaton but unfortunately it can be very large.  If we
162     use more one automata, the summary size of the automata usually
163     is less than the single one.  The automaton name is used in
164     define_cpu_unit.  All automata should have unique names.
165
166   o (define_reservation string string) names reservation (the first
167     string) of cpu functional units (the 2nd string).  Sometimes unit
168     reservations for different insns contain common parts.  In such
169     case, you describe common part and use one its name (the 1st
170     parameter) in regular expression in define_insn_reservation.  All
171     define_reservations, define results and define_cpu_units should
172     have unique names which cannot be "nothing".
173
174   o (define_insn_reservation name default_latency condition regexpr)
175     describes reservation of cpu functional units (the 3nd operand)
176     for instruction which is selected by the condition (the 2nd
177     parameter).  The first parameter is used for output of debugging
178     information.  The reservations are described by a regular
179     expression according the following syntax:
180
181       regexp = regexp "," oneof
182              | oneof
183
184       oneof = oneof "|" allof
185             | allof
186
187       allof = allof "+" repeat
188             | repeat
189
190       repeat = element "*" number
191              | element
192
193       element = cpu_function_name
194               | reservation_name
195               | result_name
196               | "nothing"
197               | "(" regexp ")"
198
199       1. "," is used for describing start of the next cycle in
200          reservation.
201
202       2. "|" is used for describing the reservation described by the
203          first regular expression *or* the reservation described by
204          the second regular expression *or* etc.
205
206       3. "+" is used for describing the reservation described by the
207          first regular expression *and* the reservation described by
208          the second regular expression *and* etc.
209
210       4. "*" is used for convenience and simply means sequence in
211          which the regular expression are repeated NUMBER times with
212          cycle advancing (see ",").
213
214       5. cpu function unit name which means reservation.
215
216       6. reservation name -- see define_reservation.
217
218       7. string "nothing" means no units reservation.
219
220*/
221;;-----------------------------------------------------------------
222
223
224;;----------------------------------------------------------------
225;; Microblaze 5-stage pipeline description (v5.00.a and later)
226;;----------------------------------------------------------------
227
228(define_automaton   "mbpipe_5")
229(define_cpu_unit    "mb_issue,mb_iu,mb_wb,mb_fpu,mb_fpu_2,mb_mul,mb_mul_2,mb_div,mb_div_2,mb_bs,mb_bs_2" "mbpipe_5")
230
231(define_insn_reservation "mb-integer" 1
232  (and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith")
233       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
234  "mb_issue,mb_iu,mb_wb")
235
236(define_insn_reservation "mb-special-move" 2
237  (and (eq_attr "type" "move")
238       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
239  "mb_issue,mb_iu*2,mb_wb")
240
241(define_insn_reservation "mb-mem-load" 3
242  (and (eq_attr "type" "load,no_delay_load")
243       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
244  "mb_issue,mb_iu,mb_wb")
245
246(define_insn_reservation "mb-mem-store" 1
247  (and (eq_attr "type" "store,no_delay_store")
248       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
249  "mb_issue,mb_iu,mb_wb")
250
251(define_insn_reservation "mb-mul" 3
252  (and (eq_attr "type" "imul,no_delay_imul")
253       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
254  "mb_issue,mb_mul,mb_mul_2*2,mb_wb")
255
256(define_insn_reservation "mb-div" 34
257  (and (eq_attr "type" "idiv")
258       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
259    "mb_issue,mb_div,mb_div_2*33,mb_wb")
260
261(define_insn_reservation "mb-bs" 2
262  (and (eq_attr "type" "bshift")
263       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
264   "mb_issue,mb_bs,mb_bs_2,mb_wb")
265
266(define_insn_reservation "mb-fpu-add-sub-mul" 6
267  (and (eq_attr "type" "fadd,frsub,fmul")
268       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
269  "mb_issue,mb_fpu,mb_fpu_2*5,mb_wb")
270
271(define_insn_reservation "mb-fpu-fcmp" 3
272  (and (eq_attr "type" "fcmp")
273       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
274  "mb_issue,mb_fpu,mb_fpu*2,mb_wb")
275
276(define_insn_reservation "mb-fpu-div" 30
277  (and (eq_attr "type" "fdiv")
278       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
279  "mb_issue,mb_fpu,mb_fpu_2*29,mb_wb")
280
281(define_insn_reservation "mb-fpu-sqrt" 30
282  (and (eq_attr "type" "fsqrt")
283       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
284  "mb_issue,mb_fpu,mb_fpu_2*29,mb_wb")
285
286(define_insn_reservation "mb-fpu-fcvt" 4
287  (and (eq_attr "type" "fcvt")
288       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_5)))
289  "mb_issue,mb_fpu,mb_fpu_2*3,mb_wb")
290
291;;----------------------------------------------------------------
292;; Microblaze 3-stage pipeline description (for v4.00.a and earlier)
293;;----------------------------------------------------------------
294
295(define_automaton   "mbpipe_3")
296(define_cpu_unit    "mb3_iu" "mbpipe_3")
297
298(define_insn_reservation "mb3-integer" 1
299  (and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith")
300       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
301  "mb3_iu")
302
303(define_insn_reservation "mb3-special-move" 2
304  (and (eq_attr "type" "move")
305       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
306  "mb3_iu*2")
307
308(define_insn_reservation "mb3-mem-load" 2
309  (and (eq_attr "type" "load,no_delay_load")
310       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
311  "mb3_iu")
312
313(define_insn_reservation "mb3-mem-store" 1
314  (and (eq_attr "type" "store,no_delay_store")
315       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
316  "mb3_iu")
317
318(define_insn_reservation "mb3-mul" 3
319  (and (eq_attr "type" "imul,no_delay_imul")
320       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
321  "mb3_iu")
322
323(define_insn_reservation "mb3-div" 34
324  (and (eq_attr "type" "idiv")
325       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
326    "mb3_iu")
327
328(define_insn_reservation "mb3-bs" 2
329  (and (eq_attr "type" "bshift")
330       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
331   "mb3_iu")
332
333(define_insn_reservation "mb3-fpu-add-sub-mul" 6
334  (and (eq_attr "type" "fadd,frsub,fmul")
335       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
336  "mb3_iu")
337
338(define_insn_reservation "mb3-fpu-fcmp" 3
339  (and (eq_attr "type" "fcmp")
340       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
341  "mb3_iu")
342
343(define_insn_reservation "mb3-fpu-div" 30
344  (and (eq_attr "type" "fdiv")
345       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
346  "mb3_iu")
347
348(define_insn_reservation "mb3-fpu-sqrt" 30
349  (and (eq_attr "type" "fsqrt")
350       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
351  "mb3_iu")
352
353(define_insn_reservation "mb3-fpu-fcvt" 4
354  (and (eq_attr "type" "fcvt")
355       (eq (symbol_ref  "microblaze_pipe") (const_int MB_PIPE_3)))
356  "mb3_iu")
357
358(automata_option "v")
359(automata_option "time")
360(automata_option "progress")
361
362(define_insn "bswapsi2"
363  [(set (match_operand:SI 0 "register_operand" "=r")
364        (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
365  "TARGET_REORDER"
366  "swapb %0, %1"
367)
368
369(define_insn "bswaphi2"
370  [(set (match_operand:HI 0 "register_operand" "=r")
371        (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
372  "TARGET_REORDER"
373  "swapb %0, %1
374   swaph %0, %0"
375)
376
377;;----------------------------------------------------------------
378;; Microblaze delay slot description
379;;----------------------------------------------------------------
380(define_delay (eq_attr "type" "branch,call,jump")
381  [(and (eq_attr "type" "!branch,call,jump,icmp,multi,no_delay_arith,no_delay_load,no_delay_store,no_delay_imul,no_delay_move,darith")
382        (ior (not (match_test "microblaze_no_unsafe_delay"))
383             (eq_attr "type" "!fadd,frsub,fmul,fdiv,fcmp,store,load")
384             ))
385  (nil) (nil)])
386
387
388;;----------------------------------------------------------------
389;; Microblaze FPU
390;;----------------------------------------------------------------
391
392(define_insn "addsf3"
393  [(set (match_operand:SF 0 "register_operand" "=d")
394        (plus:SF (match_operand:SF 1 "register_operand" "d")
395                 (match_operand:SF 2 "register_operand" "d")))]
396  "TARGET_HARD_FLOAT"
397  "fadd\t%0,%1,%2"
398  [(set_attr "type"     "fadd")
399  (set_attr "mode"      "SF")
400  (set_attr "length"    "4")])
401
402(define_insn "subsf3"
403  [(set (match_operand:SF 0 "register_operand" "=d")
404        (minus:SF (match_operand:SF 1 "register_operand" "d")
405                  (match_operand:SF 2 "register_operand" "d")))]
406  "TARGET_HARD_FLOAT"
407  "frsub\t%0,%2,%1"
408  [(set_attr "type"     "frsub")
409  (set_attr "mode"      "SF")
410  (set_attr "length"    "4")])
411
412(define_insn "mulsf3"
413  [(set (match_operand:SF 0 "register_operand" "=d")
414        (mult:SF (match_operand:SF 1 "register_operand" "d")
415                 (match_operand:SF 2 "register_operand" "d")))]
416  "TARGET_HARD_FLOAT"
417  "fmul\t%0,%1,%2"
418  [(set_attr "type"     "fmul")
419  (set_attr "mode"      "SF")
420  (set_attr "length"    "4")])
421
422
423(define_insn "divsf3"
424  [(set (match_operand:SF 0 "register_operand" "=d")
425        (div:SF (match_operand:SF 1 "register_operand" "d")
426                (match_operand:SF 2 "register_operand" "d")))]
427  "TARGET_HARD_FLOAT"
428  "fdiv\t%0,%2,%1"
429  [(set_attr "type"     "fdiv")
430  (set_attr "mode"      "SF")
431  (set_attr "length"    "4")])
432
433(define_insn "sqrtsf2"
434  [(set (match_operand:SF 0 "register_operand" "=d")
435        (sqrt:SF (match_operand:SF 1 "register_operand" "d")))]
436  "TARGET_HARD_FLOAT && TARGET_FLOAT_SQRT"
437  "fsqrt\t%0,%1"
438  [(set_attr "type"     "fsqrt")
439  (set_attr "mode"      "SF")
440  (set_attr "length"    "4")])
441
442(define_insn "floatsisf2"
443  [(set (match_operand:SF 0 "register_operand" "=d")
444        (float:SF (match_operand:SI 1 "register_operand" "d")))]
445  "TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT"
446  "flt\t%0,%1"
447  [(set_attr "type"     "fcvt")
448  (set_attr "mode"      "SF")
449  (set_attr "length"    "4")])
450
451(define_insn "fix_truncsfsi2"
452  [(set (match_operand:SI 0 "register_operand" "=d")
453        (fix:SI (match_operand:SF 1 "register_operand" "d")))]
454  "TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT"
455  "fint\t%0,%1"
456  [(set_attr "type"     "fcvt")
457  (set_attr "mode"      "SF")
458  (set_attr "length"    "4")])
459
460;;----------------------------------------------------------------
461;; Add
462;;----------------------------------------------------------------
463
464;; Add 2 SImode integers [ src1 = reg ; src2 = arith ; dest = reg ]
465;; Leave carry as is
466(define_insn "addsi3"
467  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
468	(plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ")
469		 (match_operand:SI 2 "arith_plus_operand" "d,I,i")))]
470  ""
471  "@
472   addk\t%0,%z1,%2
473   addik\t%0,%z1,%2
474   addik\t%0,%z1,%2"
475  [(set_attr "type"	"arith,arith,no_delay_arith")
476  (set_attr "mode"	"SI,SI,SI")
477  (set_attr "length"	"4,4,8")])
478
479;;----------------------------------------------------------------
480;; Double Precision Additions
481;;----------------------------------------------------------------
482
483;; reg_DI_dest = reg_DI_src1 + DI_src2
484
485;; Adding 2 DI operands in register or reg/imm
486
487(define_insn "adddi3"
488  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
489	(plus:DI (match_operand:DI 1 "register_operand" "%d,d,d")
490		 (match_operand:DI 2 "arith_operand32" "d,P,N")))]
491  ""
492  "@
493  add\t%L0,%L1,%L2\;addc\t%M0,%M1,%M2
494  addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0
495  addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0\;addi\t%M0,%M0,-1"
496  [(set_attr "type"	"darith")
497  (set_attr "mode"	"DI")
498  (set_attr "length"	"8,8,12")])
499
500;;----------------------------------------------------------------
501;; Subtraction
502;;----------------------------------------------------------------
503
504(define_insn "subsi3"
505  [(set (match_operand:SI 0 "register_operand" "=d,d")
506	(minus:SI (match_operand:SI 1 "arith_operand" "d,d")
507		  (match_operand:SI 2 "arith_operand" "d,n")))]
508  ""
509  "@
510   rsubk\t%0,%2,%z1
511   addik\t%0,%z1,-%2"
512  [(set_attr "type"	"arith,no_delay_arith")
513  (set_attr "mode"	"SI")
514  (set_attr "length"	"4,8")])
515
516(define_insn "iprefetch"
517  [(unspec [(match_operand:SI 0 "const_int_operand" "n")] UNSPEC_IPREFETCH)
518   (clobber (mem:BLK (scratch)))]
519   "TARGET_PREFETCH"
520  {
521    operands[2] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
522    return "mfs\t%2,rpc\n\twic\t%2,r0";
523  }
524  [(set_attr "type" "arith")
525   (set_attr "mode"  "SI")
526   (set_attr "length"    "8")])
527
528;;----------------------------------------------------------------
529;; Double Precision Subtraction
530;;----------------------------------------------------------------
531
532(define_insn "subdi3"
533  [(set (match_operand:DI 0 "register_operand" "=&d")
534	(minus:DI (match_operand:DI 1 "register_operand" "d")
535		  (match_operand:DI 2 "arith_operand32" "d")))]
536  ""
537  "rsub\t%L0,%L2,%L1\;rsubc\t%M0,%M2,%M1"
538  [(set_attr "type"	"darith")
539  (set_attr "mode"	"DI")
540  (set_attr "length"	"8")])
541
542
543;;----------------------------------------------------------------
544;; Multiplication
545;;----------------------------------------------------------------
546
547(define_insn "mulsi3"
548  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
549	(mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
550		 (match_operand:SI 2 "arith_operand" "d,I,i")))]
551  "!TARGET_SOFT_MUL"
552  "@
553  mul\t%0,%1,%2
554  muli\t%0,%1,%2
555  muli\t%0,%1,%2"
556  [(set_attr "type"	"imul,imul,no_delay_imul")
557  (set_attr "mode"	"SI")
558  (set_attr "length"	"4,4,8")])
559
560(define_insn "mulsidi3"
561  [(set (match_operand:DI 0 "register_operand" "=&d")
562        (mult:DI
563         (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
564         (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
565  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
566  "mul\t%L0,%1,%2\;mulh\t%M0,%1,%2"
567  [(set_attr "type"     "no_delay_arith")
568   (set_attr "mode"     "DI")
569   (set_attr "length"   "8")])
570
571(define_insn "umulsidi3"
572  [(set (match_operand:DI 0 "register_operand" "=&d")
573        (mult:DI
574         (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
575         (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
576  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
577  "mul\t%L0,%1,%2\;mulhu\t%M0,%1,%2"
578  [(set_attr "type"     "no_delay_arith")
579   (set_attr "mode"     "DI")
580   (set_attr "length"   "8")])
581
582(define_insn "usmulsidi3"
583  [(set (match_operand:DI 0 "register_operand" "=&d")
584        (mult:DI
585         (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
586         (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
587  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
588  "mul\t%L0,%1,%2\;mulhsu\t%M0,%2,%1"
589  [(set_attr "type"     "no_delay_arith")
590   (set_attr "mode"     "DI")
591   (set_attr "length"   "8")])
592
593(define_insn "*smulsi3_highpart"
594  [(set (match_operand:SI 0 "register_operand" "=d")
595        (truncate:SI
596         (lshiftrt:DI
597          (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "d"))
598                   (sign_extend:DI (match_operand:SI 2 "register_operand"  "d")))
599          (const_int 32))))]
600  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
601  "mulh\t%0,%1,%2"
602  [(set_attr "type"     "imul")
603  (set_attr "mode"      "SI")
604  (set_attr "length"    "4")])
605
606(define_insn "*umulsi3_highpart"
607  [(set (match_operand:SI 0 "register_operand"                            "=d")
608        (truncate:SI
609         (lshiftrt:DI
610          (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "d"))
611                   (zero_extend:DI (match_operand:SI 2 "register_operand"  "d"))
612)
613          (const_int 32))))]
614  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
615  "mulhu\t%0,%1,%2"
616  [(set_attr "type"     "imul")
617  (set_attr "mode"      "SI")
618  (set_attr "length"    "4")])
619
620(define_insn "*usmulsi3_highpart"
621  [(set (match_operand:SI 0 "register_operand"                            "=d")
622        (truncate:SI
623         (lshiftrt:DI
624          (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "d"))
625                   (sign_extend:DI (match_operand:SI 2 "register_operand"  "d"))
626)
627          (const_int 32))))]
628  "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
629  "mulhsu\t%0,%2,%1"
630  [(set_attr "type"     "imul")
631  (set_attr "mode"      "SI")
632  (set_attr "length"    "4")])
633
634
635;;----------------------------------------------------------------
636;; Division and remainder
637;;----------------------------------------------------------------
638(define_expand "divsi3"
639  [(set (match_operand:SI 0 "register_operand" "=d")
640	(div:SI (match_operand:SI 1 "register_operand" "d")
641                (match_operand:SI 2 "register_operand" "d")))
642  ]
643  "(!TARGET_SOFT_DIV) || (TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)"
644  {
645    if (TARGET_SOFT_DIV && TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)
646      {
647        microblaze_expand_divide (operands);
648        DONE;
649      }
650    else if (!TARGET_SOFT_DIV)
651      {
652        emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2]));
653        DONE;
654      }
655  }
656)
657
658
659(define_insn "divsi3_internal"
660  [(set (match_operand:SI 0 "register_operand" "=d")
661	(div:SI (match_operand:SI 1 "register_operand" "d")
662		(match_operand:SI 2 "register_operand" "d")))
663  ]
664  "!TARGET_SOFT_DIV"
665  "idiv\t%0,%2,%1"
666  [(set_attr "type"	"idiv")
667  (set_attr "mode"	"SI")
668  (set_attr "length"	"4")]
669)
670
671(define_insn "udivsi3"
672  [(set (match_operand:SI 0 "register_operand" "=d")
673	(udiv:SI (match_operand:SI 1 "register_operand" "d")
674                 (match_operand:SI 2 "register_operand" "d")))
675  ]
676  "!TARGET_SOFT_DIV"
677  "idivu\t%0,%2,%1"
678  [(set_attr "type"	"idiv")
679  (set_attr "mode"	"SI")
680  (set_attr "length"	"4")])
681
682(define_peephole2
683  [(set (match_operand:SI 0 "register_operand")
684        (fix:SI (match_operand:SF 1 "register_operand")))
685   (set (pc)
686        (if_then_else (match_operator 2 "ordered_comparison_operator"
687                       [(match_operand:SI 3 "register_operand")
688                        (match_operand:SI 4 "arith_operand")])
689                      (label_ref (match_operand 5))
690                      (pc)))]
691   "TARGET_HARD_FLOAT"
692   [(set (match_dup 1) (match_dup 3))]
693
694  {
695    rtx condition;
696    rtx cmp_op0 = operands[3];
697    rtx cmp_op1 = operands[4];
698    rtx comp_reg =  gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
699
700    emit_insn (gen_cstoresf4 (comp_reg, operands[2],
701                              gen_rtx_REG (SFmode, REGNO (cmp_op0)),
702                              gen_rtx_REG (SFmode, REGNO (cmp_op1))));
703    condition = gen_rtx_NE (SImode, comp_reg, const0_rtx);
704    emit_jump_insn (gen_condjump (condition, operands[5]));
705  }
706)
707
708;;----------------------------------------------------------------
709;; Negation and one's complement
710;;----------------------------------------------------------------
711
712(define_insn "negsi2"
713  [(set (match_operand:SI 0 "register_operand" "=d")
714	(neg:SI (match_operand:SI 1 "register_operand" "d")))]
715  ""
716  "rsubk\t%0,%1,r0"
717  [(set_attr "type"	"arith")
718  (set_attr "mode"	"SI")
719  (set_attr "length"	"4")])
720
721(define_insn "negdi2"
722  [(set (match_operand:DI 0 "register_operand" "=d")
723	(neg:DI (match_operand:DI 1 "register_operand" "d")))]
724  ""
725  "rsub\t%L0,%L1,r0\;rsubc\t%M0,%M1,r0"
726  [(set_attr "type"	"darith")
727  (set_attr "mode"	"DI")
728  (set_attr "length"	"8")])
729
730
731(define_insn "one_cmplsi2"
732  [(set (match_operand:SI 0 "register_operand" "=d")
733	(not:SI (match_operand:SI 1 "register_operand" "d")))]
734  ""
735  "xori\t%0,%1,-1"
736  [(set_attr "type"	"arith")
737  (set_attr "mode"	"SI")
738  (set_attr "length"	"4")])
739
740(define_insn "*one_cmpldi2"
741  [(set (match_operand:DI 0 "register_operand" "=d")
742	(not:DI (match_operand:DI 1 "register_operand" "d")))]
743  ""
744  "nor\t%M0,r0,%M1\;nor\t%L0,r0,%L1"
745  [(set_attr "type"	"darith")
746  (set_attr "mode"	"DI")
747  (set_attr "length"    "8")]
748)
749
750(define_split
751  [(set (match_operand:DI 0 "register_operand" "")
752	(not:DI (match_operand:DI 1 "register_operand" "")))]
753  "reload_completed
754   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
755   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
756
757  [(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0)))
758  (set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))]
759  "")
760
761
762;;----------------------------------------------------------------
763;; Logical
764;;----------------------------------------------------------------
765
766(define_insn "andsi3"
767  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
768	(and:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d")
769		(match_operand:SI 2 "arith_operand" "d,I,i,M")))]
770  ""
771  "@
772   and\t%0,%1,%2
773   andi\t%0,%1,%2 #and1
774   andi\t%0,%1,%2 #and2
775   andi\t%0,%1,%2 #and3"
776  [(set_attr "type"	"arith,arith,no_delay_arith,no_delay_arith")
777  (set_attr "mode"	"SI,SI,SI,SI")
778  (set_attr "length"	"4,8,8,8")])
779
780
781(define_insn "iorsi3"
782  [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
783	(ior:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d")
784		(match_operand:SI 2 "arith_operand" "d,I,M,i")))]
785  ""
786  "@
787   or\t%0,%1,%2
788   ori\t%0,%1,%2
789   ori\t%0,%1,%2
790   ori\t%0,%1,%2"
791  [(set_attr "type"	"arith,no_delay_arith,no_delay_arith,no_delay_arith")
792  (set_attr "mode"	"SI,SI,SI,SI")
793  (set_attr "length"	"4,8,8,8")])
794
795(define_insn "xorsi3"
796  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
797	(xor:SI (match_operand:SI 1 "arith_operand" "%d,d,d")
798		(match_operand:SI 2 "arith_operand" "d,I,i")))]
799  ""
800  "@
801   xor\t%0,%1,%2
802   xori\t%0,%1,%2
803   xori\t%0,%1,%2"
804  [(set_attr "type"	"arith,arith,no_delay_arith")
805  (set_attr "mode"	"SI,SI,SI")
806  (set_attr "length"	"4,8,8")])
807
808;;----------------------------------------------------------------
809;; Zero extension
810;;----------------------------------------------------------------
811
812(define_insn "zero_extendhisi2"
813  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
814	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))]
815  ""
816  "@
817  andi\t%0,%1,0xffff
818  lhu%i1\t%0,%1
819  lhu%i1\t%0,%1"
820  [(set_attr "type"	"no_delay_arith,load,no_delay_load")
821  (set_attr "mode"	"SI,SI,SI")
822  (set_attr "length"	"8,4,8")])
823
824(define_insn "zero_extendqihi2"
825  [(set (match_operand:HI 0 "register_operand" "=d,d,d")
826	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))]
827  ""
828  "@
829  andi\t%0,%1,0x00ff
830  lbu%i1\t%0,%1
831  lbu%i1\t%0,%1"
832  [(set_attr "type"	"arith,load,no_delay_load")
833  (set_attr "mode"	"HI")
834  (set_attr "length"	"4,4,8")])
835
836(define_insn "zero_extendqisi2"
837  [(set (match_operand:SI 0 "register_operand" "=d,d,d")
838	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))]
839  ""
840  "@
841  andi\t%0,%1,0x00ff
842  lbu%i1\t%0,%1
843  lbu%i1\t%0,%1"
844  [(set_attr "type"	"arith,load,no_delay_load")
845  (set_attr "mode"	"SI,SI,SI")
846  (set_attr "length"	"4,4,8")])
847
848;;----------------------------------------------------------------
849;; Sign extension
850;;----------------------------------------------------------------
851
852;; basic Sign Extend Operations
853
854(define_insn "extendqisi2"
855  [(set (match_operand:SI 0 "register_operand" "=d")
856	(sign_extend:SI (match_operand:QI 1 "register_operand" "d")))]
857  ""
858  "sext8\t%0,%1"
859  [(set_attr "type"	"arith")
860  (set_attr "mode"	"SI")
861  (set_attr "length"	"4")])
862
863(define_insn "extendhisi2"
864  [(set (match_operand:SI 0 "register_operand" "=d")
865	(sign_extend:SI (match_operand:HI 1 "register_operand" "d")))]
866  ""
867  "sext16\t%0,%1"
868  [(set_attr "type"	"arith")
869  (set_attr "mode"	"SI")
870  (set_attr "length"	"4")])
871
872;; Those for integer source operand are ordered
873;; widest source type first.
874
875(define_insn "extendsidi2"
876  [(set (match_operand:DI 0 "register_operand" "=d,d,d")
877	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))]
878  ""
879  {
880     if (which_alternative == 0)
881       output_asm_insn ("addk\t%L0,r0,%1", operands);
882     else
883       output_asm_insn ("lw%i1\t%L0,%1", operands);
884
885     output_asm_insn ("add\t%M0,%L0,%L0", operands);
886     output_asm_insn ("addc\t%M0,r0,r0", operands);
887     output_asm_insn ("beqi\t%M0,.+8", operands);
888     return "addi\t%M0,r0,0xffffffff";
889  }
890  [(set_attr "type"	"multi,multi,multi")
891  (set_attr "mode"	"DI")
892  (set_attr "length"	"20,20,20")])
893
894;;----------------------------------------------------------------
895;; Data movement
896;;----------------------------------------------------------------
897
898;; 64-bit integer moves
899
900;; Unlike most other insns, the move insns can't be split with
901;; different predicates, because register spilling and other parts of
902;; the compiler, have memoized the insn number already.
903
904(define_expand "movdi"
905  [(set (match_operand:DI 0 "nonimmediate_operand" "")
906	(match_operand:DI 1 "general_operand" ""))]
907  ""
908  {
909    /* If operands[1] is a constant address illegal for pic, then we need to
910       handle it just like microblaze_legitimize_address does.  */
911    if (flag_pic && pic_address_needs_scratch (operands[1]))
912    {
913        rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0));
914        rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
915        emit_move_insn (operands[0], gen_rtx_PLUS (DImode, temp, temp2));
916        DONE;
917    }
918
919
920    if ((reload_in_progress | reload_completed) == 0
921        && !register_operand (operands[0], DImode)
922        && !register_operand (operands[1], DImode)
923        && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
924	       && operands[1] != CONST0_RTX (DImode))))
925    {
926
927      rtx temp = force_reg (DImode, operands[1]);
928      emit_move_insn (operands[0], temp);
929      DONE;
930    }
931  }
932)
933
934
935
936(define_insn "*movdi_internal"
937  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,o")
938	(match_operand:DI 1 "general_operand"      " d,i,J,R,o,d,d"))]
939  ""
940  {
941    switch (which_alternative)
942    {
943      case 0:
944        return "addk\t%0,%1\n\taddk\t%D0,%d1";
945      case 1:
946	return "addik\t%M0,r0,%h1\n\taddik\t%L0,r0,%j1 #li => la";
947      case 2:
948	  return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";
949      case 3:
950      case 4:
951        if (reg_mentioned_p (operands[0], operands[1]))
952          return "lwi\t%D0,%o1\n\tlwi\t%0,%1";
953	else
954	  return "lwi\t%0,%1\n\tlwi\t%D0,%o1";
955      case 5:
956      case 6:
957        return "swi\t%1,%0\n\tswi\t%D1,%o0";
958    }
959    return "unreachable";
960  }
961  [(set_attr "type"	"no_delay_move,no_delay_arith,no_delay_arith,no_delay_load,no_delay_load,no_delay_store,no_delay_store")
962  (set_attr "mode"	"DI")
963  (set_attr "length"   "8,8,8,8,12,8,12")])
964
965(define_split
966  [(set (match_operand:DI 0 "register_operand" "")
967	(match_operand:DI 1 "register_operand" ""))]
968  "reload_completed
969   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
970   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
971   && (REGNO(operands[0]) == (REGNO(operands[1]) + 1))"
972
973  [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))
974  (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]
975  "")
976
977(define_split
978  [(set (match_operand:DI 0 "register_operand" "")
979	(match_operand:DI 1 "register_operand" ""))]
980  "reload_completed
981   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
982   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
983   && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"
984
985  [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
986  (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
987  "")
988
989;; Unlike most other insns, the move insns can't be split with
990;; different predicates, because register spilling and other parts of
991;; the compiler, have memoized the insn number already.
992
993(define_expand "movsi"
994  [(set (match_operand:SI 0 "nonimmediate_operand" "")
995	(match_operand:SI 1 "general_operand" ""))]
996  ""
997  {
998    if (microblaze_expand_move (SImode, operands)) DONE;
999  }
1000)
1001
1002;; Added for status registers
1003(define_insn "movsi_status"
1004  [(set (match_operand:SI 0 "register_operand" "=d,d,z")
1005        (match_operand:SI 1 "register_operand" "z,d,d"))]
1006  "microblaze_is_interrupt_variant ()"
1007  "@
1008	mfs\t%0,%1  #mfs
1009	addk\t%0,%1,r0 #add movsi
1010	mts\t%0,%1  #mts"
1011  [(set_attr "type" "move")
1012  (set_attr "mode" "SI")
1013  (set_attr "length" "12")])
1014
1015;; This move will be not be moved to delay slot.
1016(define_insn "*movsi_internal3"
1017  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d")
1018	(match_operand:SI 1 "immediate_operand" "J,I,Mnis"))]
1019  "(register_operand (operands[0], SImode) &&
1020           (GET_CODE (operands[1]) == CONST_INT &&
1021                 (INTVAL (operands[1]) <= 32767 && INTVAL (operands[1]) >= -32768)))"
1022  "@
1023   addk\t%0,r0,r0
1024   addik\t%0,r0,%1\t# %X1
1025   addik\t%0,r0,%1\t# %X1"
1026  [(set_attr "type"	"arith,arith,no_delay_arith")
1027  (set_attr "mode"	"SI")
1028  (set_attr "length"	"4")])
1029
1030;; This move may be used for PLT label operand
1031(define_insn "*movsi_internal5_pltop"
1032  [(set (match_operand:SI 0 "register_operand" "=d,d")
1033	(match_operand:SI 1 "call_insn_operand" ""))]
1034  "(register_operand (operands[0], Pmode) &&
1035           PLT_ADDR_P (operands[1]))"
1036  {
1037     gcc_unreachable ();
1038  }
1039  [(set_attr "type"	"load")
1040  (set_attr "mode"	"SI")
1041  (set_attr "length"	"4")])
1042
1043(define_insn "*movsi_internal2"
1044  [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,   d,d,R,m")
1045	(match_operand:SI 1 "move_src_operand"         " d,I,Mnis,R,m,dJ,dJ"))]
1046  ""
1047  "@
1048   addk\t%0,%1,r0
1049   addik\t%0,r0,%1\t# %X1
1050   addik\t%0,%a1
1051   lw%i1\t%0,%1
1052   lw%i1\t%0,%1
1053   sw%i0\t%z1,%0
1054   sw%i0\t%z1,%0"
1055  [(set_attr "type"	"load,load,no_delay_load,load,no_delay_load,store,no_delay_store")
1056  (set_attr "mode"	"SI")
1057  (set_attr "length"	"4,4,8,4,8,4,8")])
1058
1059
1060;; 16-bit Integer moves
1061
1062;; Unlike most other insns, the move insns can't be split with
1063;; different predicates, because register spilling and other parts of
1064;; the compiler, have memoized the insn number already.
1065;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined
1066
1067(define_expand "movhi"
1068  [(set (match_operand:HI 0 "nonimmediate_operand" "")
1069	(match_operand:HI 1 "general_operand" ""))]
1070  ""
1071  {
1072    if ((reload_in_progress | reload_completed) == 0
1073        && !register_operand (operands[0], HImode)
1074        && !register_operand (operands[1], HImode)
1075        && ((GET_CODE (operands[1]) != CONST_INT
1076  	    || INTVAL (operands[1]) != 0)))
1077    {
1078        rtx temp = force_reg (HImode, operands[1]);
1079        emit_move_insn (operands[0], temp);
1080        DONE;
1081    }
1082  }
1083)
1084
1085(define_insn "*movhi_internal2"
1086  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m")
1087	(match_operand:HI 1 "general_operand"       "I,d,R,m,dJ,dJ"))]
1088  ""
1089  "@
1090   addik\t%0,r0,%1\t# %X1
1091   addk\t%0,%1,r0
1092   lhui\t%0,%1
1093   lhui\t%0,%1
1094   sh%i0\t%z1,%0
1095   sh%i0\t%z1,%0"
1096  [(set_attr "type"	"arith,move,load,no_delay_load,store,no_delay_store")
1097  (set_attr "mode"	"HI")
1098  (set_attr "length"	"4,4,4,8,8,8")])
1099
1100;; 8-bit Integer moves
1101
1102;; Unlike most other insns, the move insns can't be split with
1103;; different predicates, because register spilling and other parts of
1104;; the compiler, have memoized the insn number already.
1105;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined
1106
1107(define_expand "movqi"
1108  [(set (match_operand:QI 0 "nonimmediate_operand" "")
1109	(match_operand:QI 1 "general_operand" ""))]
1110  ""
1111  {
1112    if ((reload_in_progress | reload_completed) == 0
1113        && !register_operand (operands[0], QImode)
1114        && !register_operand (operands[1], QImode)
1115        && ((GET_CODE (operands[1]) != CONST_INT
1116            || INTVAL (operands[1]) != 0)))
1117    {
1118        rtx temp = force_reg (QImode, operands[1]);
1119        emit_move_insn (operands[0], temp);
1120        DONE;
1121    }
1122  }
1123)
1124
1125(define_insn "*movqi_internal2"
1126  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
1127	(match_operand:QI 1 "general_operand"       "J,I,d,R,m,dJ,dJ"))]
1128  ""
1129  "@
1130   addk\t%0,r0,%z1
1131   addik\t%0,r0,%1\t# %X1
1132   addk\t%0,%1,r0
1133   lbu%i1\t%0,%1
1134   lbu%i1\t%0,%1
1135   sb%i0\t%z1,%0
1136   sbi\t%z1,%0"
1137  [(set_attr "type"	"arith,arith,move,load,no_delay_load,store,no_delay_store")
1138  (set_attr "mode"	"QI")
1139  (set_attr "length"	"4,4,8,4,8,4,8")])
1140
1141;; Block moves, see microblaze.c for more details.
1142;; Argument 0 is the destination
1143;; Argument 1 is the source
1144;; Argument 2 is the length
1145;; Argument 3 is the alignment
1146
1147(define_expand "movmemsi"
1148  [(parallel [(set (match_operand:BLK 0 "general_operand")
1149		   (match_operand:BLK 1 "general_operand"))
1150	      (use (match_operand:SI 2 ""))
1151	      (use (match_operand:SI 3 "const_int_operand"))])]
1152  ""
1153  {
1154    if (microblaze_expand_block_move (operands[0], operands[1],
1155				      operands[2], operands[3]))
1156        DONE;
1157    else
1158        FAIL;
1159  }
1160)
1161
1162;;Load and store reverse
1163(define_insn "movsi4_rev"
1164  [(set (match_operand:SI 0 "reg_or_mem_operand" "=r,Q")
1165        (bswap:SI (match_operand:SF 1 "reg_or_mem_operand" "Q,r")))]
1166  "TARGET_REORDER"
1167  "@
1168   lwr\t%0,%y1,r0
1169   swr\t%1,%y0,r0"
1170  [(set_attr "type"     "load,store")
1171  (set_attr "mode"      "SI")
1172  (set_attr "length"    "4,4")])
1173
1174;; 32-bit floating point moves
1175
1176(define_expand "movsf"
1177  [(set (match_operand:SF 0 "nonimmediate_operand" "")
1178        (match_operand:SF 1 "general_operand" ""))]
1179  ""
1180  {
1181    if ((reload_in_progress | reload_completed) == 0
1182        && !register_operand (operands[0], SFmode)
1183        && !register_operand (operands[1], SFmode)
1184        && ( ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
1185                 && operands[1] != CONST0_RTX (SFmode))))
1186    {
1187        rtx temp = force_reg (SFmode, operands[1]);
1188        emit_move_insn (operands[0], temp);
1189        DONE;
1190    }
1191  }
1192)
1193
1194;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
1195;;
1196(define_insn "*movsf_internal"
1197  [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
1198        (match_operand:SF 1 "general_operand" "G,d,R,F,m,d,d"))]
1199  "(register_operand (operands[0], SFmode)
1200       || register_operand (operands[1], SFmode)
1201       || operands[1] == CONST0_RTX (SFmode))"
1202  "@
1203   addk\t%0,r0,r0
1204   addk\t%0,%1,r0
1205   lw%i1\t%0,%1
1206   addik\t%0,r0,%F1
1207   lw%i1\t%0,%1
1208   sw%i0\t%z1,%0
1209   swi\t%z1,%0"
1210  [(set_attr "type"     "move,no_delay_load,load,no_delay_load,no_delay_load,store,no_delay_store")
1211  (set_attr "mode"      "SF")
1212  (set_attr "length"    "4,4,4,4,4,4,4")])
1213
1214;; 64-bit floating point moves
1215(define_expand "movdf"
1216  [(set (match_operand:DF 0 "nonimmediate_operand" "")
1217        (match_operand:DF 1 "general_operand" ""))]
1218  ""
1219  {
1220    if (flag_pic == 2) {
1221      if (GET_CODE (operands[1]) == MEM
1222          && !microblaze_legitimate_address_p (DFmode, XEXP (operands[1],0), 0))
1223      {
1224        rtx ptr_reg;
1225        rtx result;
1226        ptr_reg = force_reg (Pmode, XEXP (operands[1],0));
1227        result = gen_rtx_MEM (DFmode, ptr_reg);
1228        emit_move_insn (operands[0], result);
1229        DONE;
1230      }
1231    }
1232    if ((reload_in_progress | reload_completed) == 0
1233        && !register_operand (operands[0], DFmode)
1234        && !register_operand (operands[1], DFmode)
1235        && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
1236                 && operands[1] != CONST0_RTX (DFmode))))
1237    {
1238        rtx temp = force_reg (DFmode, operands[1]);
1239        emit_move_insn (operands[0], temp);
1240        DONE;
1241    }
1242  }
1243)
1244
1245;; movdf_internal
1246;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
1247;;
1248(define_insn "*movdf_internal"
1249  [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,o")
1250        (match_operand:DF 1 "general_operand" "dG,o,F,T,d"))]
1251  ""
1252  {
1253    switch (which_alternative)
1254    {
1255      case 0:
1256	return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";
1257      case 1:
1258      case 3:
1259	if (reg_mentioned_p (operands[0], operands[1]))
1260          return "lwi\t%D0,%o1\n\tlwi\t%0,%1";
1261        else
1262	  return "lwi\t%0,%1\n\tlwi\t%D0,%o1";
1263      case 2:
1264      {
1265	return "addik\t%0,r0,%h1 \n\taddik\t%D0,r0,%j1 #Xfer Lo";
1266      }
1267      case 4:
1268	return "swi\t%1,%0\n\tswi\t%D1,%o0";
1269    }
1270    gcc_unreachable ();
1271  }
1272  [(set_attr "type"     "no_delay_move,no_delay_load,no_delay_load,no_delay_load,no_delay_store")
1273  (set_attr "mode"      "DF")
1274  (set_attr "length"    "4,8,8,16,8")])
1275
1276(define_split
1277  [(set (match_operand:DF 0 "register_operand" "")
1278        (match_operand:DF 1 "register_operand" ""))]
1279  "reload_completed
1280   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
1281   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
1282   && (REGNO (operands[0]) == (REGNO (operands[1]) + 1))"
1283  [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))
1284  (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]
1285  "")
1286
1287(define_split
1288  [(set (match_operand:DF 0 "register_operand" "")
1289        (match_operand:DF 1 "register_operand" ""))]
1290  "reload_completed
1291   && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
1292   && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
1293   && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"
1294  [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
1295  (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
1296  "")
1297
1298;;----------------------------------------------------------------
1299;; Shifts
1300;;----------------------------------------------------------------
1301
1302;;----------------------------------------------------------------
1303;; 32-bit left shifts
1304;;----------------------------------------------------------------
1305(define_expand "ashlsi3"
1306  [(set (match_operand:SI 0 "register_operand" "=&d")
1307	(ashift:SI (match_operand:SI 1 "register_operand" "d")
1308		   (match_operand:SI 2 "arith_operand" "")))]
1309  ""
1310  {
1311    /* Avoid recursion for trivial cases. */
1312    if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1313      if (microblaze_expand_shift (operands))
1314        DONE;
1315  }
1316)
1317
1318;; Irrespective of if we have a barrel-shifter or not, we want to match
1319;; shifts by 1 with a special pattern. When a barrel shifter is present,
1320;; saves a cycle. If not, allows us to annotate the instruction for delay
1321;; slot optimization
1322(define_insn "*ashlsi3_byone"
1323  [(set (match_operand:SI 0 "register_operand" "=d")
1324	(ashift:SI (match_operand:SI 1 "register_operand" "d")
1325                   (match_operand:SI 2 "arith_operand"    "I")))]
1326  "(operands[2] == const1_rtx)"
1327  "addk\t%0,%1,%1"
1328  [(set_attr "type"	"arith")
1329   (set_attr "mode"	"SI")
1330   (set_attr "length"	"4")]
1331)
1332
1333;; Barrel shift left
1334(define_insn "ashlsi3_bshift"
1335  [(set (match_operand:SI 0 "register_operand" "=d,d")
1336	(ashift:SI (match_operand:SI 1 "register_operand" "d,d")
1337                   (match_operand:SI 2 "arith_operand"    "I,d")))]
1338  "TARGET_BARREL_SHIFT"
1339  "@
1340  bslli\t%0,%1,%2
1341  bsll\t%0,%1,%2"
1342  [(set_attr "type"	"bshift,bshift")
1343  (set_attr "mode"	"SI,SI")
1344  (set_attr "length"	"4,4")]
1345)
1346
1347;; The following patterns apply when there is no barrel shifter present
1348
1349(define_insn "*ashlsi3_with_mul_delay"
1350  [(set (match_operand:SI 0 "register_operand" "=d")
1351	(ashift:SI (match_operand:SI 1 "register_operand"  "d")
1352                   (match_operand:SI 2 "immediate_operand" "I")))]
1353  "!TARGET_SOFT_MUL
1354   && ((1 << INTVAL (operands[2])) <= 32767 && (1 << INTVAL (operands[2])) >= -32768)"
1355  "muli\t%0,%1,%m2"
1356  ;; This MUL will not generate an imm. Can go into a delay slot.
1357  [(set_attr "type"	"arith")
1358   (set_attr "mode"	"SI")
1359   (set_attr "length"	"4")]
1360)
1361
1362(define_insn "*ashlsi3_with_mul_nodelay"
1363  [(set (match_operand:SI 0 "register_operand" "=d")
1364	(ashift:SI (match_operand:SI 1 "register_operand"  "d")
1365                   (match_operand:SI 2 "immediate_operand" "I")))]
1366  "!TARGET_SOFT_MUL"
1367  "muli\t%0,%1,%m2"
1368  ;; This MUL will generate an IMM. Cannot go into a delay slot
1369  [(set_attr "type"	"no_delay_arith")
1370   (set_attr "mode"	"SI")
1371   (set_attr "length"	"8")]
1372)
1373
1374(define_insn "*ashlsi3_with_size_opt"
1375  [(set (match_operand:SI 0 "register_operand" "=&d")
1376       (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1377                   (match_operand:SI 2 "immediate_operand" "I")))]
1378  "(INTVAL (operands[2]) > 5 && optimize_size)"
1379  {
1380    operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1381
1382    output_asm_insn ("ori\t%3,r0,%2", operands);
1383    if (REGNO (operands[0]) != REGNO (operands[1]))
1384        output_asm_insn ("addk\t%0,%1,r0", operands);
1385
1386    output_asm_insn ("addik\t%3,%3,-1", operands);
1387    output_asm_insn ("bneid\t%3,.-4", operands);
1388    return "addk\t%0,%0,%0";
1389  }
1390  [(set_attr "type"    "multi")
1391   (set_attr "mode"    "SI")
1392   (set_attr "length"  "20")]
1393)
1394
1395(define_insn "*ashlsi3_with_rotate"
1396  [(set (match_operand:SI 0 "register_operand" "=&d")
1397       (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1398                   (match_operand:SI 2 "immediate_operand" "I")))]
1399  "(INTVAL (operands[2]) > 17 && !optimize_size)"
1400  {
1401    int i, nshift;
1402
1403    nshift = INTVAL (operands[2]);
1404    operands[3] = gen_int_mode (0xFFFFFFFF << nshift, SImode);
1405
1406    /* We do one extra shift so that the first bit (carry) coming into the MSB
1407       will be masked out */
1408    output_asm_insn ("src\t%0,%1", operands);
1409    for (i = 0; i < (32 - nshift); i++)
1410       output_asm_insn ("src\t%0,%0", operands);
1411
1412    return "andi\t%0,%0,%3";
1413  }
1414  [(set_attr "type"    "multi")
1415  (set_attr "mode"     "SI")
1416  (set_attr "length"   "80")]
1417)
1418
1419(define_insn "*ashlsi_inline"
1420  [(set (match_operand:SI 0 "register_operand" "=&d")
1421       (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1422                   (match_operand:SI 2 "immediate_operand" "I")))]
1423  ""
1424  {
1425    int i;
1426    int nshift = INTVAL (operands[2]);
1427    if (REGNO (operands[0]) != REGNO (operands[1]))
1428      output_asm_insn ("addk\t%0,r0,%1", operands);
1429    output_asm_insn ("addk\t%0,%1,%1", operands);
1430    for (i = 0; i < (nshift - 2); i++)
1431      output_asm_insn ("addk\t%0,%0,%0", operands);
1432    return "addk\t%0,%0,%0";
1433  }
1434  [(set_attr "type"    "multi")
1435  (set_attr "mode"     "SI")
1436  (set_attr "length"   "124")]
1437)
1438
1439(define_insn "*ashlsi_reg"
1440  [(set (match_operand:SI 0 "register_operand" "=&d")
1441       (ashift:SI (match_operand:SI 1 "register_operand"  "d")
1442                   (match_operand:SI 2 "register_operand" "d")))]
1443  ""
1444  {
1445    operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1446    output_asm_insn ("andi\t%3,%2,31", operands);
1447    if (REGNO (operands[0]) != REGNO (operands[1]))
1448      output_asm_insn ("addk\t%0,r0,%1", operands);
1449    /* Exit the loop if zero shift. */
1450    output_asm_insn ("beqid\t%3,.+20", operands);
1451    /* Emit the loop.  */
1452    output_asm_insn ("addk\t%0,%0,r0", operands);
1453    output_asm_insn ("addik\t%3,%3,-1", operands);
1454    output_asm_insn ("bneid\t%3,.-4", operands);
1455    return "addk\t%0,%0,%0";
1456  }
1457  [(set_attr "type"    "multi")
1458  (set_attr "mode"     "SI")
1459  (set_attr "length"   "28")]
1460)
1461
1462
1463;;----------------------------------------------------------------
1464;; 32-bit right shifts
1465;;----------------------------------------------------------------
1466(define_expand "ashrsi3"
1467  [(set (match_operand:SI 0 "register_operand" "=&d")
1468	(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
1469                     (match_operand:SI 2 "arith_operand" "")))]
1470  ""
1471  {
1472    /* Avoid recursion for trivial cases. */
1473    if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1474      if (microblaze_expand_shift (operands))
1475        DONE;
1476  }
1477)
1478
1479;; Irrespective of if we have a barrel-shifter or not, we want to match
1480;; shifts by 1 with a special pattern. When a barrel shifter is present,
1481;; saves a cycle. If not, allows us to annotate the instruction for delay
1482;; slot optimization
1483(define_insn "*ashrsi3_byone"
1484  [(set (match_operand:SI 0 "register_operand" "=d")
1485	(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
1486                     (match_operand:SI 2 "arith_operand"    "I")))]
1487  "(operands[2] == const1_rtx)"
1488  "sra\t%0,%1"
1489  [(set_attr "type"	"arith")
1490   (set_attr "mode"	"SI")
1491   (set_attr "length"	"4")]
1492)
1493
1494;; Barrel shift right logical
1495(define_insn "*ashrsi3_bshift"
1496  [(set (match_operand:SI 0 "register_operand" "=d,d")
1497	(ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
1498                     (match_operand:SI 2 "arith_operand"    "I,d")))]
1499  "TARGET_BARREL_SHIFT"
1500  "@
1501  bsrai\t%0,%1,%2
1502  bsra\t%0,%1,%2"
1503  [(set_attr "type"	"bshift,bshift")
1504  (set_attr "mode"	"SI,SI")
1505  (set_attr "length"	"4,4")]
1506)
1507
1508(define_insn "*ashrsi_inline"
1509  [(set (match_operand:SI 0 "register_operand" "=&d")
1510       (ashiftrt:SI (match_operand:SI 1 "register_operand"  "d")
1511                   (match_operand:SI 2 "immediate_operand" "I")))]
1512  ""
1513  {
1514    int i;
1515    int nshift = INTVAL (operands[2]);
1516    if (REGNO (operands[0]) != REGNO (operands[1]))
1517      output_asm_insn ("addk\t%0,r0,%1", operands);
1518    output_asm_insn ("sra\t%0,%1", operands);
1519    for (i = 0; i < (nshift - 2); i++)
1520      output_asm_insn ("sra\t%0,%0", operands);
1521    return "sra\t%0,%0";
1522  }
1523  [(set_attr "type"    "multi")
1524  (set_attr "mode"     "SI")
1525  (set_attr "length"   "124")]
1526)
1527
1528(define_insn "*ashrsi_reg"
1529  [(set (match_operand:SI 0 "register_operand" "=&d")
1530       (ashiftrt:SI (match_operand:SI 1 "register_operand"  "d")
1531                   (match_operand:SI 2 "register_operand" "d")))]
1532  ""
1533  {
1534    operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1535    output_asm_insn ("andi\t%3,%2,31", operands);
1536    if (REGNO (operands[0]) != REGNO (operands[1]))
1537      output_asm_insn ("addk\t%0,r0,%1", operands);
1538    /* Exit the loop if zero shift. */
1539    output_asm_insn ("beqid\t%3,.+20", operands);
1540    /* Emit the loop.  */
1541    output_asm_insn ("addk\t%0,%0,r0", operands);
1542    output_asm_insn ("addik\t%3,%3,-1", operands);
1543    output_asm_insn ("bneid\t%3,.-4", operands);
1544    return "sra\t%0,%0";
1545  }
1546  [(set_attr "type"    "multi")
1547  (set_attr "mode"     "SI")
1548  (set_attr "length"   "28")]
1549)
1550
1551;;----------------------------------------------------------------
1552;; 32-bit right shifts (logical)
1553;;----------------------------------------------------------------
1554
1555(define_expand "lshrsi3"
1556  [(set (match_operand:SI 0 "register_operand" "=&d")
1557	(lshiftrt:SI (match_operand:SI 1 "register_operand" "d")
1558                     (match_operand:SI 2 "arith_operand" "")))]
1559  ""
1560  {
1561    /* Avoid recursion for trivial cases. */
1562    if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1563      if (microblaze_expand_shift (operands))
1564        DONE;
1565  }
1566)
1567
1568;; Irrespective of if we have a barrel-shifter or not, we want to match
1569;; shifts by 1 with a special pattern. When a barrel shifter is present,
1570;; saves a cycle. If not, allows us to annotate the instruction for delay
1571;; slot optimization
1572(define_insn "*lshrsi3_byone"
1573  [(set (match_operand:SI 0 "register_operand" "=d")
1574	(lshiftrt:SI (match_operand:SI 1 "register_operand" "d")
1575                     (match_operand:SI 2 "arith_operand"    "I")))]
1576  "(operands[2] == const1_rtx)"
1577  "srl\t%0,%1"
1578  [(set_attr "type"	"arith")
1579   (set_attr "mode"	"SI")
1580   (set_attr "length"	"4")]
1581)
1582
1583;; Barrel shift right logical
1584(define_insn "*lshrsi3_bshift"
1585  [(set (match_operand:SI 0 "register_operand" "=d,d")
1586	(lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
1587                     (match_operand:SI 2 "arith_operand"    "I,d")))]
1588  "TARGET_BARREL_SHIFT"
1589  "@
1590  bsrli\t%0,%1,%2
1591  bsrl\t%0,%1,%2"
1592  [(set_attr "type"	"bshift,bshift")
1593  (set_attr "mode"	"SI,SI")
1594  (set_attr "length"	"4,4")]
1595)
1596
1597(define_insn "*lshrsi_inline"
1598  [(set (match_operand:SI 0 "register_operand" "=&d")
1599       (lshiftrt:SI (match_operand:SI 1 "register_operand"  "d")
1600                   (match_operand:SI 2 "immediate_operand" "I")))]
1601  ""
1602  {
1603    int i;
1604    int nshift = INTVAL (operands[2]);
1605    if (REGNO (operands[0]) != REGNO (operands[1]))
1606      output_asm_insn ("addk\t%0,r0,%1", operands);
1607    output_asm_insn ("srl\t%0,%1", operands);
1608    for (i = 0; i < (nshift - 2); i++)
1609      output_asm_insn ("srl\t%0,%0", operands);
1610    return "srl\t%0,%0";
1611  }
1612  [(set_attr "type"    "multi")
1613  (set_attr "mode"     "SI")
1614  (set_attr "length"   "124")]
1615)
1616
1617(define_insn "*lshrsi_reg"
1618  [(set (match_operand:SI 0 "register_operand" "=&d")
1619       (lshiftrt:SI (match_operand:SI 1 "register_operand"  "d")
1620                   (match_operand:SI 2 "register_operand" "d")))]
1621  ""
1622  {
1623    operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1624    output_asm_insn ("andi\t%3,%2,31", operands);
1625    if (REGNO (operands[0]) != REGNO (operands[1]))
1626      output_asm_insn ("addk\t%0,r0,%1", operands);
1627    /* Exit the loop if zero shift. */
1628    output_asm_insn ("beqid\t%3,.+20", operands);
1629    /* Emit the loop.  */
1630    output_asm_insn ("addk\t%0,%0,r0", operands);
1631    output_asm_insn ("addik\t%3,%3,-1", operands);
1632    output_asm_insn ("bneid\t%3,.-4", operands);
1633    return "srl\t%0,%0";
1634  }
1635  [(set_attr "type"    "multi")
1636  (set_attr "mode"     "SI")
1637  (set_attr "length"   "28")]
1638)
1639
1640;;----------------------------------------------------------------
1641;; Setting a register from an integer comparison.
1642;;----------------------------------------------------------------
1643(define_expand "cstoresi4"
1644   [(set (match_operand:SI 0 "register_operand")
1645        (match_operator:SI 1 "ordered_comparison_operator"
1646	      [(match_operand:SI 2 "register_operand")
1647	       (match_operand:SI 3 "register_operand")]))]
1648  "TARGET_PATTERN_COMPARE"
1649  "if (GET_CODE (operand1) != EQ && GET_CODE (operand1) != NE)
1650     FAIL;
1651  "
1652)
1653
1654(define_insn "seq_internal_pat"
1655  [(set (match_operand:SI 0 "register_operand" "=d")
1656	(eq:SI
1657	       (match_operand:SI 1 "register_operand" "d")
1658	       (match_operand:SI 2 "register_operand" "d")))]
1659  "TARGET_PATTERN_COMPARE"
1660  "pcmpeq\t%0,%1,%2"
1661  [(set_attr "type"	"arith")
1662   (set_attr "mode"	"SI")
1663   (set_attr "length"	"4")]
1664)
1665
1666(define_insn "sne_internal_pat"
1667  [(set (match_operand:SI 0 "register_operand" "=d")
1668	(ne:SI
1669	       (match_operand:SI 1 "register_operand" "d")
1670	       (match_operand:SI 2 "register_operand" "d")))]
1671  "TARGET_PATTERN_COMPARE"
1672  "pcmpne\t%0,%1,%2"
1673  [(set_attr "type"	"arith")
1674  (set_attr "mode"	"SI")
1675  (set_attr "length"	"4")]
1676)
1677
1678;;----------------------------------------------------------------
1679;; Setting a register from an floating point comparison.
1680;;----------------------------------------------------------------
1681(define_insn "cstoresf4"
1682   [(set (match_operand:SI 0 "register_operand" "=r")
1683        (match_operator:SI 1 "ordered_comparison_operator"
1684	      [(match_operand:SF 2 "register_operand" "r")
1685	       (match_operand:SF 3 "register_operand" "r")]))]
1686  "TARGET_HARD_FLOAT"
1687  "fcmp.%C1\t%0,%3,%2"
1688  [(set_attr "type"     "fcmp")
1689   (set_attr "mode"      "SF")
1690   (set_attr "length"    "4")]
1691)
1692
1693;;----------------------------------------------------------------
1694;; Conditional branches
1695;;----------------------------------------------------------------
1696
1697(define_expand "cbranchsi4"
1698  [(set (pc)
1699        (if_then_else (match_operator 0 "ordered_comparison_operator"
1700                       [(match_operand:SI 1 "register_operand")
1701                        (match_operand:SI 2 "arith_operand" "I,i")])
1702                      (label_ref (match_operand 3 ""))
1703                      (pc)))]
1704  ""
1705{
1706  microblaze_expand_conditional_branch (SImode, operands);
1707  DONE;
1708})
1709
1710(define_expand "cbranchsi4_reg"
1711  [(set (pc)
1712        (if_then_else (match_operator 0 "ordered_comparison_operator"
1713                       [(match_operand:SI 1 "register_operand")
1714                        (match_operand:SI 2 "register_operand")])
1715                      (label_ref (match_operand 3 ""))
1716                      (pc)))]
1717  ""
1718{
1719  microblaze_expand_conditional_branch_reg (SImode, operands);
1720  DONE;
1721})
1722
1723(define_expand "cbranchsf4"
1724  [(set (pc)
1725	(if_then_else (match_operator 0 "ordered_comparison_operator"
1726		       [(match_operand:SF 1 "register_operand")
1727		        (match_operand:SF 2 "register_operand")])
1728		      (label_ref (match_operand 3 ""))
1729		      (pc)))]
1730  "TARGET_HARD_FLOAT"
1731{
1732  microblaze_expand_conditional_branch_sf (operands);
1733  DONE;
1734
1735})
1736
1737;; Used to implement comparison instructions
1738(define_expand "condjump"
1739  [(set (pc)
1740	(if_then_else (match_operand 0)
1741		      (label_ref (match_operand 1))
1742		      (pc)))])
1743
1744(define_insn "branch_zero"
1745  [(set (pc)
1746	(if_then_else (match_operator:SI 0 "ordered_comparison_operator"
1747  				 [(match_operand:SI 1 "register_operand" "d")
1748                                  (const_int 0)])
1749                      (match_operand:SI 2 "pc_or_label_operand" "")
1750                      (match_operand:SI 3 "pc_or_label_operand" "")))
1751  ]
1752  ""
1753  {
1754    if (operands[3] == pc_rtx)
1755      return "b%C0i%?\t%z1,%2";
1756    else
1757      return "b%N0i%?\t%z1,%3";
1758  }
1759  [(set_attr "type"	"branch")
1760   (set_attr "mode"	"none")
1761   (set_attr "length"	"4")]
1762)
1763
1764(define_insn "branch_compare"
1765  [(set (pc)
1766        (if_then_else (match_operator:SI 0 "cmp_op"
1767                                         [(match_operand:SI 1 "register_operand" "d")
1768                                          (match_operand:SI 2 "register_operand" "d")
1769                                         ])
1770                      (label_ref (match_operand 3))
1771                      (pc)))
1772  (clobber(reg:SI R_TMP))]
1773  ""
1774  {
1775    operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1776    enum rtx_code code = GET_CODE (operands[0]);
1777
1778    if (code == GT || code == LE)
1779      {
1780        output_asm_insn ("cmp\tr18,%z1,%z2", operands);
1781        code = swap_condition (code);
1782      }
1783    else if (code == GTU || code == LEU)
1784      {
1785        output_asm_insn ("cmpu\tr18,%z1,%z2", operands);
1786        code = swap_condition (code);
1787      }
1788    else if (code == GE || code == LT)
1789      {
1790        output_asm_insn ("cmp\tr18,%z2,%z1", operands);
1791      }
1792    else if (code == GEU || code == LTU)
1793      {
1794        output_asm_insn ("cmpu\tr18,%z2,%z1", operands);
1795      }
1796
1797    operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx);
1798    return "b%C0i%?\tr18,%3";
1799  }
1800  [(set_attr "type"     "branch")
1801   (set_attr "mode"     "none")
1802   (set_attr "length"   "12")]
1803)
1804
1805;;----------------------------------------------------------------
1806;; Unconditional branches
1807;;----------------------------------------------------------------
1808(define_insn "jump"
1809  [(set (pc)
1810	(label_ref (match_operand 0 "" "")))]
1811  ""
1812  {
1813    if (GET_CODE (operands[0]) == REG)
1814        return "br%?\t%0";
1815    else
1816        return "bri%?\t%l0";
1817  }
1818  [(set_attr "type"	"jump")
1819  (set_attr "mode"	"none")
1820  (set_attr "length"	"4")])
1821
1822(define_expand "indirect_jump"
1823  [(set (pc) (match_operand 0 "register_operand" "d"))]
1824  ""
1825  {
1826    rtx dest = operands[0];
1827    if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode)
1828      operands[0] = copy_to_mode_reg (Pmode, dest);
1829
1830    emit_jump_insn (gen_indirect_jump_internal1 (operands[0]));
1831    DONE;
1832  }
1833)
1834
1835;; Indirect jumps. Jump to register values. Assuming absolute jumps
1836
1837(define_insn "indirect_jump_internal1"
1838  [(set (pc) (match_operand:SI 0 "register_operand" "d"))]
1839  ""
1840  "bra%?\t%0"
1841  [(set_attr "type"	"jump")
1842  (set_attr "mode"	"none")
1843  (set_attr "length"	"4")])
1844
1845(define_expand "tablejump"
1846  [(set (pc)
1847	(match_operand 0 "register_operand" "d"))
1848  (use (label_ref (match_operand 1 "" "")))]
1849  ""
1850  {
1851    gcc_assert (GET_MODE (operands[0]) == Pmode);
1852
1853    if (!flag_pic || TARGET_PIC_DATA_TEXT_REL)
1854      emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1]));
1855    else
1856      emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1]));
1857    DONE;
1858  }
1859)
1860
1861(define_insn "tablejump_internal1"
1862  [(set (pc)
1863	(match_operand:SI 0 "register_operand" "d"))
1864  (use (label_ref (match_operand 1 "" "")))]
1865  ""
1866  "bra%?\t%0 "
1867  [(set_attr "type"	"jump")
1868  (set_attr "mode"	"none")
1869  (set_attr "length"	"4")])
1870
1871(define_expand "tablejump_internal3"
1872  [(parallel [(set (pc)
1873		   (plus:SI (match_operand:SI 0 "register_operand" "d")
1874			    (label_ref:SI (match_operand:SI 1 "" ""))))
1875             (use (label_ref:SI (match_dup 1)))])]
1876  ""
1877  ""
1878)
1879
1880;; need to change for MicroBlaze PIC
1881(define_insn ""
1882 [(set (pc)
1883	(plus:SI (match_operand:SI 0 "register_operand" "d")
1884		 (label_ref:SI (match_operand 1 "" ""))))
1885  (use (label_ref:SI (match_dup 1)))]
1886 "NEXT_INSN (as_a <rtx_insn *> (operands[1])) != 0
1887  && GET_CODE (PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[1])))) == ADDR_DIFF_VEC
1888  && flag_pic"
1889  {
1890    output_asm_insn ("addk\t%0,%0,r20",operands);
1891    return "bra%?\t%0";
1892}
1893 [(set_attr "type"	"jump")
1894  (set_attr "mode"	"none")
1895  (set_attr "length"	"4")])
1896
1897(define_expand "tablejump_internal4"
1898  [(parallel [(set (pc)
1899		   (plus:DI (match_operand:DI 0 "register_operand" "d")
1900			    (label_ref:DI (match_operand:SI 1 "" ""))))
1901             (use (label_ref:DI (match_dup 1)))])]
1902  ""
1903  ""
1904)
1905
1906;;----------------------------------------------------------------
1907;; Function prologue/epilogue and stack allocation
1908;;----------------------------------------------------------------
1909(define_expand "prologue"
1910  [(const_int 1)]
1911  ""
1912  {
1913      microblaze_expand_prologue ();
1914      DONE;
1915  }
1916)
1917
1918(define_expand "epilogue"
1919  [(use (const_int 0))]
1920  ""
1921  {
1922      microblaze_expand_epilogue ();
1923      DONE;
1924  }
1925)
1926
1927;; An insn to allocate new stack space for dynamic use (e.g., alloca).
1928;; We copy the return address, decrement the stack pointer and save the
1929;; return address again at the new stack top
1930
1931(define_expand "allocate_stack"
1932  [(set (match_operand 0 "register_operand" "=r")
1933	(minus (reg 1) (match_operand 1 "register_operand" "")))
1934   (set (reg 1)
1935	(minus (reg 1) (match_dup 1)))]
1936  ""
1937  {
1938    rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
1939    rtx rtmp    = gen_rtx_REG (SImode, R_TMP);
1940    rtx neg_op0;
1941
1942    emit_move_insn (rtmp, retaddr);
1943    if (GET_CODE (operands[1]) != CONST_INT)
1944    {
1945        neg_op0 = gen_reg_rtx (Pmode);
1946	emit_insn (gen_negsi2 (neg_op0, operands[1]));
1947    } else
1948        neg_op0 = GEN_INT (- INTVAL (operands[1]));
1949
1950    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, neg_op0));
1951    emit_move_insn (gen_rtx_MEM (Pmode, stack_pointer_rtx), rtmp);
1952    emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
1953    emit_insn (gen_rtx_CLOBBER (SImode, rtmp));
1954    DONE;
1955  }
1956)
1957
1958(define_expand "save_stack_block"
1959  [(match_operand 0 "register_operand" "")
1960   (match_operand 1 "register_operand" "")]
1961  ""
1962  {
1963    emit_move_insn (operands[0], operands[1]);
1964    DONE;
1965  }
1966)
1967
1968(define_expand "restore_stack_block"
1969  [(match_operand 0 "register_operand" "")
1970   (match_operand 1 "register_operand" "")]
1971  ""
1972  {
1973    rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
1974    rtx rtmp    = gen_rtx_REG (SImode, R_TMP);
1975
1976    /* Move the retaddr.  */
1977    emit_move_insn (rtmp, retaddr);
1978    emit_move_insn (operands[0], operands[1]);
1979    emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), rtmp);
1980    DONE;
1981  }
1982)
1983
1984;; Trivial return.  Make it look like a normal return insn as that
1985;; allows jump optimizations to work better .
1986(define_expand "return"
1987  [(simple_return)]
1988  "microblaze_can_use_return_insn ()"
1989  {}
1990)
1991
1992(define_expand "simple_return"
1993  [(simple_return)]
1994  ""
1995  {}
1996)
1997
1998(define_insn "*<optab>"
1999  [(any_return)]
2000  ""
2001  {
2002    if (microblaze_is_break_handler ())
2003        return "rtbd\tr16, 8\;%#";
2004    else if (microblaze_is_interrupt_variant ())
2005        return "rtid\tr14, 0\;%#";
2006    else
2007        return "rtsd\tr15, 8\;%#";
2008  }
2009  [(set_attr "type"	"jump")
2010  (set_attr "mode"	"none")
2011  (set_attr "length"	"4")]
2012)
2013
2014;; Normal return.
2015
2016(define_insn "<optab>_internal"
2017  [(any_return)
2018   (use (match_operand:SI 0 "register_operand" ""))]
2019  ""
2020  {
2021    if (microblaze_is_break_handler ())
2022        return "rtbd\tr16,8\;%#";
2023    else if (microblaze_is_interrupt_variant ())
2024        return "rtid\tr14,0 \;%#";
2025    else
2026        return "rtsd\tr15,8 \;%#";
2027  }
2028  [(set_attr "type"	"jump")
2029  (set_attr "mode"	"none")
2030  (set_attr "length"	"4")])
2031
2032
2033;; Block any insns from across this point
2034;; Useful to group sequences together.
2035(define_insn "blockage"
2036  [(unspec_volatile [(const_int 0)] 0)]
2037  ""
2038  ""
2039  [(set_attr "type"	"unknown")
2040  (set_attr "mode"	"none")
2041  (set_attr "length"	"0")])
2042
2043
2044;;----------------------------------------------------------------
2045;; Function calls
2046;;----------------------------------------------------------------
2047
2048(define_expand "call"
2049  [(parallel [(call (match_operand 0 "memory_operand" "m")
2050		    (match_operand 1 "" "i"))
2051             (clobber (reg:SI R_SR))
2052             (use (match_operand 2 "" ""))
2053             (use (match_operand 3 "" ""))])]
2054  ""
2055  {
2056    rtx addr = XEXP (operands[0], 0);
2057
2058    if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL
2059    && GET_CODE (addr) == SYMBOL_REF
2060	&& !SYMBOL_REF_LOCAL_P (addr))
2061      {
2062        rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
2063        XEXP (operands[0], 0) = temp;
2064      }
2065
2066    if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
2067	|| !call_insn_operand (addr, VOIDmode))
2068      XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr);
2069
2070    if (GET_CODE (XEXP (operands[0], 0)) == UNSPEC)
2071      emit_call_insn (gen_call_internal_plt0 (operands[0], operands[1],
2072                        gen_rtx_REG (SImode,
2073				     GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
2074                               	     pic_offset_table_rtx));
2075    else
2076      emit_call_insn (gen_call_internal0 (operands[0], operands[1],
2077                        gen_rtx_REG (SImode,
2078				     GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2079
2080        DONE;
2081  }
2082)
2083
2084(define_expand "call_internal0"
2085  [(parallel [(call (match_operand 0 "" "")
2086		    (match_operand 1 "" ""))
2087             (clobber (match_operand:SI 2 "" ""))])]
2088  ""
2089  {
2090  }
2091)
2092
2093(define_expand "call_internal_plt0"
2094  [(parallel [(call (match_operand 0 "" "")
2095		    (match_operand 1 "" ""))
2096             (clobber (match_operand:SI 2 "" ""))
2097             (use (match_operand:SI 3 "" ""))])]
2098  ""
2099  {
2100  }
2101)
2102
2103(define_insn "call_internal_plt"
2104  [(call (mem (match_operand:SI 0 "call_insn_plt_operand" ""))
2105	 (match_operand:SI 1 "" "i"))
2106  (clobber (reg:SI R_SR))
2107  (use (reg:SI R_GOT))]
2108  "flag_pic"
2109  {
2110    register rtx target2 = gen_rtx_REG (Pmode,
2111			      GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2112    gen_rtx_CLOBBER (VOIDmode, target2);
2113    return "brlid\tr15,%0\;%#";
2114  }
2115  [(set_attr "type"	"call")
2116  (set_attr "mode"	"none")
2117  (set_attr "length"	"4")])
2118
2119(define_insn "call_internal1"
2120  [(call (mem (match_operand:VOID 0 "call_insn_simple_operand" "ri"))
2121	 (match_operand:SI 1 "" "i"))
2122  (clobber (reg:SI R_SR))]
2123  ""
2124  {
2125    register rtx target = operands[0];
2126    register rtx target2 = gen_rtx_REG (Pmode,
2127			      GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2128    if (GET_CODE (target) == SYMBOL_REF) {
2129        if (microblaze_break_function_p (SYMBOL_REF_DECL (target))) {
2130            gen_rtx_CLOBBER (VOIDmode, target2);
2131            return "brki\tr16,%0\;%#";
2132        }
2133        else {
2134            gen_rtx_CLOBBER (VOIDmode, target2);
2135            return "brlid\tr15,%0\;%#";
2136        }
2137    } else if (GET_CODE (target) == CONST_INT)
2138        return "la\t%@,r0,%0\;brald\tr15,%@\;%#";
2139    else if (GET_CODE (target) == REG)
2140        return "brald\tr15,%0\;%#";
2141    else {
2142        fprintf (stderr,"Unsupported call insn\n");
2143        return NULL;
2144    }
2145  }
2146  [(set_attr "type"	"call")
2147  (set_attr "mode"	"none")
2148  (set_attr "length"	"4")])
2149
2150;; calls.c now passes a fourth argument, make saber happy
2151
2152(define_expand "call_value"
2153  [(parallel [(set (match_operand 0 "register_operand" "=d")
2154		   (call (match_operand 1 "memory_operand" "m")
2155			 (match_operand 2 "" "i")))
2156             (clobber (reg:SI R_SR))
2157             (use (match_operand 3 "" ""))])] ;; next_arg_reg
2158  ""
2159  {
2160    rtx addr = XEXP (operands[1], 0);
2161
2162    if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL
2163    && GET_CODE (addr) == SYMBOL_REF
2164	&& !SYMBOL_REF_LOCAL_P (addr))
2165      {
2166        rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
2167        XEXP (operands[1], 0) = temp;
2168      }
2169
2170    if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
2171        || !call_insn_operand (addr, VOIDmode))
2172      XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);
2173
2174    if (GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
2175      emit_call_insn (gen_call_value_intern_plt0 (operands[0], operands[1],
2176			operands[2],
2177                        gen_rtx_REG (SImode,
2178				     GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
2179				     pic_offset_table_rtx));
2180    else
2181      emit_call_insn (gen_call_value_internal (operands[0], operands[1],
2182			operands[2],
2183                        gen_rtx_REG (SImode,
2184				     GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2185
2186    DONE;
2187  }
2188)
2189
2190
2191(define_expand "call_value_internal"
2192  [(parallel [(set (match_operand 0 "" "")
2193		   (call (match_operand 1 "" "")
2194			 (match_operand 2 "" "")))
2195             (clobber (match_operand:SI 3 "" ""))
2196             ])]
2197  ""
2198  {}
2199)
2200
2201(define_expand "call_value_intern_plt0"
2202  [(parallel[(set (match_operand 0 "" "")
2203                  (call (match_operand 1 "" "")
2204                        (match_operand 2 "" "")))
2205             (clobber (match_operand:SI 3 "" ""))
2206             (use (match_operand:SI 4 "" ""))])]
2207  "flag_pic"
2208  {}
2209)
2210
2211(define_insn "call_value_intern_plt"
2212  [(set (match_operand:VOID 0 "register_operand" "=d")
2213        (call (mem (match_operand:SI 1 "call_insn_plt_operand" ""))
2214              (match_operand:SI 2 "" "i")))
2215   (clobber (match_operand:SI 3 "register_operand" "=d"))
2216   (use (match_operand:SI 4 "register_operand"))]
2217  "flag_pic"
2218  {
2219    register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2220
2221    gen_rtx_CLOBBER (VOIDmode,target2);
2222    return "brlid\tr15,%1\;%#";
2223  }
2224  [(set_attr "type"	"call")
2225  (set_attr "mode"	"none")
2226  (set_attr "length"	"4")])
2227
2228(define_insn "call_value_intern"
2229  [(set (match_operand:VOID 0 "register_operand" "=d")
2230        (call (mem (match_operand:VOID 1 "call_insn_operand" "ri"))
2231              (match_operand:SI 2 "" "i")))
2232   (clobber (match_operand:SI 3 "register_operand" "=d"))]
2233  ""
2234  {
2235    register rtx target = operands[1];
2236    register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2237
2238    if (GET_CODE (target) == SYMBOL_REF)
2239    {
2240      gen_rtx_CLOBBER (VOIDmode,target2);
2241      if (microblaze_break_function_p (SYMBOL_REF_DECL (target)))
2242        return "brki\tr16,%1\;%#";
2243      else if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION)
2244        {
2245	  return "brlid\tr15,%1\;%#";
2246        }
2247      else
2248        {
2249	    return "bralid\tr15,%1\;%#";
2250        }
2251    }
2252    else if (GET_CODE (target) == CONST_INT)
2253        return "la\t%@,r0,%1\;brald\tr15,%@\;%#";
2254    else if (GET_CODE (target) == REG)
2255        return "brald\tr15,%1\;%#";
2256    else
2257        return "Unsupported call insn\n";
2258  }
2259  [(set_attr "type"	"call")
2260  (set_attr "mode"	"none")
2261  (set_attr "length"	"4")])
2262
2263
2264;; Call subroutine returning any type.
2265(define_expand "untyped_call"
2266  [(parallel [(call (match_operand 0 "" "")
2267		    (const_int 0))
2268             (match_operand 1 "" "")
2269             (match_operand 2 "" "")])]
2270  ""
2271  {
2272    if (operands[0])		/* silence statement not reached warnings */
2273    {
2274        int i;
2275
2276        emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2277
2278        for (i = 0; i < XVECLEN (operands[2], 0); i++)
2279	{
2280	    rtx set = XVECEXP (operands[2], 0, i);
2281	    emit_move_insn (SET_DEST (set), SET_SRC (set));
2282	}
2283
2284        emit_insn (gen_blockage ());
2285        DONE;
2286      }
2287  }
2288)
2289
2290;;----------------------------------------------------------------
2291;; Misc.
2292;;----------------------------------------------------------------
2293
2294(define_insn "nop"
2295  [(const_int 0)]
2296  ""
2297  "nop"
2298  [(set_attr "type"	"nop")
2299  (set_attr "mode"	"none")
2300  (set_attr "length"	"4")])
2301
2302;; Trap instruction pattern for __builtin_trap. Same as the glibc ABORT_INSTRUCTION
2303(define_insn "trap"
2304  [(trap_if (const_int 1) (const_int 0))]
2305  ""
2306  "brki\tr0,-1"
2307 [(set_attr "type" "trap")]
2308)
2309
2310;; The insn to set GOT. The hardcoded number "8" accounts for $pc difference
2311;; between "mfs" and "addik" instructions.
2312(define_insn "set_got"
2313  [(set (match_operand:SI 0 "register_operand" "=r")
2314    (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))]
2315  ""
2316  "mfs\t%0,rpc\n\taddik\t%0,%0,_GLOBAL_OFFSET_TABLE_+8"
2317  [(set_attr "type" "multi")
2318   (set_attr "length" "12")])
2319
2320;; The insn to set TEXT.
2321;; The hardcoded number "8" accounts for $pc difference
2322;; between "mfs" and "addik" instructions.
2323(define_insn "set_text"
2324  [(set (match_operand:SI 0 "register_operand" "=r")
2325    (unspec:SI[(const_int 0)] UNSPEC_SET_TEXT))]
2326  ""
2327  "mfs\t%0,rpc\n\taddik\t%0,%0,8@TXTPCREL"
2328  [(set_attr "type" "multi")
2329   (set_attr "length" "12")])
2330
2331
2332;; This insn gives the count of leading number of zeros for the second
2333;; operand and stores the result in first operand.
2334(define_insn "clzsi2"
2335  [(set (match_operand:SI 0 "register_operand" "=r")
2336        (clz:SI (match_operand:SI 1 "register_operand" "r")))]
2337  "TARGET_HAS_CLZ"
2338  "clz\t%0,%1"
2339  [(set_attr "type"     "arith")
2340  (set_attr "mode"      "SI")
2341  (set_attr "length"    "4")])
2342
2343; This is used in compiling the unwind routines.
2344(define_expand "eh_return"
2345  [(use (match_operand 0 "general_operand" ""))]
2346  ""
2347  "
2348{
2349  microblaze_eh_return (operands[0]);
2350  DONE;
2351}")
2352
2353(include "sync.md")
2354