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