1 ;; microblaze.md -- Machine description for Xilinx MicroBlaze processors.
2 ;; Copyright 2009, 2010 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)
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 ;;----------------------------------------------------
27 ;;----------------------------------------------------
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
46 ;;----------------------------------------------------
47 ;; Instruction Attributes
48 ;;----------------------------------------------------
50 ;; Classification of each insn.
51 ;; branch conditional branch
52 ;; jump unconditional jump
53 ;; call unconditional call
54 ;; load load instruction(s)
55 ;; store store instruction(s)
56 ;; move data movement within same register set
57 ;; arith integer arithmetic instruction
58 ;; darith double precision integer arithmetic instructions
59 ;; imul integer multiply
60 ;; idiv integer divide
61 ;; icmp integer compare
62 ;; Xfadd floating point add/subtract
63 ;; Xfmul floating point multiply
64 ;; Xfmadd floating point multiply-add
65 ;; Xfdiv floating point divide
66 ;; Xfabs floating point absolute value
67 ;; Xfneg floating point negation
68 ;; Xfcmp floating point compare
69 ;; Xfcvt floating point convert
70 ;; Xfsqrt floating point square root
71 ;; multi multiword sequence (or user asm statements)
73 ;; bshift Shift operations
76 "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"
77 (const_string "unknown"))
79 ;; Main data type used by the insn
80 (define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown"))
82 ;; # instructions (4 bytes each)
83 (define_attr "length" "" (const_int 4))
85 ;;----------------------------------------------------
86 ;; Attribute describing the processor.
87 ;;----------------------------------------------------
89 ;; Describe a user's asm statement.
90 (define_asm_attributes
91 [(set_attr "type" "multi")])
93 ;; whether or not generating calls to position independent functions
94 (define_attr "abicalls" "no,yes"
95 (const (symbol_ref "microblaze_abicalls_attr")))
97 ;;----------------------------------------------------------------
98 ;; Microblaze DFA Pipeline description
99 ;;----------------------------------------------------------------
101 ;;-----------------------------------------------------------------
103 This is description of pipeline hazards based on DFA. The
104 following constructions can be used for this:
106 o define_cpu_unit string [string]) describes a cpu functional unit
107 (separated by comma).
109 1st operand: Names of cpu function units.
110 2nd operand: Name of automaton (see comments for
113 All define_reservations and define_cpu_units should have unique
114 names which can not be "nothing".
116 o (exclusion_set string string) means that each CPU function unit
117 in the first string can not be reserved simultaneously with each
118 unit whose name is in the second string and vise versa. CPU
119 units in the string are separated by commas. For example, it is
120 useful for description CPU with fully pipelined floating point
121 functional unit which can execute simultaneously only single
122 floating point insns or only double floating point insns.
124 o (presence_set string string) means that each CPU function unit in
125 the first string can not be reserved unless at least one of units
126 whose names are in the second string is reserved. This is an
127 asymmetric relation. CPU units in the string are separated by
128 commas. For example, it is useful for description that slot1 is
129 reserved after slot0 reservation for a VLIW processor.
131 o (absence_set string string) means that each CPU function unit in
132 the first string can not be reserved only if each unit whose name
133 is in the second string is not reserved. This is an asymmetric
134 relation (actually exclusion set is analogous to this one but it
135 is symmetric). CPU units in the string are separated by commas.
136 For example, it is useful for description that slot0 can not be
137 reserved after slot1 or slot2 reservation for a VLIW processor.
139 o (define_bypass number out_insn_names in_insn_names) names bypass with
140 given latency (the first number) from insns given by the first
141 string (see define_insn_reservation) into insns given by the
142 second string. Insn names in the strings are separated by
145 o (define_automaton string) describes names of an automaton
146 generated and used for pipeline hazards recognition. The names
147 are separated by comma. Actually it is possibly to generate the
148 single automaton but unfortunately it can be very large. If we
149 use more one automata, the summary size of the automata usually
150 is less than the single one. The automaton name is used in
151 define_cpu_unit. All automata should have unique names.
153 o (define_reservation string string) names reservation (the first
154 string) of cpu functional units (the 2nd string). Sometimes unit
155 reservations for different insns contain common parts. In such
156 case, you describe common part and use one its name (the 1st
157 parameter) in regular expression in define_insn_reservation. All
158 define_reservations, define results and define_cpu_units should
159 have unique names which can not be "nothing".
161 o (define_insn_reservation name default_latency condition regexpr)
162 describes reservation of cpu functional units (the 3nd operand)
163 for instruction which is selected by the condition (the 2nd
164 parameter). The first parameter is used for output of debugging
165 information. The reservations are described by a regular
166 expression according the following syntax:
168 regexp = regexp "," oneof
171 oneof = oneof "|" allof
174 allof = allof "+" repeat
177 repeat = element "*" number
180 element = cpu_function_name
186 1. "," is used for describing start of the next cycle in
189 2. "|" is used for describing the reservation described by the
190 first regular expression *or* the reservation described by
191 the second regular expression *or* etc.
193 3. "+" is used for describing the reservation described by the
194 first regular expression *and* the reservation described by
195 the second regular expression *and* etc.
197 4. "*" is used for convenience and simply means sequence in
198 which the regular expression are repeated NUMBER times with
199 cycle advancing (see ",").
201 5. cpu function unit name which means reservation.
203 6. reservation name -- see define_reservation.
205 7. string "nothing" means no units reservation.
208 ;;-----------------------------------------------------------------
211 ;;----------------------------------------------------------------
212 ;; Microblaze 5-stage pipeline description (v5.00.a and later)
213 ;;----------------------------------------------------------------
215 (define_automaton "mbpipe_5")
216 (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")
218 (define_insn_reservation "mb-integer" 1
219 (and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith")
220 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
221 "mb_issue,mb_iu,mb_wb")
223 (define_insn_reservation "mb-special-move" 2
224 (and (eq_attr "type" "move")
225 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
226 "mb_issue,mb_iu*2,mb_wb")
228 (define_insn_reservation "mb-mem-load" 3
229 (and (eq_attr "type" "load,no_delay_load")
230 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
231 "mb_issue,mb_iu,mb_wb")
233 (define_insn_reservation "mb-mem-store" 1
234 (and (eq_attr "type" "store,no_delay_store")
235 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
236 "mb_issue,mb_iu,mb_wb")
238 (define_insn_reservation "mb-mul" 3
239 (and (eq_attr "type" "imul,no_delay_imul")
240 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
241 "mb_issue,mb_mul,mb_mul_2*2,mb_wb")
243 (define_insn_reservation "mb-div" 34
244 (and (eq_attr "type" "idiv")
245 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
246 "mb_issue,mb_div,mb_div_2*33,mb_wb")
248 (define_insn_reservation "mb-bs" 2
249 (and (eq_attr "type" "bshift")
250 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
251 "mb_issue,mb_bs,mb_bs_2,mb_wb")
253 (define_insn_reservation "mb-fpu-add-sub-mul" 6
254 (and (eq_attr "type" "fadd,frsub,fmul")
255 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
256 "mb_issue,mb_fpu,mb_fpu_2*5,mb_wb")
258 (define_insn_reservation "mb-fpu-fcmp" 3
259 (and (eq_attr "type" "fcmp")
260 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
261 "mb_issue,mb_fpu,mb_fpu*2,mb_wb")
263 (define_insn_reservation "mb-fpu-div" 30
264 (and (eq_attr "type" "fdiv")
265 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
266 "mb_issue,mb_fpu,mb_fpu_2*29,mb_wb")
268 (define_insn_reservation "mb-fpu-sqrt" 30
269 (and (eq_attr "type" "fsqrt")
270 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
271 "mb_issue,mb_fpu,mb_fpu_2*29,mb_wb")
273 (define_insn_reservation "mb-fpu-fcvt" 4
274 (and (eq_attr "type" "fcvt")
275 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_5)))
276 "mb_issue,mb_fpu,mb_fpu_2*3,mb_wb")
278 ;;----------------------------------------------------------------
279 ;; Microblaze 3-stage pipeline description (for v4.00.a and earlier)
280 ;;----------------------------------------------------------------
282 (define_automaton "mbpipe_3")
283 (define_cpu_unit "mb3_iu" "mbpipe_3")
285 (define_insn_reservation "mb3-integer" 1
286 (and (eq_attr "type" "branch,jump,call,arith,darith,icmp,nop,no_delay_arith")
287 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
290 (define_insn_reservation "mb3-special-move" 2
291 (and (eq_attr "type" "move")
292 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
295 (define_insn_reservation "mb3-mem-load" 2
296 (and (eq_attr "type" "load,no_delay_load")
297 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
300 (define_insn_reservation "mb3-mem-store" 1
301 (and (eq_attr "type" "store,no_delay_store")
302 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
305 (define_insn_reservation "mb3-mul" 3
306 (and (eq_attr "type" "imul,no_delay_imul")
307 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
310 (define_insn_reservation "mb3-div" 34
311 (and (eq_attr "type" "idiv")
312 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
315 (define_insn_reservation "mb3-bs" 2
316 (and (eq_attr "type" "bshift")
317 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
320 (define_insn_reservation "mb3-fpu-add-sub-mul" 6
321 (and (eq_attr "type" "fadd,frsub,fmul")
322 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
325 (define_insn_reservation "mb3-fpu-fcmp" 3
326 (and (eq_attr "type" "fcmp")
327 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
330 (define_insn_reservation "mb3-fpu-div" 30
331 (and (eq_attr "type" "fdiv")
332 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
335 (define_insn_reservation "mb3-fpu-sqrt" 30
336 (and (eq_attr "type" "fsqrt")
337 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
340 (define_insn_reservation "mb3-fpu-fcvt" 4
341 (and (eq_attr "type" "fcvt")
342 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
345 (automata_option "v")
346 (automata_option "time")
347 (automata_option "progress")
349 ;;----------------------------------------------------------------
350 ;; Microblaze delay slot description
351 ;;----------------------------------------------------------------
352 (define_delay (eq_attr "type" "branch,call,jump")
353 [(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")
354 (ior (eq (symbol_ref "microblaze_no_unsafe_delay") (const_int 0))
355 (eq_attr "type" "!fadd,frsub,fmul,fdiv,fcmp,store,load")
360 ;;----------------------------------------------------------------
362 ;;----------------------------------------------------------------
364 (define_insn "addsf3"
365 [(set (match_operand:SF 0 "register_operand" "=d")
366 (plus:SF (match_operand:SF 1 "register_operand" "d")
367 (match_operand:SF 2 "register_operand" "d")))]
370 [(set_attr "type" "fadd")
371 (set_attr "mode" "SF")
372 (set_attr "length" "4")])
374 (define_insn "subsf3"
375 [(set (match_operand:SF 0 "register_operand" "=d")
376 (minus:SF (match_operand:SF 1 "register_operand" "d")
377 (match_operand:SF 2 "register_operand" "d")))]
380 [(set_attr "type" "frsub")
381 (set_attr "mode" "SF")
382 (set_attr "length" "4")])
384 (define_insn "mulsf3"
385 [(set (match_operand:SF 0 "register_operand" "=d")
386 (mult:SF (match_operand:SF 1 "register_operand" "d")
387 (match_operand:SF 2 "register_operand" "d")))]
390 [(set_attr "type" "fmul")
391 (set_attr "mode" "SF")
392 (set_attr "length" "4")])
395 (define_insn "divsf3"
396 [(set (match_operand:SF 0 "register_operand" "=d")
397 (div:SF (match_operand:SF 1 "register_operand" "d")
398 (match_operand:SF 2 "register_operand" "d")))]
401 [(set_attr "type" "fdiv")
402 (set_attr "mode" "SF")
403 (set_attr "length" "4")])
405 (define_insn "sqrtsf2"
406 [(set (match_operand:SF 0 "register_operand" "=d")
407 (sqrt:SF (match_operand:SF 1 "register_operand" "d")))]
408 "TARGET_HARD_FLOAT && TARGET_FLOAT_SQRT"
410 [(set_attr "type" "fsqrt")
411 (set_attr "mode" "SF")
412 (set_attr "length" "4")])
414 (define_insn "floatsisf2"
415 [(set (match_operand:SF 0 "register_operand" "=d")
416 (float:SF (match_operand:SI 1 "register_operand" "d")))]
417 "TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT"
419 [(set_attr "type" "fcvt")
420 (set_attr "mode" "SF")
421 (set_attr "length" "4")])
423 (define_insn "fix_truncsfsi2"
424 [(set (match_operand:SI 0 "register_operand" "=d")
425 (fix:SI (match_operand:SF 1 "register_operand" "d")))]
426 "TARGET_HARD_FLOAT && TARGET_FLOAT_CONVERT"
428 [(set_attr "type" "fcvt")
429 (set_attr "mode" "SF")
430 (set_attr "length" "4")])
432 ;;----------------------------------------------------------------
434 ;;----------------------------------------------------------------
436 ;; Add 2 SImode integers [ src1 = reg ; src2 = arith ; dest = reg ]
438 (define_insn "addsi3"
439 [(set (match_operand:SI 0 "register_operand" "=d,d,d")
440 (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ")
441 (match_operand:SI 2 "arith_operand" "d,I,i")))]
447 [(set_attr "type" "arith,arith,no_delay_arith")
448 (set_attr "mode" "SI,SI,SI")
449 (set_attr "length" "4,4,8")])
451 ;;----------------------------------------------------------------
452 ;; Double Precision Additions
453 ;;----------------------------------------------------------------
455 ;; reg_DI_dest = reg_DI_src1 + DI_src2
457 ;; Adding 2 DI operands in register or reg/imm
459 (define_insn "adddi3"
460 [(set (match_operand:DI 0 "register_operand" "=d,d,d")
461 (plus:DI (match_operand:DI 1 "register_operand" "%d,d,d")
462 (match_operand:DI 2 "arith_operand32" "d,P,N")))]
465 add\t%L0,%L1,%L2\;addc\t%M0,%M1,%M2
466 addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0
467 addi\t%L0,%L1,%2\;addc\t%M0,%M1,r0\;addi\t%M0,%M0,-1"
468 [(set_attr "type" "darith")
469 (set_attr "mode" "DI")
470 (set_attr "length" "8,8,12")])
472 ;;----------------------------------------------------------------
474 ;;----------------------------------------------------------------
476 (define_insn "subsi3"
477 [(set (match_operand:SI 0 "register_operand" "=d,d")
478 (minus:SI (match_operand:SI 1 "arith_operand" "d,d")
479 (match_operand:SI 2 "arith_operand" "d,n")))]
484 [(set_attr "type" "arith,no_delay_arith")
485 (set_attr "mode" "SI")
486 (set_attr "length" "4,8")])
489 ;;----------------------------------------------------------------
490 ;; Double Precision Subtraction
491 ;;----------------------------------------------------------------
493 (define_insn "subdi3"
494 [(set (match_operand:DI 0 "register_operand" "=&d")
495 (minus:DI (match_operand:DI 1 "register_operand" "d")
496 (match_operand:DI 2 "arith_operand32" "d")))]
499 rsub\t%L0,%L2,%L1\;rsubc\t%M0,%M2,%M1"
500 [(set_attr "type" "darith")
501 (set_attr "mode" "DI")
502 (set_attr "length" "8")])
505 ;;----------------------------------------------------------------
507 ;;----------------------------------------------------------------
509 (define_insn "mulsi3"
510 [(set (match_operand:SI 0 "register_operand" "=d,d,d")
511 (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
512 (match_operand:SI 2 "arith_operand" "d,I,i")))]
518 [(set_attr "type" "imul,imul,no_delay_imul")
519 (set_attr "mode" "SI")
520 (set_attr "length" "4,4,8")])
522 (define_insn "mulsidi3"
523 [(set (match_operand:DI 0 "register_operand" "=&d")
525 (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
526 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
527 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
528 "mul\t%L0,%1,%2\;mulh\t%M0,%1,%2"
529 [(set_attr "type" "no_delay_arith")
530 (set_attr "mode" "DI")
531 (set_attr "length" "8")])
533 (define_insn "umulsidi3"
534 [(set (match_operand:DI 0 "register_operand" "=&d")
536 (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
537 (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
538 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
539 "mul\t%L0,%1,%2\;mulhu\t%M0,%1,%2"
540 [(set_attr "type" "no_delay_arith")
541 (set_attr "mode" "DI")
542 (set_attr "length" "8")])
544 (define_insn "usmulsidi3"
545 [(set (match_operand:DI 0 "register_operand" "=&d")
547 (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
548 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
549 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
550 "mul\t%L0,%1,%2\;mulhsu\t%M0,%2,%1"
551 [(set_attr "type" "no_delay_arith")
552 (set_attr "mode" "DI")
553 (set_attr "length" "8")])
555 (define_insn "*smulsi3_highpart"
556 [(set (match_operand:SI 0 "register_operand" "=d")
559 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
560 (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))
562 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
564 [(set_attr "type" "imul")
565 (set_attr "mode" "SI")
566 (set_attr "length" "4")])
568 (define_insn "*umulsi3_highpart"
569 [(set (match_operand:SI 0 "register_operand" "=d")
572 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
573 (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))
576 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
578 [(set_attr "type" "imul")
579 (set_attr "mode" "SI")
580 (set_attr "length" "4")])
582 (define_insn "*usmulsi3_highpart"
583 [(set (match_operand:SI 0 "register_operand" "=d")
586 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
587 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))
590 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
592 [(set_attr "type" "imul")
593 (set_attr "mode" "SI")
594 (set_attr "length" "4")])
597 ;;----------------------------------------------------------------
598 ;; Division and remainder
599 ;;----------------------------------------------------------------
600 (define_expand "divsi3"
601 [(set (match_operand:SI 0 "register_operand" "=d")
602 (div:SI (match_operand:SI 1 "register_operand" "d")
603 (match_operand:SI 2 "register_operand" "d")))
605 "(!TARGET_SOFT_DIV) || (TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)"
607 if (TARGET_SOFT_DIV && TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)
609 microblaze_expand_divide (operands);
612 else if (!TARGET_SOFT_DIV)
614 emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2]));
621 (define_insn "divsi3_internal"
622 [(set (match_operand:SI 0 "register_operand" "=d")
623 (div:SI (match_operand:SI 1 "register_operand" "d")
624 (match_operand:SI 2 "register_operand" "d")))
628 [(set_attr "type" "idiv")
629 (set_attr "mode" "SI")
630 (set_attr "length" "4")]
633 (define_insn "udivsi3"
634 [(set (match_operand:SI 0 "register_operand" "=d")
635 (udiv:SI (match_operand:SI 1 "register_operand" "d")
636 (match_operand:SI 2 "register_operand" "d")))
640 [(set_attr "type" "idiv")
641 (set_attr "mode" "SI")
642 (set_attr "length" "4")])
645 ;;----------------------------------------------------------------
646 ;; Negation and one's complement
647 ;;----------------------------------------------------------------
649 (define_insn "negsi2"
650 [(set (match_operand:SI 0 "register_operand" "=d")
651 (neg:SI (match_operand:SI 1 "register_operand" "d")))]
654 [(set_attr "type" "arith")
655 (set_attr "mode" "SI")
656 (set_attr "length" "4")])
658 (define_insn "negdi2"
659 [(set (match_operand:DI 0 "register_operand" "=d")
660 (neg:DI (match_operand:DI 1 "register_operand" "d")))]
662 "rsub\t%L0,%L1,r0\;rsubc\t%M0,%M1,r0"
663 [(set_attr "type" "darith")
664 (set_attr "mode" "DI")
665 (set_attr "length" "8")])
668 (define_insn "one_cmplsi2"
669 [(set (match_operand:SI 0 "register_operand" "=d")
670 (not:SI (match_operand:SI 1 "register_operand" "d")))]
673 [(set_attr "type" "arith")
674 (set_attr "mode" "SI")
675 (set_attr "length" "4")])
677 (define_insn "*one_cmpldi2"
678 [(set (match_operand:DI 0 "register_operand" "=d")
679 (not:DI (match_operand:DI 1 "register_operand" "d")))]
681 "nor\t%M0,r0,%M1\;nor\t%L0,r0,%L1"
682 [(set_attr "type" "darith")
683 (set_attr "mode" "DI")
684 (set_attr "length" "8")]
688 [(set (match_operand:DI 0 "register_operand" "")
689 (not:DI (match_operand:DI 1 "register_operand" "")))]
691 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
692 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
694 [(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0)))
695 (set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))]
699 ;;----------------------------------------------------------------
701 ;;----------------------------------------------------------------
703 (define_insn "andsi3"
704 [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
705 (and:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d")
706 (match_operand:SI 2 "arith_operand" "d,I,i,M")))]
712 andi\t%0,%1,%2 #and3"
713 [(set_attr "type" "arith,arith,no_delay_arith,no_delay_arith")
714 (set_attr "mode" "SI,SI,SI,SI")
715 (set_attr "length" "4,8,8,8")])
718 (define_insn "anddi3"
719 [(set (match_operand:DI 0 "register_operand" "=d")
720 (and:DI (match_operand:DI 1 "register_operand" "d")
721 (match_operand:DI 2 "register_operand" "d")))]
723 "and\t%M0,%M1,%M2\;and\t%L0,%L1,%L2"
724 [(set_attr "type" "darith")
725 (set_attr "mode" "DI")
726 (set_attr "length" "8")])
730 [(set (match_operand:DI 0 "register_operand" "")
731 (and:DI (match_operand:DI 1 "register_operand" "")
732 (match_operand:DI 2 "register_operand" "")))]
734 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
735 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
736 && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
738 [(set (subreg:SI (match_dup 0) 0) (and:SI (subreg:SI (match_dup 1) 0)
739 (subreg:SI (match_dup 2) 0)))
740 (set (subreg:SI (match_dup 0) 4) (and:SI (subreg:SI (match_dup 1) 4)
741 (subreg:SI (match_dup 2) 4)))]
744 (define_insn "iorsi3"
745 [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
746 (ior:SI (match_operand:SI 1 "arith_operand" "%d,d,d,d")
747 (match_operand:SI 2 "arith_operand" "d,I,M,i")))]
754 [(set_attr "type" "arith,no_delay_arith,no_delay_arith,no_delay_arith")
755 (set_attr "mode" "SI,SI,SI,SI")
756 (set_attr "length" "4,8,8,8")])
759 (define_insn "iordi3"
760 [(set (match_operand:DI 0 "register_operand" "=d")
761 (ior:DI (match_operand:DI 1 "register_operand" "d")
762 (match_operand:DI 2 "register_operand" "d")))]
764 "or\t%M0,%M1,%M2\;or\t%L0,%L1,%L2"
765 [(set_attr "type" "darith")
766 (set_attr "mode" "DI")
767 (set_attr "length" "8")]
772 [(set (match_operand:DI 0 "register_operand" "")
773 (ior:DI (match_operand:DI 1 "register_operand" "")
774 (match_operand:DI 2 "register_operand" "")))]
776 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
777 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
778 && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
780 [(set (subreg:SI (match_dup 0) 0) (ior:SI (subreg:SI (match_dup 1) 0)
781 (subreg:SI (match_dup 2) 0)))
782 (set (subreg:SI (match_dup 0) 4) (ior:SI (subreg:SI (match_dup 1) 4)
783 (subreg:SI (match_dup 2) 4)))]
786 (define_insn "xorsi3"
787 [(set (match_operand:SI 0 "register_operand" "=d,d,d")
788 (xor:SI (match_operand:SI 1 "arith_operand" "%d,d,d")
789 (match_operand:SI 2 "arith_operand" "d,I,i")))]
795 [(set_attr "type" "arith,arith,no_delay_arith")
796 (set_attr "mode" "SI,SI,SI")
797 (set_attr "length" "4,8,8")])
799 (define_insn "xordi3"
800 [(set (match_operand:DI 0 "register_operand" "=d")
801 (xor:DI (match_operand:DI 1 "register_operand" "d")
802 (match_operand:DI 2 "register_operand" "d")))]
804 "xor\t%M0,%M1,%M2\;xor\t%L0,%L1,%L2"
805 [(set_attr "type" "darith")
806 (set_attr "mode" "DI")
807 (set_attr "length" "8")]
812 [(set (match_operand:DI 0 "register_operand" "")
813 (xor:DI (match_operand:DI 1 "register_operand" "")
814 (match_operand:DI 2 "register_operand" "")))]
816 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
817 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
818 && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
820 [(set (subreg:SI (match_dup 0) 0) (xor:SI (subreg:SI (match_dup 1) 0)
821 (subreg:SI (match_dup 2) 0)))
822 (set (subreg:SI (match_dup 0) 4) (xor:SI (subreg:SI (match_dup 1) 4)
823 (subreg:SI (match_dup 2) 4)))]
826 ;;----------------------------------------------------------------
828 ;;----------------------------------------------------------------
830 (define_insn "zero_extendhisi2"
831 [(set (match_operand:SI 0 "register_operand" "=d,d,d")
832 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,m")))]
838 [(set_attr "type" "no_delay_arith,load,no_delay_load")
839 (set_attr "mode" "SI,SI,SI")
840 (set_attr "length" "8,4,8")])
842 (define_insn "zero_extendqihi2"
843 [(set (match_operand:HI 0 "register_operand" "=d,d,d")
844 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))]
850 [(set_attr "type" "arith,load,no_delay_load")
851 (set_attr "mode" "HI")
852 (set_attr "length" "4,4,8")])
854 (define_insn "zero_extendqisi2"
855 [(set (match_operand:SI 0 "register_operand" "=d,d,d")
856 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,R,m")))]
862 [(set_attr "type" "arith,load,no_delay_load")
863 (set_attr "mode" "SI,SI,SI")
864 (set_attr "length" "4,4,8")])
866 ;;----------------------------------------------------------------
868 ;;----------------------------------------------------------------
870 ;; basic Sign Extend Operations
872 (define_insn "extendqisi2"
873 [(set (match_operand:SI 0 "register_operand" "=d")
874 (sign_extend:SI (match_operand:QI 1 "register_operand" "d")))]
877 [(set_attr "type" "arith")
878 (set_attr "mode" "SI")
879 (set_attr "length" "4")])
881 (define_insn "extendhisi2"
882 [(set (match_operand:SI 0 "register_operand" "=d")
883 (sign_extend:SI (match_operand:HI 1 "register_operand" "d")))]
886 [(set_attr "type" "arith")
887 (set_attr "mode" "SI")
888 (set_attr "length" "4")])
890 ;; Those for integer source operand are ordered
891 ;; widest source type first.
893 (define_insn "extendsidi2"
894 [(set (match_operand:DI 0 "register_operand" "=d,d,d")
895 (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))]
898 if (which_alternative == 0)
899 output_asm_insn ("addk\t%D0,r0,%1", operands);
901 output_asm_insn ("lw%i1\t%D0,%1", operands);
903 output_asm_insn ("add\t%0,%D0,%D0", operands);
904 output_asm_insn ("addc\t%0,r0,r0", operands);
905 output_asm_insn ("beqi\t%0,.+8", operands);
906 return "addi\t%0,r0,0xffffffff";
908 [(set_attr "type" "multi,multi,multi")
909 (set_attr "mode" "DI")
910 (set_attr "length" "20,20,20")])
912 ;;----------------------------------------------------------------
914 ;;----------------------------------------------------------------
916 ;; 64-bit integer moves
918 ;; Unlike most other insns, the move insns can't be split with
919 ;; different predicates, because register spilling and other parts of
920 ;; the compiler, have memoized the insn number already.
922 (define_expand "movdi"
923 [(set (match_operand:DI 0 "nonimmediate_operand" "")
924 (match_operand:DI 1 "general_operand" ""))]
927 /* If operands[1] is a constant address illegal for pic, then we need to
928 handle it just like microblaze_legitimize_address does. */
929 if (flag_pic && pic_address_needs_scratch (operands[1]))
931 rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0));
932 rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
933 emit_move_insn (operands[0], gen_rtx_PLUS (DImode, temp, temp2));
938 if ((reload_in_progress | reload_completed) == 0
939 && !register_operand (operands[0], DImode)
940 && !register_operand (operands[1], DImode)
941 && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
942 && operands[1] != CONST0_RTX (DImode))))
945 rtx temp = force_reg (DImode, operands[1]);
946 emit_move_insn (operands[0], temp);
954 (define_insn "*movdi_internal"
955 [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
956 (match_operand:DI 1 "general_operand" " d,i,J,R,m,d,d"))]
959 switch (which_alternative)
962 return "addk\t%0,%1\n\taddk\t%D0,%d1";
964 return "addik\t%0,r0,%h1\n\taddik\t%D0,r0,%j1 #li => la";
966 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";
969 if (reg_mentioned_p (operands[0], operands[1]))
970 return "lwi\t%D0,%o1\n\tlwi\t%0,%1";
972 return "lwi\t%0,%1\n\tlwi\t%D0,%o1";
975 return "swi\t%1,%0\n\tswi\t%D1,%o0";
977 return "unreachable";
979 [(set_attr "type" "no_delay_move,no_delay_arith,no_delay_arith,no_delay_load,no_delay_load,no_delay_store,no_delay_store")
980 (set_attr "mode" "DI")
981 (set_attr "length" "8,8,8,8,12,8,12")])
984 [(set (match_operand:DI 0 "register_operand" "")
985 (match_operand:DI 1 "register_operand" ""))]
987 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
988 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
989 && (REGNO(operands[0]) == (REGNO(operands[1]) + 1))"
991 [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))
992 (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]
996 [(set (match_operand:DI 0 "register_operand" "")
997 (match_operand:DI 1 "register_operand" ""))]
999 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
1000 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
1001 && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"
1003 [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
1004 (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
1007 ;; Unlike most other insns, the move insns can't be split with
1008 ;; different predicates, because register spilling and other parts of
1009 ;; the compiler, have memoized the insn number already.
1011 (define_expand "movsi"
1012 [(set (match_operand:SI 0 "nonimmediate_operand" "")
1013 (match_operand:SI 1 "general_operand" ""))]
1016 if (microblaze_expand_move (SImode, operands)) DONE;
1020 ;; Added for status resgisters
1021 (define_insn "movsi_status"
1022 [(set (match_operand:SI 0 "register_operand" "=d,d,z")
1023 (match_operand:SI 1 "register_operand" "z,d,d"))]
1027 addk\t%0,%1,r0 #add movsi
1029 [(set_attr "type" "move")
1030 (set_attr "mode" "SI")
1031 (set_attr "length" "12")])
1033 ;; This move will be not be moved to delay slot.
1034 (define_insn "*movsi_internal3"
1035 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d")
1036 (match_operand:SI 1 "immediate_operand" "J,I,Mnis"))]
1037 "(register_operand (operands[0], SImode) &&
1038 (GET_CODE (operands[1]) == CONST_INT &&
1039 (INTVAL (operands[1]) <= 32767 && INTVAL (operands[1]) >= -32768)))"
1042 addik\t%0,r0,%1\t# %X1
1043 addik\t%0,r0,%1\t# %X1"
1044 [(set_attr "type" "arith,arith,no_delay_arith")
1045 (set_attr "mode" "SI")
1046 (set_attr "length" "4")])
1048 ;; This move may be used for PLT label operand
1049 (define_insn "*movsi_internal5_pltop"
1050 [(set (match_operand:SI 0 "register_operand" "=d,d")
1051 (match_operand:SI 1 "call_insn_operand" ""))]
1052 "(register_operand (operands[0], Pmode) &&
1053 PLT_ADDR_P (operands[1]))"
1057 [(set_attr "type" "load")
1058 (set_attr "mode" "SI")
1059 (set_attr "length" "4")])
1061 (define_insn "*movsi_internal2"
1062 [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d, d,d,R, T")
1063 (match_operand:SI 1 "move_operand" " d,I,Mnis,R,m,dJ,dJ"))]
1064 "(register_operand (operands[0], SImode)
1065 || register_operand (operands[1], SImode)
1066 || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))
1067 && (flag_pic != 2 || (GET_CODE (operands[1]) != SYMBOL_REF
1068 && GET_CODE (operands[1]) != LABEL_REF))"
1071 addik\t%0,r0,%1\t# %X1
1077 [(set_attr "type" "load,load,no_delay_load,load,no_delay_load,store,no_delay_store")
1078 (set_attr "mode" "SI")
1079 (set_attr "length" "4,4,8,4,8,4,8")])
1082 ;; 16-bit Integer moves
1084 ;; Unlike most other insns, the move insns can't be split with
1085 ;; different predicates, because register spilling and other parts of
1086 ;; the compiler, have memoized the insn number already.
1087 ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined
1089 (define_expand "movhi"
1090 [(set (match_operand:HI 0 "nonimmediate_operand" "")
1091 (match_operand:HI 1 "general_operand" ""))]
1094 if ((reload_in_progress | reload_completed) == 0
1095 && !register_operand (operands[0], HImode)
1096 && !register_operand (operands[1], HImode)
1097 && ((GET_CODE (operands[1]) != CONST_INT
1098 || INTVAL (operands[1]) != 0)))
1100 rtx temp = force_reg (HImode, operands[1]);
1101 emit_move_insn (operands[0], temp);
1107 (define_insn "*movhi_internal2"
1108 [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m")
1109 (match_operand:HI 1 "general_operand" "I,d,R,m,dJ,dJ"))]
1112 addik\t%0,r0,%1\t# %X1
1118 [(set_attr "type" "arith,move,load,no_delay_load,store,no_delay_store")
1119 (set_attr "mode" "HI")
1120 (set_attr "length" "4,4,4,8,8,8")])
1122 ;; 8-bit Integer moves
1124 ;; Unlike most other insns, the move insns can't be split with
1125 ;; different predicates, because register spilling and other parts of
1126 ;; the compiler, have memoized the insn number already.
1127 ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined
1129 (define_expand "movqi"
1130 [(set (match_operand:QI 0 "nonimmediate_operand" "")
1131 (match_operand:QI 1 "general_operand" ""))]
1134 if ((reload_in_progress | reload_completed) == 0
1135 && !register_operand (operands[0], QImode)
1136 && !register_operand (operands[1], QImode)
1137 && ((GET_CODE (operands[1]) != CONST_INT
1138 || INTVAL (operands[1]) != 0)))
1140 rtx temp = force_reg (QImode, operands[1]);
1141 emit_move_insn (operands[0], temp);
1147 (define_insn "*movqi_internal2"
1148 [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
1149 (match_operand:QI 1 "general_operand" "J,I,d,R,m,dJ,dJ"))]
1153 addik\t%0,r0,%1\t# %X1
1159 [(set_attr "type" "arith,arith,move,load,no_delay_load,store,no_delay_store")
1160 (set_attr "mode" "QI")
1161 (set_attr "length" "4,4,8,4,8,4,8")])
1163 ;; Block moves, see microblaze.c for more details.
1164 ;; Argument 0 is the destination
1165 ;; Argument 1 is the source
1166 ;; Argument 2 is the length
1167 ;; Argument 3 is the alignment
1169 (define_expand "movmemsi"
1170 [(parallel [(set (match_operand:BLK 0 "general_operand")
1171 (match_operand:BLK 1 "general_operand"))
1172 (use (match_operand:SI 2 ""))
1173 (use (match_operand:SI 3 "const_int_operand"))])]
1176 if (microblaze_expand_block_move (operands[0], operands[1],
1177 operands[2], operands[3]))
1184 ;; 32-bit floating point moves
1186 (define_expand "movsf"
1187 [(set (match_operand:SF 0 "nonimmediate_operand" "")
1188 (match_operand:SF 1 "general_operand" ""))]
1191 if ((reload_in_progress | reload_completed) == 0
1192 && !register_operand (operands[0], SFmode)
1193 && !register_operand (operands[1], SFmode)
1194 && ( ((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
1195 && operands[1] != CONST0_RTX (SFmode))))
1197 rtx temp = force_reg (SFmode, operands[1]);
1198 emit_move_insn (operands[0], temp);
1204 ;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
1206 (define_insn "*movsf_internal"
1207 [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,d,d,R,m")
1208 (match_operand:SF 1 "general_operand" "G,d,R,F,m,d,d"))]
1209 "(register_operand (operands[0], SFmode)
1210 || register_operand (operands[1], SFmode)
1211 || operands[1] == CONST0_RTX (SFmode))"
1220 [(set_attr "type" "move,no_delay_load,load,no_delay_load,no_delay_load,store,no_delay_store")
1221 (set_attr "mode" "SF")
1222 (set_attr "length" "4,4,4,4,4,4,4")])
1224 ;; 64-bit floating point moves
1225 (define_expand "movdf"
1226 [(set (match_operand:DF 0 "nonimmediate_operand" "")
1227 (match_operand:DF 1 "general_operand" ""))]
1230 if (flag_pic == 2) {
1231 if (GET_CODE (operands[1]) == MEM
1232 && !microblaze_legitimate_address_p (DFmode, XEXP (operands[1],0), 0))
1236 ptr_reg = force_reg (Pmode, XEXP (operands[1],0));
1237 result = gen_rtx_MEM (DFmode, ptr_reg);
1238 emit_move_insn (operands[0], result);
1242 if ((reload_in_progress | reload_completed) == 0
1243 && !register_operand (operands[0], DFmode)
1244 && !register_operand (operands[1], DFmode)
1245 && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
1246 && operands[1] != CONST0_RTX (DFmode))))
1248 rtx temp = force_reg (DFmode, operands[1]);
1249 emit_move_insn (operands[0], temp);
1256 ;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
1258 (define_insn "*movdf_internal"
1259 [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,To")
1260 (match_operand:DF 1 "general_operand" "dG,o,F,T,d"))]
1263 switch (which_alternative)
1266 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";
1269 if (reg_mentioned_p (operands[0], operands[1]))
1270 return "lwi\t%D0,%o1\n\tlwi\t%0,%1";
1272 return "lwi\t%0,%1\n\tlwi\t%D0,%o1";
1275 return "addik\t%0,r0,%h1 \n\taddik\t%D0,r0,%j1 #Xfer Lo";
1278 return "swi\t%1,%0\n\tswi\t%D1,%o0";
1282 [(set_attr "type" "no_delay_move,no_delay_load,no_delay_load,no_delay_load,no_delay_store")
1283 (set_attr "mode" "DF")
1284 (set_attr "length" "4,8,8,16,8")])
1287 [(set (match_operand:DF 0 "register_operand" "")
1288 (match_operand:DF 1 "register_operand" ""))]
1290 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
1291 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
1292 && (REGNO (operands[0]) == (REGNO (operands[1]) + 1))"
1293 [(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))
1294 (set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]
1298 [(set (match_operand:DF 0 "register_operand" "")
1299 (match_operand:DF 1 "register_operand" ""))]
1301 && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
1302 && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
1303 && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"
1304 [(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
1305 (set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
1308 ;;----------------------------------------------------------------
1310 ;;----------------------------------------------------------------
1312 ;;----------------------------------------------------------------
1313 ;; 32-bit left shifts
1314 ;;----------------------------------------------------------------
1315 (define_expand "ashlsi3"
1316 [(set (match_operand:SI 0 "register_operand" "=&d")
1317 (ashift:SI (match_operand:SI 1 "register_operand" "d")
1318 (match_operand:SI 2 "arith_operand" "")))]
1321 /* Avoid recursion for trivial cases. */
1322 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1323 if (microblaze_expand_shift (operands))
1328 ;; Irrespective of if we have a barrel-shifter or not, we want to match
1329 ;; shifts by 1 with a special pattern. When a barrel shifter is present,
1330 ;; saves a cycle. If not, allows us to annotate the instruction for delay
1331 ;; slot optimization
1332 (define_insn "*ashlsi3_byone"
1333 [(set (match_operand:SI 0 "register_operand" "=d")
1334 (ashift:SI (match_operand:SI 1 "register_operand" "d")
1335 (match_operand:SI 2 "arith_operand" "I")))]
1336 "(INTVAL (operands[2]) == 1)"
1338 [(set_attr "type" "arith")
1339 (set_attr "mode" "SI")
1340 (set_attr "length" "4")]
1343 ;; Barrel shift left
1344 (define_insn "ashlsi3_bshift"
1345 [(set (match_operand:SI 0 "register_operand" "=d,d")
1346 (ashift:SI (match_operand:SI 1 "register_operand" "d,d")
1347 (match_operand:SI 2 "arith_operand" "I,d")))]
1348 "TARGET_BARREL_SHIFT"
1352 [(set_attr "type" "bshift,bshift")
1353 (set_attr "mode" "SI,SI")
1354 (set_attr "length" "4,4")]
1357 ;; The following patterns apply when there is no barrel shifter present
1359 (define_insn "*ashlsi3_with_mul_delay"
1360 [(set (match_operand:SI 0 "register_operand" "=d")
1361 (ashift:SI (match_operand:SI 1 "register_operand" "d")
1362 (match_operand:SI 2 "immediate_operand" "I")))]
1364 && ((1 << INTVAL (operands[2])) <= 32767 && (1 << INTVAL (operands[2])) >= -32768)"
1366 ;; This MUL will not generate an imm. Can go into a delay slot.
1367 [(set_attr "type" "arith")
1368 (set_attr "mode" "SI")
1369 (set_attr "length" "4")]
1372 (define_insn "*ashlsi3_with_mul_nodelay"
1373 [(set (match_operand:SI 0 "register_operand" "=d")
1374 (ashift:SI (match_operand:SI 1 "register_operand" "d")
1375 (match_operand:SI 2 "immediate_operand" "I")))]
1378 ;; This MUL will generate an IMM. Cannot go into a delay slot
1379 [(set_attr "type" "no_delay_arith")
1380 (set_attr "mode" "SI")
1381 (set_attr "length" "8")]
1384 (define_insn "*ashlsi3_with_size_opt"
1385 [(set (match_operand:SI 0 "register_operand" "=&d")
1386 (ashift:SI (match_operand:SI 1 "register_operand" "d")
1387 (match_operand:SI 2 "immediate_operand" "I")))]
1388 "(INTVAL (operands[2]) > 5 && optimize_size)"
1390 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1392 output_asm_insn ("ori\t%3,r0,%2", operands);
1393 if (REGNO (operands[0]) != REGNO (operands[1]))
1394 output_asm_insn ("addk\t%0,%1,r0", operands);
1396 output_asm_insn ("addik\t%3,%3,-1", operands);
1397 output_asm_insn ("bneid\t%3,.-4", operands);
1398 return "addk\t%0,%0,%0";
1400 [(set_attr "type" "multi")
1401 (set_attr "mode" "SI")
1402 (set_attr "length" "20")]
1405 (define_insn "*ashlsi3_with_rotate"
1406 [(set (match_operand:SI 0 "register_operand" "=&d")
1407 (ashift:SI (match_operand:SI 1 "register_operand" "d")
1408 (match_operand:SI 2 "immediate_operand" "I")))]
1409 "(INTVAL (operands[2]) > 17 && !optimize_size)"
1413 nshift = INTVAL (operands[2]);
1414 operands[3] = gen_int_mode (0xFFFFFFFF << nshift, SImode);
1416 /* We do one extra shift so that the first bit (carry) coming into the MSB
1417 will be masked out */
1418 output_asm_insn ("src\t%0,%1", operands);
1419 for (i = 0; i < (32 - nshift); i++)
1420 output_asm_insn ("src\t%0,%0", operands);
1422 return "andi\t%0,%0,%3";
1424 [(set_attr "type" "multi")
1425 (set_attr "mode" "SI")
1426 (set_attr "length" "80")]
1429 (define_insn "*ashlsi_inline"
1430 [(set (match_operand:SI 0 "register_operand" "=&d")
1431 (ashift:SI (match_operand:SI 1 "register_operand" "d")
1432 (match_operand:SI 2 "immediate_operand" "I")))]
1436 int nshift = INTVAL (operands[2]);
1437 if (REGNO (operands[0]) != REGNO (operands[1]))
1438 output_asm_insn ("addk\t%0,r0,%1", operands);
1439 output_asm_insn ("addk\t%0,%1,%1", operands);
1440 for (i = 0; i < (nshift - 2); i++)
1441 output_asm_insn ("addk\t%0,%0,%0", operands);
1442 return "addk\t%0,%0,%0";
1444 [(set_attr "type" "multi")
1445 (set_attr "mode" "SI")
1446 (set_attr "length" "124")]
1449 (define_insn "*ashlsi_reg"
1450 [(set (match_operand:SI 0 "register_operand" "=&d")
1451 (ashift:SI (match_operand:SI 1 "register_operand" "d")
1452 (match_operand:SI 2 "register_operand" "d")))]
1455 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1456 output_asm_insn ("andi\t%3,%2,31", operands);
1457 if (REGNO (operands[0]) != REGNO (operands[1]))
1458 output_asm_insn ("addk\t%0,r0,%1", operands);
1459 /* Exit the loop if zero shift. */
1460 output_asm_insn ("beqid\t%3,.+20", operands);
1461 /* Emit the loop. */
1462 output_asm_insn ("addk\t%0,%0,r0", operands);
1463 output_asm_insn ("addik\t%3,%3,-1", operands);
1464 output_asm_insn ("bneid\t%3,.-4", operands);
1465 return "addk\t%0,%0,%0";
1467 [(set_attr "type" "multi")
1468 (set_attr "mode" "SI")
1469 (set_attr "length" "28")]
1473 ;;----------------------------------------------------------------
1474 ;; 32-bit right shifts
1475 ;;----------------------------------------------------------------
1476 (define_expand "ashrsi3"
1477 [(set (match_operand:SI 0 "register_operand" "=&d")
1478 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
1479 (match_operand:SI 2 "arith_operand" "")))]
1482 /* Avoid recursion for trivial cases. */
1483 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1484 if (microblaze_expand_shift (operands))
1489 ;; Irrespective of if we have a barrel-shifter or not, we want to match
1490 ;; shifts by 1 with a special pattern. When a barrel shifter is present,
1491 ;; saves a cycle. If not, allows us to annotate the instruction for delay
1492 ;; slot optimization
1493 (define_insn "*ashrsi3_byone"
1494 [(set (match_operand:SI 0 "register_operand" "=d")
1495 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
1496 (match_operand:SI 2 "arith_operand" "I")))]
1497 "(INTVAL (operands[2]) == 1)"
1499 [(set_attr "type" "arith")
1500 (set_attr "mode" "SI")
1501 (set_attr "length" "4")]
1504 ;; Barrel shift right logical
1505 (define_insn "*ashrsi3_bshift"
1506 [(set (match_operand:SI 0 "register_operand" "=d,d")
1507 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
1508 (match_operand:SI 2 "arith_operand" "I,d")))]
1509 "TARGET_BARREL_SHIFT"
1513 [(set_attr "type" "bshift,bshift")
1514 (set_attr "mode" "SI,SI")
1515 (set_attr "length" "4,4")]
1518 (define_insn "*ashrsi_inline"
1519 [(set (match_operand:SI 0 "register_operand" "=&d")
1520 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
1521 (match_operand:SI 2 "immediate_operand" "I")))]
1525 int nshift = INTVAL (operands[2]);
1526 if (REGNO (operands[0]) != REGNO (operands[1]))
1527 output_asm_insn ("addk\t%0,r0,%1", operands);
1528 output_asm_insn ("sra\t%0,%1", operands);
1529 for (i = 0; i < (nshift - 2); i++)
1530 output_asm_insn ("sra\t%0,%0", operands);
1531 return "sra\t%0,%0";
1533 [(set_attr "type" "multi")
1534 (set_attr "mode" "SI")
1535 (set_attr "length" "124")]
1538 (define_insn "*ashlri_reg"
1539 [(set (match_operand:SI 0 "register_operand" "=&d")
1540 (ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
1541 (match_operand:SI 2 "register_operand" "d")))]
1544 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1545 output_asm_insn ("andi\t%3,%2,31", operands);
1546 if (REGNO (operands[0]) != REGNO (operands[1]))
1547 output_asm_insn ("addk\t%0,r0,%1", operands);
1548 /* Exit the loop if zero shift. */
1549 output_asm_insn ("beqid\t%3,.+20", operands);
1550 /* Emit the loop. */
1551 output_asm_insn ("addk\t%0,%0,r0", operands);
1552 output_asm_insn ("addik\t%3,%3,-1", operands);
1553 output_asm_insn ("bneid\t%3,.-4", operands);
1554 return "sra\t%0,%0";
1556 [(set_attr "type" "multi")
1557 (set_attr "mode" "SI")
1558 (set_attr "length" "28")]
1561 ;;----------------------------------------------------------------
1562 ;; 32-bit right shifts (logical)
1563 ;;----------------------------------------------------------------
1565 (define_expand "lshrsi3"
1566 [(set (match_operand:SI 0 "register_operand" "=&d")
1567 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d")
1568 (match_operand:SI 2 "arith_operand" "")))]
1571 /* Avoid recursion for trivial cases. */
1572 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1573 if (microblaze_expand_shift (operands))
1578 ;; Irrespective of if we have a barrel-shifter or not, we want to match
1579 ;; shifts by 1 with a special pattern. When a barrel shifter is present,
1580 ;; saves a cycle. If not, allows us to annotate the instruction for delay
1581 ;; slot optimization
1582 (define_insn "*lshrsi3_byone"
1583 [(set (match_operand:SI 0 "register_operand" "=d")
1584 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d")
1585 (match_operand:SI 2 "arith_operand" "I")))]
1586 "(INTVAL (operands[2]) == 1)"
1588 [(set_attr "type" "arith")
1589 (set_attr "mode" "SI")
1590 (set_attr "length" "4")]
1593 ;; Barrel shift right logical
1594 (define_insn "*lshrsi3_bshift"
1595 [(set (match_operand:SI 0 "register_operand" "=d,d")
1596 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d,d")
1597 (match_operand:SI 2 "arith_operand" "I,d")))]
1598 "TARGET_BARREL_SHIFT"
1602 [(set_attr "type" "bshift,bshift")
1603 (set_attr "mode" "SI,SI")
1604 (set_attr "length" "4,4")]
1607 (define_insn "*lshrsi_inline"
1608 [(set (match_operand:SI 0 "register_operand" "=&d")
1609 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d")
1610 (match_operand:SI 2 "immediate_operand" "I")))]
1614 int nshift = INTVAL (operands[2]);
1615 if (REGNO (operands[0]) != REGNO (operands[1]))
1616 output_asm_insn ("addk\t%0,r0,%1", operands);
1617 output_asm_insn ("srl\t%0,%1", operands);
1618 for (i = 0; i < (nshift - 2); i++)
1619 output_asm_insn ("srl\t%0,%0", operands);
1620 return "srl\t%0,%0";
1622 [(set_attr "type" "multi")
1623 (set_attr "mode" "SI")
1624 (set_attr "length" "124")]
1627 (define_insn "*lshlri_reg"
1628 [(set (match_operand:SI 0 "register_operand" "=&d")
1629 (lshiftrt:SI (match_operand:SI 1 "register_operand" "d")
1630 (match_operand:SI 2 "register_operand" "d")))]
1633 operands[3] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
1634 output_asm_insn ("andi\t%3,%2,31", operands);
1635 if (REGNO (operands[0]) != REGNO (operands[1]))
1636 output_asm_insn ("addk\t%0,r0,%1", operands);
1637 /* Exit the loop if zero shift. */
1638 output_asm_insn ("beqid\t%3,.+20", operands);
1639 /* Emit the loop. */
1640 output_asm_insn ("addk\t%0,%0,r0", operands);
1641 output_asm_insn ("addik\t%3,%3,-1", operands);
1642 output_asm_insn ("bneid\t%3,.-4", operands);
1643 return "srl\t%0,%0";
1645 [(set_attr "type" "multi")
1646 (set_attr "mode" "SI")
1647 (set_attr "length" "28")]
1650 ;;----------------------------------------------------------------
1651 ;; Setting a register from an integer comparison.
1652 ;;----------------------------------------------------------------
1653 (define_expand "cstoresi4"
1654 [(set (match_operand:SI 0 "register_operand")
1655 (match_operator:SI 1 "ordered_comparison_operator"
1656 [(match_operand:SI 2 "register_operand")
1657 (match_operand:SI 3 "register_operand")]))]
1658 "TARGET_PATTERN_COMPARE"
1659 "if (GET_CODE (operand1) != EQ && GET_CODE (operand1) != NE)
1664 (define_insn "seq_internal_pat"
1665 [(set (match_operand:SI 0 "register_operand" "=d")
1667 (match_operand:SI 1 "register_operand" "d")
1668 (match_operand:SI 2 "register_operand" "d")))]
1669 "TARGET_PATTERN_COMPARE"
1671 [(set_attr "type" "arith")
1672 (set_attr "mode" "SI")
1673 (set_attr "length" "4")]
1676 (define_insn "sne_internal_pat"
1677 [(set (match_operand:SI 0 "register_operand" "=d")
1679 (match_operand:SI 1 "register_operand" "d")
1680 (match_operand:SI 2 "register_operand" "d")))]
1681 "TARGET_PATTERN_COMPARE"
1683 [(set_attr "type" "arith")
1684 (set_attr "mode" "SI")
1685 (set_attr "length" "4")]
1688 (define_insn "signed_compare"
1689 [(set (match_operand:SI 0 "register_operand" "=d")
1691 [(match_operand:SI 1 "register_operand" "d")
1692 (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))]
1695 [(set_attr "type" "arith")
1696 (set_attr "mode" "SI")
1697 (set_attr "length" "4")])
1699 (define_insn "unsigned_compare"
1700 [(set (match_operand:SI 0 "register_operand" "=d")
1702 [(match_operand:SI 1 "register_operand" "d")
1703 (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))]
1706 [(set_attr "type" "arith")
1707 (set_attr "mode" "SI")
1708 (set_attr "length" "4")])
1710 ;;----------------------------------------------------------------
1711 ;; Setting a register from an floating point comparison.
1712 ;;----------------------------------------------------------------
1713 (define_insn "cstoresf4"
1714 [(set (match_operand:SI 0 "register_operand")
1715 (match_operator:SI 1 "ordered_comparison_operator"
1716 [(match_operand:SF 2 "register_operand")
1717 (match_operand:SF 3 "register_operand")]))]
1719 "fcmp.%C1\t%0,%3,%2"
1720 [(set_attr "type" "fcmp")
1721 (set_attr "mode" "SF")
1722 (set_attr "length" "4")]
1725 ;;----------------------------------------------------------------
1726 ;; Conditional branches
1727 ;;----------------------------------------------------------------
1729 (define_expand "cbranchsi4"
1731 (if_then_else (match_operator 0 "ordered_comparison_operator"
1732 [(match_operand:SI 1 "register_operand")
1733 (match_operand:SI 2 "arith_operand")])
1734 (label_ref (match_operand 3 ""))
1738 microblaze_expand_conditional_branch (SImode, operands);
1742 (define_expand "cbranchsf4"
1744 (if_then_else (match_operator:SI 0 "ordered_comparison_operator"
1745 [(match_operand:SF 1 "register_operand")
1746 (match_operand:SF 2 "register_operand")])
1747 (label_ref (match_operand 3 ""))
1751 microblaze_expand_conditional_branch_sf (operands);
1756 ;; Used to implement comparison instructions
1757 (define_expand "condjump"
1759 (if_then_else (match_operand 0)
1760 (label_ref (match_operand 1))
1763 (define_insn "branch_zero"
1765 (if_then_else (match_operator:SI 0 "ordered_comparison_operator"
1766 [(match_operand:SI 1 "register_operand" "d")
1768 (match_operand:SI 2 "pc_or_label_operand" "")
1769 (match_operand:SI 3 "pc_or_label_operand" "")))
1773 if (operands[3] == pc_rtx)
1774 return "b%C0i%?\t%z1,%2";
1776 return "b%N0i%?\t%z1,%3";
1778 [(set_attr "type" "branch")
1779 (set_attr "mode" "none")
1780 (set_attr "length" "4")]
1783 ;;----------------------------------------------------------------
1784 ;; Unconditional branches
1785 ;;----------------------------------------------------------------
1788 (label_ref (match_operand 0 "" "")))]
1791 if (GET_CODE (operands[0]) == REG)
1794 return "bri%?\t%l0";
1796 [(set_attr "type" "jump")
1797 (set_attr "mode" "none")
1798 (set_attr "length" "4")])
1800 (define_expand "indirect_jump"
1801 [(set (pc) (match_operand 0 "register_operand" "d"))]
1804 rtx dest = operands[0];
1805 if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode)
1806 operands[0] = copy_to_mode_reg (Pmode, dest);
1808 emit_jump_insn (gen_indirect_jump_internal1 (operands[0]));
1813 ;; Indirect jumps. Jump to register values. Assuming absolute jumps
1815 (define_insn "indirect_jump_internal1"
1816 [(set (pc) (match_operand:SI 0 "register_operand" "d"))]
1819 [(set_attr "type" "jump")
1820 (set_attr "mode" "none")
1821 (set_attr "length" "4")])
1823 (define_expand "tablejump"
1825 (match_operand 0 "register_operand" "d"))
1826 (use (label_ref (match_operand 1 "" "")))]
1829 gcc_assert (GET_MODE (operands[0]) == Pmode);
1832 emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1]));
1834 emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1]));
1839 (define_insn "tablejump_internal1"
1841 (match_operand:SI 0 "register_operand" "d"))
1842 (use (label_ref (match_operand 1 "" "")))]
1845 [(set_attr "type" "jump")
1846 (set_attr "mode" "none")
1847 (set_attr "length" "4")])
1849 (define_expand "tablejump_internal3"
1850 [(parallel [(set (pc)
1851 (plus:SI (match_operand:SI 0 "register_operand" "d")
1852 (label_ref:SI (match_operand:SI 1 "" ""))))
1853 (use (label_ref:SI (match_dup 1)))])]
1858 ;; need to change for MicroBlaze PIC
1861 (plus:SI (match_operand:SI 0 "register_operand" "d")
1862 (label_ref:SI (match_operand 1 "" ""))))
1863 (use (label_ref:SI (match_dup 1)))]
1864 "next_active_insn (insn) != 0
1865 && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC
1866 && PREV_INSN (next_active_insn (insn)) == operands[1]
1869 output_asm_insn ("addk\t%0,%0,r20",operands);
1872 [(set_attr "type" "jump")
1873 (set_attr "mode" "none")
1874 (set_attr "length" "4")])
1876 (define_expand "tablejump_internal4"
1877 [(parallel [(set (pc)
1878 (plus:DI (match_operand:DI 0 "register_operand" "d")
1879 (label_ref:DI (match_operand:SI 1 "" ""))))
1880 (use (label_ref:DI (match_dup 1)))])]
1885 ;;----------------------------------------------------------------
1886 ;; Function prologue/epilogue and stack allocation
1887 ;;----------------------------------------------------------------
1888 (define_expand "prologue"
1892 microblaze_expand_prologue ();
1897 (define_expand "epilogue"
1898 [(use (const_int 0))]
1901 microblaze_expand_epilogue ();
1906 ;; An insn to allocate new stack space for dynamic use (e.g., alloca).
1907 ;; We copy the return address, decrement the stack pointer and save the
1908 ;; return address again at the new stack top
1910 (define_expand "allocate_stack"
1911 [(set (match_operand 0 "register_operand" "=r")
1912 (minus (reg 1) (match_operand 1 "register_operand" "")))
1914 (minus (reg 1) (match_dup 1)))]
1917 rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
1918 rtx rtmp = gen_rtx_REG (SImode, R_TMP);
1921 emit_move_insn (rtmp, retaddr);
1922 if (GET_CODE (operands[1]) != CONST_INT)
1924 neg_op0 = gen_reg_rtx (Pmode);
1925 emit_insn (gen_negsi2 (neg_op0, operands[1]));
1927 neg_op0 = GEN_INT (- INTVAL (operands[1]));
1929 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, neg_op0));
1930 emit_move_insn (gen_rtx_MEM (Pmode, stack_pointer_rtx), rtmp);
1931 emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
1932 emit_insn (gen_rtx_CLOBBER (SImode, rtmp));
1937 ;; Trivial return. Make it look like a normal return insn as that
1938 ;; allows jump optimizations to work better .
1939 (define_insn "return"
1941 "microblaze_can_use_return_insn ()"
1943 if (microblaze_is_interrupt_handler ())
1944 return "rtid\tr14, 0\;%#";
1946 return "rtsd\tr15, 8\;%#";
1948 [(set_attr "type" "jump")
1949 (set_attr "mode" "none")
1950 (set_attr "length" "4")])
1953 ;; We match any mode for the return address, so that this will work with
1954 ;; both 32 bit and 64 bit targets.
1956 (define_insn "return_internal"
1957 [(parallel [(use (match_operand:SI 0 "register_operand" ""))
1961 if (microblaze_is_interrupt_handler ())
1962 return "rtid\tr14,0 \;%#";
1964 return "rtsd\tr15,8 \;%#";
1966 [(set_attr "type" "jump")
1967 (set_attr "mode" "none")
1968 (set_attr "length" "4")])
1971 ;; Block any insns from across this point
1972 ;; Useful to group sequences together.
1973 (define_insn "blockage"
1974 [(unspec_volatile [(const_int 0)] 0)]
1977 [(set_attr "type" "unknown")
1978 (set_attr "mode" "none")
1979 (set_attr "length" "0")])
1982 ;;----------------------------------------------------------------
1984 ;;----------------------------------------------------------------
1986 (define_expand "call"
1987 [(parallel [(call (match_operand 0 "memory_operand" "m")
1988 (match_operand 1 "" "i"))
1989 (clobber (reg:SI R_SR))
1990 (use (match_operand 2 "" ""))
1991 (use (match_operand 3 "" ""))])]
1994 rtx addr = XEXP (operands[0], 0);
1996 if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF
1997 && !SYMBOL_REF_LOCAL_P (addr))
1999 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
2000 XEXP (operands[0], 0) = temp;
2003 if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
2004 || !call_insn_operand (addr, VOIDmode))
2005 XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr);
2007 if (GET_CODE (XEXP (operands[0], 0)) == UNSPEC)
2008 emit_call_insn (gen_call_internal_plt0 (operands[0], operands[1],
2009 gen_rtx_REG (SImode,
2010 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
2011 pic_offset_table_rtx));
2013 emit_call_insn (gen_call_internal0 (operands[0], operands[1],
2014 gen_rtx_REG (SImode,
2015 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2021 (define_expand "call_internal0"
2022 [(parallel [(call (match_operand 0 "" "")
2023 (match_operand 1 "" ""))
2024 (clobber (match_operand:SI 2 "" ""))])]
2030 (define_expand "call_internal_plt0"
2031 [(parallel [(call (match_operand 0 "" "")
2032 (match_operand 1 "" ""))
2033 (clobber (match_operand:SI 2 "" ""))
2034 (use (match_operand:SI 3 "" ""))])]
2040 (define_insn "call_internal_plt"
2041 [(call (mem (match_operand:SI 0 "call_insn_plt_operand" ""))
2042 (match_operand:SI 1 "" "i"))
2043 (clobber (reg:SI R_SR))
2044 (use (reg:SI R_GOT))]
2047 register rtx target2 = gen_rtx_REG (Pmode,
2048 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2049 gen_rtx_CLOBBER (VOIDmode, target2);
2050 return "brlid\tr15,%0\;%#";
2052 [(set_attr "type" "call")
2053 (set_attr "mode" "none")
2054 (set_attr "length" "4")])
2056 (define_insn "call_internal1"
2057 [(call (mem (match_operand:SI 0 "call_insn_operand" "ri"))
2058 (match_operand:SI 1 "" "i"))
2059 (clobber (reg:SI R_SR))]
2062 register rtx target = operands[0];
2063 register rtx target2 = gen_rtx_REG (Pmode,
2064 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2065 if (GET_CODE (target) == SYMBOL_REF) {
2066 gen_rtx_CLOBBER (VOIDmode, target2);
2067 return "brlid\tr15,%0\;%#";
2068 } else if (GET_CODE (target) == CONST_INT)
2069 return "la\t%@,r0,%0\;brald\tr15,%@\;%#";
2070 else if (GET_CODE (target) == REG)
2071 return "brald\tr15,%0\;%#";
2073 fprintf (stderr,"Unsupported call insn\n");
2077 [(set_attr "type" "call")
2078 (set_attr "mode" "none")
2079 (set_attr "length" "4")])
2081 ;; calls.c now passes a fourth argument, make saber happy
2083 (define_expand "call_value"
2084 [(parallel [(set (match_operand 0 "register_operand" "=d")
2085 (call (match_operand 1 "memory_operand" "m")
2086 (match_operand 2 "" "i")))
2087 (clobber (reg:SI R_SR))
2088 (use (match_operand 3 "" ""))])] ;; next_arg_reg
2091 rtx addr = XEXP (operands[1], 0);
2093 if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF
2094 && !SYMBOL_REF_LOCAL_P (addr))
2096 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
2097 XEXP (operands[1], 0) = temp;
2100 if ((GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr))
2101 || !call_insn_operand (addr, VOIDmode))
2102 XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);
2104 if (GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
2105 emit_call_insn (gen_call_value_intern_plt0 (operands[0], operands[1],
2107 gen_rtx_REG (SImode,
2108 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
2109 pic_offset_table_rtx));
2111 emit_call_insn (gen_call_value_internal (operands[0], operands[1],
2113 gen_rtx_REG (SImode,
2114 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
2121 (define_expand "call_value_internal"
2122 [(parallel [(set (match_operand 0 "" "")
2123 (call (match_operand 1 "" "")
2124 (match_operand 2 "" "")))
2125 (clobber (match_operand:SI 3 "" ""))
2131 (define_expand "call_value_intern_plt0"
2132 [(parallel[(set (match_operand 0 "" "")
2133 (call (match_operand 1 "" "")
2134 (match_operand 2 "" "")))
2135 (clobber (match_operand:SI 3 "" ""))
2136 (use (match_operand:SI 4 "" ""))])]
2141 (define_insn "call_value_intern_plt"
2142 [(set (match_operand:VOID 0 "register_operand" "=d")
2143 (call (mem (match_operand:SI 1 "call_insn_plt_operand" ""))
2144 (match_operand:SI 2 "" "i")))
2145 (clobber (match_operand:SI 3 "register_operand" "=d"))
2146 (use (match_operand:SI 4 "register_operand"))]
2149 register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2151 gen_rtx_CLOBBER (VOIDmode,target2);
2152 return "brlid\tr15,%1\;%#";
2154 [(set_attr "type" "call")
2155 (set_attr "mode" "none")
2156 (set_attr "length" "4")])
2158 (define_insn "call_value_intern"
2159 [(set (match_operand:VOID 0 "register_operand" "=d")
2160 (call (mem (match_operand:VOID 1 "call_insn_operand" "ri"))
2161 (match_operand:SI 2 "" "i")))
2162 (clobber (match_operand:SI 3 "register_operand" "=d"))]
2165 register rtx target = operands[1];
2166 register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
2168 if (GET_CODE (target) == SYMBOL_REF){
2169 gen_rtx_CLOBBER (VOIDmode,target2);
2170 return "brlid\tr15,%1\;%#";
2172 else if (GET_CODE (target) == CONST_INT)
2173 return "la\t%@,r0,%1\;brald\tr15,%@\;%#";
2174 else if (GET_CODE (target) == REG)
2175 return "brald\tr15,%1\;%#";
2177 return "Unsupported call insn\n";
2179 [(set_attr "type" "call")
2180 (set_attr "mode" "none")
2181 (set_attr "length" "4")])
2184 ;; Call subroutine returning any type.
2185 (define_expand "untyped_call"
2186 [(parallel [(call (match_operand 0 "" "")
2188 (match_operand 1 "" "")
2189 (match_operand 2 "" "")])]
2192 if (operands[0]) /* silence statement not reached warnings */
2196 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2198 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2200 rtx set = XVECEXP (operands[2], 0, i);
2201 emit_move_insn (SET_DEST (set), SET_SRC (set));
2204 emit_insn (gen_blockage ());
2210 ;;----------------------------------------------------------------
2212 ;;----------------------------------------------------------------
2218 [(set_attr "type" "nop")
2219 (set_attr "mode" "none")
2220 (set_attr "length" "4")])
2222 ;; The insn to set GOT. The hardcoded number "8" accounts for $pc difference
2223 ;; between "mfs" and "addik" instructions.
2224 (define_insn "set_got"
2225 [(set (match_operand:SI 0 "register_operand" "=r")
2226 (unspec:SI [(const_int 0)] UNSPEC_SET_GOT))]
2228 "mfs\t%0,rpc\n\taddik\t%0,%0,_GLOBAL_OFFSET_TABLE_+8"
2229 [(set_attr "type" "multi")
2230 (set_attr "length" "12")])