Fix version check for ATTRIBUTE_GCC_DUMP_PRINTF
[official-gcc.git] / gcc / config / microblaze / microblaze.md
blobbec346f60ff60e780f00f19f370e7ebd43266f38
1 ;; microblaze.md -- Machine description for Xilinx MicroBlaze processors.
2 ;; Copyright (C) 2009-2018 Free Software Foundation, Inc.
4 ;; Contributed by Michael Eager <eager@eagercon.com>.
6 ;; This file is part of GCC.
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.
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.
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/>.  */
22 (include "constraints.md")
23 (include "predicates.md")
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
48 (define_c_enum "unspec" [
49   UNSPEC_IPREFETCH
52 ;;----------------------------------------------------
53 ;; Instruction Attributes
54 ;;----------------------------------------------------
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
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"))
85 ;; Main data type used by the insn
86 (define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown"))
88 ;; # instructions (4 bytes each)
89 (define_attr "length" "" (const_int 4))
91 (define_code_iterator any_return [return simple_return])
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")])
98 ;;----------------------------------------------------
99 ;; Attribute describing the processor.  
100 ;;----------------------------------------------------
102 ;; Describe a user's asm statement.
103 (define_asm_attributes
104   [(set_attr "type" "multi")])
106 ;; whether or not generating calls to position independent functions
107 (define_attr "abicalls" "no,yes"
108   (const (symbol_ref "microblaze_abicalls_attr")))
110 ;;----------------------------------------------------------------
111 ;; Microblaze DFA Pipeline description
112 ;;----------------------------------------------------------------
113                   
114 ;;-----------------------------------------------------------------
116    This is description of pipeline hazards based on DFA.  The
117    following constructions can be used for this:
119    o define_cpu_unit string [string]) describes a cpu functional unit
120      (separated by comma).
122      1st operand: Names of cpu function units.
123      2nd operand: Name of automaton (see comments for
124      DEFINE_AUTOMATON).
126      All define_reservations and define_cpu_units should have unique
127      names which can not be "nothing".
129    o (exclusion_set string string) means that each CPU function unit
130      in the first string can not 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.
137    o (presence_set string string) means that each CPU function unit in
138      the first string can not 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.
144    o (absence_set string string) means that each CPU function unit in
145      the first string can not 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 can not be
150      reserved after slot1 or slot2 reservation for a VLIW processor.
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.
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.
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 can not be "nothing".
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:
181        regexp = regexp "," oneof
182               | oneof
184        oneof = oneof "|" allof
185              | allof
187        allof = allof "+" repeat
188              | repeat
190        repeat = element "*" number
191               | element
193        element = cpu_function_name
194                | reservation_name
195                | result_name
196                | "nothing"
197                | "(" regexp ")"
199        1. "," is used for describing start of the next cycle in
200           reservation.
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.
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.
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 ",").
214        5. cpu function unit name which means reservation.
216        6. reservation name -- see define_reservation.
218        7. string "nothing" means no units reservation.
221 ;;-----------------------------------------------------------------
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
291 ;;----------------------------------------------------------------
292 ;; Microblaze 3-stage pipeline description (for v4.00.a and earlier)
293 ;;----------------------------------------------------------------
295 (define_automaton   "mbpipe_3")
296 (define_cpu_unit    "mb3_iu" "mbpipe_3")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
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")
358 (automata_option "v")
359 (automata_option "time")
360 (automata_option "progress")
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"
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"
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)])
388 ;;----------------------------------------------------------------
389 ;; Microblaze FPU
390 ;;----------------------------------------------------------------
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")])
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")])
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")])
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")])
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")])
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")])
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")])
460 ;;----------------------------------------------------------------
461 ;; Add
462 ;;----------------------------------------------------------------
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")])
479 ;;----------------------------------------------------------------
480 ;; Double Precision Additions
481 ;;----------------------------------------------------------------
483 ;; reg_DI_dest = reg_DI_src1 + DI_src2
485 ;; Adding 2 DI operands in register or reg/imm
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")])
500 ;;----------------------------------------------------------------
501 ;; Subtraction
502 ;;----------------------------------------------------------------
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")])
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")])
528 ;;----------------------------------------------------------------
529 ;; Double Precision Subtraction
530 ;;----------------------------------------------------------------
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")])
543 ;;----------------------------------------------------------------
544 ;; Multiplication
545 ;;----------------------------------------------------------------
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")])
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")])
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")])
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")])
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")])
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"))
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")])
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"))
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")])
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   }     
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")]
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")])
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))]
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);
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   }
708 ;;----------------------------------------------------------------
709 ;; Negation and one's complement
710 ;;----------------------------------------------------------------
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")])
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")])
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")])
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")]
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]))"
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   "")
762 ;;----------------------------------------------------------------
763 ;; Logical
764 ;;----------------------------------------------------------------
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")])
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")])
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")])
808 ;;----------------------------------------------------------------
809 ;; Zero extension
810 ;;----------------------------------------------------------------
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")])
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")])
848 ;;----------------------------------------------------------------
849 ;; Sign extension
850 ;;----------------------------------------------------------------
852 ;; basic Sign Extend Operations
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")])
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")])
872 ;; Those for integer source operand are ordered
873 ;; widest source type first.
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);
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")])
894 ;;----------------------------------------------------------------
895 ;; Data movement
896 ;;----------------------------------------------------------------
898 ;; 64-bit integer moves
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.
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     }
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     {
927       rtx temp = force_reg (DImode, operands[1]);
928       emit_move_insn (operands[0], temp);
929       DONE;
930     }
931   }
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")])
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))"
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   "")
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))"
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   "")
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.
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   }
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")])
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")])
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")])
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")])
1060 ;; 16-bit Integer moves
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
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   }
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")])
1100 ;; 8-bit Integer moves
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
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   }
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")])
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
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   }
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")])
1174 ;; 32-bit floating point moves
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   }
1194 ;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
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")])
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   }
1245 ;; movdf_internal
1246 ;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
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")])
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   "")
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   "")
1298 ;;----------------------------------------------------------------
1299 ;; Shifts
1300 ;;----------------------------------------------------------------
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   }
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")]
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")]
1347 ;; The following patterns apply when there is no barrel shifter present
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")]
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")]
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);
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);
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")]
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);
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);
1412     return "andi\t%0,%0,%3";
1413   }
1414   [(set_attr "type"    "multi")
1415   (set_attr "mode"     "SI")
1416   (set_attr "length"   "80")]
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")]
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")]
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   }
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")]
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")]
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")]
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")]
1551 ;;----------------------------------------------------------------
1552 ;; 32-bit right shifts (logical)
1553 ;;----------------------------------------------------------------
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   }
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")]
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")]
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")]
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")]
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   "
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 )              
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 )              
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")]
1693 ;;----------------------------------------------------------------
1694 ;; Conditional branches
1695 ;;----------------------------------------------------------------
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   ""
1706   microblaze_expand_conditional_branch (SImode, operands);
1707   DONE;
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   ""
1719   microblaze_expand_conditional_branch_reg (SImode, operands);
1720   DONE;
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"
1732   microblaze_expand_conditional_branch_sf (operands);
1733   DONE;
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)))])
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")]
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]);
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       }
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")]
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")])
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);
1830     emit_jump_insn (gen_indirect_jump_internal1 (operands[0]));
1831     DONE;
1832   }
1835 ;; Indirect jumps. Jump to register values. Assuming absolute jumps
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")])
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);
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   }
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")])
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   ""
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";
1893  [(set_attr "type"      "jump")
1894   (set_attr "mode"      "none")
1895   (set_attr "length"    "4")])
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   ""
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   }
1918 (define_expand "epilogue"
1919   [(use (const_int 0))]
1920   ""
1921   {
1922       microblaze_expand_epilogue ();
1923       DONE;
1924   }
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 
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;
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]));
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   }
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   }
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);
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   }
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   {}
1992 (define_expand "simple_return"
1993   [(simple_return)]
1994   ""
1995   {}
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")]
2014 ;; Normal return.
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")])
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")])
2043   
2044 ;;----------------------------------------------------------------
2045 ;; Function calls
2046 ;;----------------------------------------------------------------
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);
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);
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)));
2080         DONE;
2081   }
2084 (define_expand "call_internal0"
2085   [(parallel [(call (match_operand 0 "" "")
2086                     (match_operand 1 "" ""))
2087              (clobber (match_operand:SI 2 "" ""))])]
2088   ""
2089   {
2090   }
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   }
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")])
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")])
2150 ;; calls.c now passes a fourth argument, make saber happy
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);
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       }
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);
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)));
2186     DONE;
2187   }
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   {}
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   {}
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);
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")])
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);
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")])
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;
2276         emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
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         }
2284         emit_insn (gen_blockage ());
2285         DONE;
2286       }
2287   }
2290 ;;----------------------------------------------------------------
2291 ;; Misc.
2292 ;;----------------------------------------------------------------
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")])
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")]
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")])
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")])
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")])
2343 ; This is used in compiling the unwind routines.
2344 (define_expand "eh_return"
2345   [(use (match_operand 0 "general_operand" ""))]
2346   ""
2347   "
2349   microblaze_eh_return (operands[0]);
2350   DONE;
2353 (include "sync.md")