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