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)
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
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" [
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)
79 ;; bshift Shift operations
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 ;;----------------------------------------------------------------
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
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
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
184 oneof = oneof "|" allof
187 allof = allof "+" repeat
190 repeat = element "*" number
193 element = cpu_function_name
199 1. "," is used for describing start of the next cycle in
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 ;;----------------------------------------------------------------
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)))
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)))
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)))
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)))
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)))
323 (define_insn_reservation "mb3-div" 34
324 (and (eq_attr "type" "idiv")
325 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
328 (define_insn_reservation "mb3-bs" 2
329 (and (eq_attr "type" "bshift")
330 (eq (symbol_ref "microblaze_pipe") (const_int MB_PIPE_3)))
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)))
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)))
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)))
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)))
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)))
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")))]
369 (define_insn "bswaphi2"
370 [(set (match_operand:HI 0 "register_operand" "=r")
371 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
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")
388 ;;----------------------------------------------------------------
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")))]
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")))]
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")))]
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")))]
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"
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"
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"
456 [(set_attr "type" "fcvt")
457 (set_attr "mode" "SF")
458 (set_attr "length" "4")])
460 ;;----------------------------------------------------------------
462 ;;----------------------------------------------------------------
464 ;; Add 2 SImode integers [ src1 = reg ; src2 = arith ; dest = reg ]
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")))]
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")))]
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 ;;----------------------------------------------------------------
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")))]
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)))]
521 operands[2] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
522 return "mfs\t%2,rpc\n\twic\t%2,r0";
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")))]
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 ;;----------------------------------------------------------------
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")))]
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")
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")
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")
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")
597 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
598 (sign_extend:DI (match_operand:SI 2 "register_operand" "d")))
600 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
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")
610 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
611 (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))
614 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
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")
624 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
625 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))
628 "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
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")))
643 "(!TARGET_SOFT_DIV) || (TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)"
645 if (TARGET_SOFT_DIV && TARGET_BARREL_SHIFT && TARGET_SMALL_DIVIDES)
647 microblaze_expand_divide (operands);
650 else if (!TARGET_SOFT_DIV)
652 emit_insn (gen_divsi3_internal (operands[0], operands[1], operands[2]));
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")))
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")))
678 [(set_attr "type" "idiv")
679 (set_attr "mode" "SI")
680 (set_attr "length" "4")])
683 [(set (match_operand:SI 0 "register_operand")
684 (fix:SI (match_operand:SF 1 "register_operand")))
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))
692 [(set (match_dup 1) (match_dup 3))]
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]));
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")))]
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")))]
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")))]
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")))]
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")]
751 [(set (match_operand:DI 0 "register_operand" "")
752 (not:DI (match_operand:DI 1 "register_operand" "")))]
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)))]
762 ;;----------------------------------------------------------------
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")))]
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")))]
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")))]
804 [(set_attr "type" "arith,arith,no_delay_arith")
805 (set_attr "mode" "SI,SI,SI")
806 (set_attr "length" "4,8,8")])
808 ;;----------------------------------------------------------------
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")))]
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")))]
832 [(set_attr "type" "arith,load,no_delay_load")
833 (set_attr "mode" "HI")
834 (set_attr "length" "4,4,8")])
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")))]
844 [(set_attr "type" "arith,load,no_delay_load")
845 (set_attr "mode" "SI,SI,SI")
846 (set_attr "length" "4,4,8")])
848 ;;----------------------------------------------------------------
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")))]
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")))]
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")))]
880 if (which_alternative == 0)
881 output_asm_insn ("addk\t%L0,r0,%1", operands);
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";
890 [(set_attr "type" "multi,multi,multi")
891 (set_attr "mode" "DI")
892 (set_attr "length" "20,20,20")])
894 ;;----------------------------------------------------------------
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" ""))]
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]))
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));
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))))
927 rtx temp = force_reg (DImode, operands[1]);
928 emit_move_insn (operands[0], temp);
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"))]
941 switch (which_alternative)
944 return "addk\t%0,%1\n\taddk\t%D0,%d1";
946 return "addik\t%M0,r0,%h1\n\taddik\t%L0,r0,%j1 #li => la";
948 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";
951 if (reg_mentioned_p (operands[0], operands[1]))
952 return "lwi\t%D0,%o1\n\tlwi\t%0,%1";
954 return "lwi\t%0,%1\n\tlwi\t%D0,%o1";
957 return "swi\t%1,%0\n\tswi\t%D1,%o0";
959 return "unreachable";
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")])
966 [(set (match_operand:DI 0 "register_operand" "")
967 (match_operand:DI 1 "register_operand" ""))]
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))]
978 [(set (match_operand:DI 0 "register_operand" "")
979 (match_operand:DI 1 "register_operand" ""))]
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))]
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" ""))]
998 if (microblaze_expand_move (SImode, operands)) DONE;
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 ()"
1009 addk\t%0,%1,r0 #add movsi
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)))"
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]))"
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"))]
1049 addik\t%0,r0,%1\t# %X1
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" ""))]
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)))
1078 rtx temp = force_reg (HImode, operands[1]);
1079 emit_move_insn (operands[0], temp);
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"))]
1090 addik\t%0,r0,%1\t# %X1
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" ""))]
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)))
1118 rtx temp = force_reg (QImode, operands[1]);
1119 emit_move_insn (operands[0], temp);
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"))]
1131 addik\t%0,r0,%1\t# %X1
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"))])]
1154 if (microblaze_expand_block_move (operands[0], operands[1],
1155 operands[2], operands[3]))
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")))]
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" ""))]
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))))
1187 rtx temp = force_reg (SFmode, operands[1]);
1188 emit_move_insn (operands[0], temp);
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))"
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" ""))]
1220 if (flag_pic == 2) {
1221 if (GET_CODE (operands[1]) == MEM
1222 && !microblaze_legitimate_address_p (DFmode, XEXP (operands[1],0), 0))
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);
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))))
1238 rtx temp = force_reg (DFmode, operands[1]);
1239 emit_move_insn (operands[0], temp);
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"))]
1253 switch (which_alternative)
1256 return "addk\t%0,r0,r0\n\taddk\t%D0,r0,r0";
1259 if (reg_mentioned_p (operands[0], operands[1]))
1260 return "lwi\t%D0,%o1\n\tlwi\t%0,%1";
1262 return "lwi\t%0,%1\n\tlwi\t%D0,%o1";
1265 return "addik\t%0,r0,%h1 \n\taddik\t%D0,r0,%j1 #Xfer Lo";
1268 return "swi\t%1,%0\n\tswi\t%D1,%o0";
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")])
1277 [(set (match_operand:DF 0 "register_operand" "")
1278 (match_operand:DF 1 "register_operand" ""))]
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))]
1288 [(set (match_operand:DF 0 "register_operand" "")
1289 (match_operand:DF 1 "register_operand" ""))]
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))]
1298 ;;----------------------------------------------------------------
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" "")))]
1311 /* Avoid recursion for trivial cases. */
1312 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1313 if (microblaze_expand_shift (operands))
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)"
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"
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")))]
1354 && ((1 << INTVAL (operands[2])) <= 32767 && (1 << INTVAL (operands[2])) >= -32768)"
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")))]
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)"
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";
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)"
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";
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")))]
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";
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")))]
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";
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" "")))]
1472 /* Avoid recursion for trivial cases. */
1473 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1474 if (microblaze_expand_shift (operands))
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)"
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"
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")))]
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";
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")))]
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";
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" "")))]
1561 /* Avoid recursion for trivial cases. */
1562 if (!((GET_CODE (operands [2]) == CONST_INT) && (INTVAL (operands[2]) == 1)))
1563 if (microblaze_expand_shift (operands))
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)"
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"
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")))]
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";
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")))]
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";
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)
1654 (define_insn "seq_internal_pat"
1655 [(set (match_operand:SI 0 "register_operand" "=d")
1657 (match_operand:SI 1 "register_operand" "d")
1658 (match_operand:SI 2 "register_operand" "d")))]
1659 "TARGET_PATTERN_COMPARE"
1661 [(set_attr "type" "arith")
1662 (set_attr "mode" "SI")
1663 (set_attr "length" "4")]
1666 (define_insn "sne_internal_pat"
1667 [(set (match_operand:SI 0 "register_operand" "=d")
1669 (match_operand:SI 1 "register_operand" "d")
1670 (match_operand:SI 2 "register_operand" "d")))]
1671 "TARGET_PATTERN_COMPARE"
1673 [(set_attr "type" "arith")
1674 (set_attr "mode" "SI")
1675 (set_attr "length" "4")]
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")]))]
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"
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 ""))
1706 microblaze_expand_conditional_branch (SImode, operands);
1710 (define_expand "cbranchsi4_reg"
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 ""))
1719 microblaze_expand_conditional_branch_reg (SImode, operands);
1723 (define_expand "cbranchsf4"
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 ""))
1732 microblaze_expand_conditional_branch_sf (operands);
1737 ;; Used to implement comparison instructions
1738 (define_expand "condjump"
1740 (if_then_else (match_operand 0)
1741 (label_ref (match_operand 1))
1744 (define_insn "branch_zero"
1746 (if_then_else (match_operator:SI 0 "ordered_comparison_operator"
1747 [(match_operand:SI 1 "register_operand" "d")
1749 (match_operand:SI 2 "pc_or_label_operand" "")
1750 (match_operand:SI 3 "pc_or_label_operand" "")))
1754 if (operands[3] == pc_rtx)
1755 return "b%C0i%?\t%z1,%2";
1757 return "b%N0i%?\t%z1,%3";
1759 [(set_attr "type" "branch")
1760 (set_attr "mode" "none")
1761 (set_attr "length" "4")]
1764 (define_insn "branch_compare"
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")
1770 (label_ref (match_operand 3))
1772 (clobber(reg:SI R_TMP))]
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)
1780 output_asm_insn ("cmp\tr18,%z1,%z2", operands);
1781 code = swap_condition (code);
1783 else if (code == GTU || code == LEU)
1785 output_asm_insn ("cmpu\tr18,%z1,%z2", operands);
1786 code = swap_condition (code);
1788 else if (code == GE || code == LT)
1790 output_asm_insn ("cmp\tr18,%z2,%z1", operands);
1792 else if (code == GEU || code == LTU)
1794 output_asm_insn ("cmpu\tr18,%z2,%z1", operands);
1797 operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx);
1798 return "b%C0i%?\tr18,%3";
1800 [(set_attr "type" "branch")
1801 (set_attr "mode" "none")
1802 (set_attr "length" "12")]
1805 ;;----------------------------------------------------------------
1806 ;; Unconditional branches
1807 ;;----------------------------------------------------------------
1810 (label_ref (match_operand 0 "" "")))]
1813 if (GET_CODE (operands[0]) == REG)
1816 return "bri%?\t%l0";
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"))]
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]));
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"))]
1841 [(set_attr "type" "jump")
1842 (set_attr "mode" "none")
1843 (set_attr "length" "4")])
1845 (define_expand "tablejump"
1847 (match_operand 0 "register_operand" "d"))
1848 (use (label_ref (match_operand 1 "" "")))]
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]));
1856 emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1]));
1861 (define_insn "tablejump_internal1"
1863 (match_operand:SI 0 "register_operand" "d"))
1864 (use (label_ref (match_operand 1 "" "")))]
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)))])]
1880 ;; need to change for MicroBlaze PIC
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
1890 output_asm_insn ("addk\t%0,%0,r20",operands);
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)))])]
1906 ;;----------------------------------------------------------------
1907 ;; Function prologue/epilogue and stack allocation
1908 ;;----------------------------------------------------------------
1909 (define_expand "prologue"
1913 microblaze_expand_prologue ();
1918 (define_expand "epilogue"
1919 [(use (const_int 0))]
1922 microblaze_expand_epilogue ();
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" "")))
1935 (minus (reg 1) (match_dup 1)))]
1938 rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
1939 rtx rtmp = gen_rtx_REG (SImode, R_TMP);
1942 emit_move_insn (rtmp, retaddr);
1943 if (GET_CODE (operands[1]) != CONST_INT)
1945 neg_op0 = gen_reg_rtx (Pmode);
1946 emit_insn (gen_negsi2 (neg_op0, operands[1]));
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));
1958 (define_expand "save_stack_block"
1959 [(match_operand 0 "register_operand" "")
1960 (match_operand 1 "register_operand" "")]
1963 emit_move_insn (operands[0], operands[1]);
1968 (define_expand "restore_stack_block"
1969 [(match_operand 0 "register_operand" "")
1970 (match_operand 1 "register_operand" "")]
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);
1984 ;; Trivial return. Make it look like a normal return insn as that
1985 ;; allows jump optimizations to work better .
1986 (define_expand "return"
1988 "microblaze_can_use_return_insn ()"
1992 (define_expand "simple_return"
1998 (define_insn "*<optab>"
2002 if (microblaze_is_break_handler ())
2003 return "rtbd\tr16, 8\;%#";
2004 else if (microblaze_is_interrupt_variant ())
2005 return "rtid\tr14, 0\;%#";
2007 return "rtsd\tr15, 8\;%#";
2009 [(set_attr "type" "jump")
2010 (set_attr "mode" "none")
2011 (set_attr "length" "4")]
2016 (define_insn "<optab>_internal"
2018 (use (match_operand:SI 0 "register_operand" ""))]
2021 if (microblaze_is_break_handler ())
2022 return "rtbd\tr16,8\;%#";
2023 else if (microblaze_is_interrupt_variant ())
2024 return "rtid\tr14,0 \;%#";
2026 return "rtsd\tr15,8 \;%#";
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)]
2039 [(set_attr "type" "unknown")
2040 (set_attr "mode" "none")
2041 (set_attr "length" "0")])
2044 ;;----------------------------------------------------------------
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 "" ""))])]
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))
2062 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
2063 XEXP (operands[0], 0) = temp;
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));
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)));
2084 (define_expand "call_internal0"
2085 [(parallel [(call (match_operand 0 "" "")
2086 (match_operand 1 "" ""))
2087 (clobber (match_operand:SI 2 "" ""))])]
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 "" ""))])]
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))]
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\;%#";
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))]
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\;%#";
2134 gen_rtx_CLOBBER (VOIDmode, target2);
2135 return "brlid\tr15,%0\;%#";
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\;%#";
2142 fprintf (stderr,"Unsupported call insn\n");
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
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))
2166 rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
2167 XEXP (operands[1], 0) = temp;
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],
2177 gen_rtx_REG (SImode,
2178 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
2179 pic_offset_table_rtx));
2181 emit_call_insn (gen_call_value_internal (operands[0], operands[1],
2183 gen_rtx_REG (SImode,
2184 GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
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 "" ""))
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 "" ""))])]
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"))]
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\;%#";
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"))]
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)
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)
2245 return "brlid\tr15,%1\;%#";
2249 return "bralid\tr15,%1\;%#";
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\;%#";
2257 return "Unsupported call insn\n";
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 "" "")
2268 (match_operand 1 "" "")
2269 (match_operand 2 "" "")])]
2272 if (operands[0]) /* silence statement not reached warnings */
2276 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
2278 for (i = 0; i < XVECLEN (operands[2], 0); i++)
2280 rtx set = XVECEXP (operands[2], 0, i);
2281 emit_move_insn (SET_DEST (set), SET_SRC (set));
2284 emit_insn (gen_blockage ());
2290 ;;----------------------------------------------------------------
2292 ;;----------------------------------------------------------------
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
2304 [(trap_if (const_int 1) (const_int 0))]
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))]
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))]
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")))]
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" ""))]
2349 microblaze_eh_return (operands[0]);