1 ;; Machine description of Andes NDS32 cpu for GNU compiler
2 ;; Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 ;; Contributed by Andes Technology Corporation.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 ;; License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
23 ;; Include predicates definition.
24 (include "predicates.md")
26 ;; Include constraints definition.
27 (include "constraints.md")
29 ;; Include iterators definition.
30 (include "iterators.md")
32 ;; Include pipelines definition.
33 (include "pipelines.md")
36 ;; Include constants definition.
37 (include "constants.md")
40 ;; Include intrinsic functions definition.
41 (include "nds32-intrinsic.md")
43 ;; Include block move for nds32 multiple load/store behavior.
44 (include "nds32-multiple.md")
46 ;; Include DImode/DFmode operations.
47 (include "nds32-doubleword.md")
49 ;; Include floating-point patterns.
50 (include "nds32-fpu.md")
52 ;; Include peephole patterns.
53 (include "nds32-peephole2.md")
56 ;; ------------------------------------------------------------------------
58 ;; CPU pipeline model.
59 (define_attr "pipeline_model" "n7,n8,e8,n9,simple"
61 (cond [(match_test "nds32_cpu_option == CPU_N7") (const_string "n7")
62 (match_test "nds32_cpu_option == CPU_E8") (const_string "e8")
63 (match_test "nds32_cpu_option == CPU_N6 || nds32_cpu_option == CPU_N8") (const_string "n8")
64 (match_test "nds32_cpu_option == CPU_N9") (const_string "n9")
65 (match_test "nds32_cpu_option == CPU_SIMPLE") (const_string "simple")]
66 (const_string "n9"))))
68 ;; Insn type, it is used to default other attribute values.
70 "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\
71 falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore"
72 (const_string "unknown"))
75 (define_attr "subtype"
77 (const_string "simple"))
79 ;; Length, in bytes, default is 4-bytes.
80 (define_attr "length" "" (const_int 4))
82 ;; Indicate the amount of micro instructions.
84 "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25"
87 ;; Insn in which feature set, it is used to enable/disable insn alternatives.
88 ;; v1 : Baseline Instructions
89 ;; v2 : Baseline Version 2 Instructions
90 ;; v3m : Baseline Version 3m Instructions
91 ;; v3 : Baseline Version 3 Instructions
92 ;; pe1 : Performance Extension Instructions
93 ;; pe2 : Performance Extension Version 2 Instructions
94 ;; se : String Extension instructions
95 (define_attr "feature"
96 "v1,v2,v3m,v3,pe1,pe2,se,fpu"
99 ;; Enabled, which is used to enable/disable insn alternatives.
100 ;; Note that we use length and TARGET_16_BIT here as criteria.
101 ;; If the instruction pattern already check TARGET_16_BIT to determine
102 ;; the length by itself, its enabled attribute should be customized to
103 ;; avoid the conflict between length attribute and this default setting.
104 (define_attr "enabled" "no,yes"
106 (and (eq_attr "length" "2")
107 (match_test "!TARGET_16_BIT"))
109 (cond [(eq_attr "feature" "v1") (const_string "yes")
110 (eq_attr "feature" "v2") (if_then_else (match_test "TARGET_ISA_V2 || TARGET_ISA_V3 || TARGET_ISA_V3M")
113 (eq_attr "feature" "v3") (if_then_else (match_test "TARGET_ISA_V3")
116 (eq_attr "feature" "v3m") (if_then_else (match_test "TARGET_ISA_V3 || TARGET_ISA_V3M")
119 (eq_attr "feature" "pe1") (if_then_else (match_test "TARGET_EXT_PERF")
122 (eq_attr "feature" "pe2") (if_then_else (match_test "TARGET_EXT_PERF2")
125 (eq_attr "feature" "se") (if_then_else (match_test "TARGET_EXT_STRING")
128 (eq_attr "feature" "fpu") (if_then_else (match_test "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE")
130 (const_string "no"))]
131 (const_string "yes"))))
134 ;; ----------------------------------------------------------------------------
137 ;; Move instructions.
139 ;; For QImode and HImode, the immediate value can be fit in imm20s.
140 ;; So there is no need to split rtx for QI and HI patterns.
142 (define_expand "mov<mode>"
143 [(set (match_operand:QIHI 0 "general_operand" "")
144 (match_operand:QIHI 1 "general_operand" ""))]
147 /* Need to force register if mem <- !reg. */
148 if (MEM_P (operands[0]) && !REG_P (operands[1]))
149 operands[1] = force_reg (<MODE>mode, operands[1]);
151 if (MEM_P (operands[1]) && optimize > 0)
153 rtx reg = gen_reg_rtx (SImode);
155 emit_insn (gen_zero_extend<mode>si2 (reg, operands[1]));
156 operands[1] = gen_lowpart (<MODE>mode, reg);
160 (define_expand "movmisalign<mode>"
161 [(set (match_operand:SIDI 0 "general_operand" "")
162 (match_operand:SIDI 1 "general_operand" ""))]
166 if (MEM_P (operands[0]) && !REG_P (operands[1]))
167 operands[1] = force_reg (<MODE>mode, operands[1]);
169 if (MEM_P (operands[0]))
171 addr = force_reg (Pmode, XEXP (operands[0], 0));
172 emit_insn (gen_unaligned_store<mode> (addr, operands[1]));
176 addr = force_reg (Pmode, XEXP (operands[1], 0));
177 emit_insn (gen_unaligned_load<mode> (operands[0], addr));
182 (define_expand "movsi"
183 [(set (match_operand:SI 0 "general_operand" "")
184 (match_operand:SI 1 "general_operand" ""))]
187 /* Need to force register if mem <- !reg. */
188 if (MEM_P (operands[0]) && !REG_P (operands[1]))
189 operands[1] = force_reg (SImode, operands[1]);
191 /* If operands[1] is a large constant and cannot be performed
192 by a single instruction, we need to split it. */
193 if (CONST_INT_P (operands[1])
194 && !satisfies_constraint_Is20 (operands[1])
195 && !satisfies_constraint_Ihig (operands[1]))
198 HOST_WIDE_INT low12_int;
201 tmp_rtx = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
203 high20_rtx = gen_int_mode ((INTVAL (operands[1]) >> 12) << 12, SImode);
204 low12_int = INTVAL (operands[1]) & 0xfff;
206 emit_move_insn (tmp_rtx, high20_rtx);
207 emit_move_insn (operands[0], plus_constant (SImode,
214 (define_insn "*mov<mode>"
215 [(set (match_operand:QIHISI 0 "nonimmediate_operand" "=r, r,U45,U33,U37,U45, m, l, l, l, d, d, r, d, r, r, r, *f, *f, r, *f, Q")
216 (match_operand:QIHISI 1 "nds32_move_operand" " r, r, l, l, l, d, r,U45,U33,U37,U45,Ufe, m,Ip05, Is05, Is20, Ihig, *f, r, *f, Q, *f"))]
217 "register_operand(operands[0], <MODE>mode)
218 || register_operand(operands[1], <MODE>mode)"
220 switch (which_alternative)
223 return "mov55\t%0, %1";
225 return "ori\t%0, %1, 0";
230 return nds32_output_16bit_store (operands, <byte>);
232 return nds32_output_32bit_store (operands, <byte>);
238 return nds32_output_16bit_load (operands, <byte>);
240 return nds32_output_32bit_load (operands, <byte>);
242 return "movpi45\t%0, %1";
244 return "movi55\t%0, %1";
246 return "movi\t%0, %1";
248 return "sethi\t%0, hi20(%1)";
250 if (TARGET_FPU_SINGLE)
251 return "fcpyss\t%0, %1, %1";
255 return "fmtsr\t%1, %0";
257 return "fmfsr\t%0, %1";
259 return nds32_output_float_load (operands);
261 return nds32_output_float_store (operands);
266 [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,load,alu,alu,alu,alu,fcpy,fmtsr,fmfsr,fload,fstore")
267 (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 2, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4")
268 (set_attr "feature" " v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v1, v3m, v1, v1, v1, v1, v1, fpu, fpu, fpu, fpu, fpu")])
271 ;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF
272 ;; are able to match such instruction template.
273 (define_insn "move_addr"
274 [(set (match_operand:SI 0 "register_operand" "=l, r")
275 (match_operand:SI 1 "nds32_symbolic_operand" " i, i"))]
278 [(set_attr "type" "alu")
279 (set_attr "length" "8")])
283 [(set (match_operand:SI 0 "register_operand" "=r")
284 (high:SI (match_operand:SI 1 "nds32_symbolic_operand" " i")))]
286 "sethi\t%0, hi20(%1)"
287 [(set_attr "type" "alu")
288 (set_attr "length" "4")])
291 (define_insn "lo_sum"
292 [(set (match_operand:SI 0 "register_operand" "=r")
293 (lo_sum:SI (match_operand:SI 1 "register_operand" " r")
294 (match_operand:SI 2 "nds32_symbolic_operand" " i")))]
296 "ori\t%0, %1, lo12(%2)"
297 [(set_attr "type" "alu")
298 (set_attr "length" "4")])
301 ;; ----------------------------------------------------------------------------
303 ;; Zero extension instructions.
305 (define_insn "zero_extend<mode>si2"
306 [(set (match_operand:SI 0 "register_operand" "=l, r, l, *r")
307 (zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, U33, m")))]
310 switch (which_alternative)
313 return "ze<size>33\t%0, %1";
315 return "ze<size>\t%0, %1";
317 return nds32_output_16bit_load (operands, <byte>);
319 return nds32_output_32bit_load (operands, <byte>);
325 [(set_attr "type" "alu,alu,load,load")
326 (set_attr "length" " 2, 4, 2, 4")])
329 ;; Sign extension instructions.
331 (define_insn "extend<mode>si2"
332 [(set (match_operand:SI 0 "register_operand" "=l, r, r")
333 (sign_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, m")))]
336 switch (which_alternative)
339 return "se<size>33\t%0, %1";
341 return "se<size>\t%0, %1";
343 return nds32_output_32bit_load_s (operands, <byte>);
349 [(set_attr "type" "alu,alu,load")
350 (set_attr "length" " 2, 4, 4")])
353 ;; ----------------------------------------------------------------------------
355 ;; Arithmetic instructions.
357 (define_insn "addsi3"
358 [(set (match_operand:SI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r")
359 (plus:SI (match_operand:SI 1 "register_operand" "% 0, l, 0, l, 0, l, 0, k, r, r")
360 (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,Iu06, Is15, r")))]
363 switch (which_alternative)
366 /* addi Rt4,Rt4,-x ==> subi45 Rt4,x
367 where 0 <= x <= 31 */
368 operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
369 return "subi45\t%0, %2";
371 /* addi Rt3,Ra3,-x ==> subi333 Rt3,Ra3,x
373 operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
374 return "subi333\t%0, %1, %2";
376 return "addi45\t%0, %2";
378 return "addi333\t%0, %1, %2";
380 return "add45\t%0, %2";
382 return "add333\t%0, %1, %2";
384 return "addi10.sp\t%2";
386 return "addri36.sp\t%0, %2";
388 return "addi\t%0, %1, %2";
390 return "add\t%0, %1, %2";
396 [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
397 (set_attr "length" " 2, 2, 2, 2, 2, 2, 2, 2, 4, 4")
398 (set_attr "feature" " v1, v1, v1, v1, v1, v1, v2, v1, v1, v1")])
400 (define_insn "subsi3"
401 [(set (match_operand:SI 0 "register_operand" "=d, l, r, r")
402 (minus:SI (match_operand:SI 1 "nds32_rimm15s_operand" " 0, l, Is15, r")
403 (match_operand:SI 2 "register_operand" " r, l, r, r")))]
410 [(set_attr "type" "alu,alu,alu,alu")
411 (set_attr "length" " 2, 2, 4, 4")])
414 ;; GCC intends to simplify (plus (ashift ...) (reg))
415 ;; into (plus (mult ...) (reg)), so our matching pattern takes 'mult'
416 ;; and needs to ensure it is exact_log2 value.
417 (define_insn "*add_slli"
418 [(set (match_operand:SI 0 "register_operand" "=r")
419 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
420 (match_operand:SI 2 "immediate_operand" " i"))
421 (match_operand:SI 3 "register_operand" " r")))]
422 "TARGET_ISA_V3 && optimize_size
423 && (exact_log2 (INTVAL (operands[2])) != -1)
424 && (exact_log2 (INTVAL (operands[2])) <= 31)"
426 /* Get floor_log2 of the immediate value
427 so that we can generate 'add_slli' instruction. */
428 operands[2] = GEN_INT (floor_log2 (INTVAL (operands[2])));
430 return "add_slli\t%0, %3, %1, %2";
432 [(set_attr "type" "alu_shift")
433 (set_attr "combo" "2")
434 (set_attr "length" "4")])
436 (define_insn "*add_srli"
437 [(set (match_operand:SI 0 "register_operand" "= r")
438 (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
439 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
440 (match_operand:SI 3 "register_operand" " r")))]
441 "TARGET_ISA_V3 && optimize_size"
442 "add_srli\t%0, %3, %1, %2"
443 [(set_attr "type" "alu_shift")
444 (set_attr "combo" "2")
445 (set_attr "length" "4")])
448 ;; GCC intends to simplify (minus (reg) (ashift ...))
449 ;; into (minus (reg) (mult ...)), so our matching pattern takes 'mult'
450 ;; and needs to ensure it is exact_log2 value.
451 (define_insn "*sub_slli"
452 [(set (match_operand:SI 0 "register_operand" "=r")
453 (minus:SI (match_operand:SI 1 "register_operand" " r")
454 (mult:SI (match_operand:SI 2 "register_operand" " r")
455 (match_operand:SI 3 "immediate_operand" " i"))))]
456 "TARGET_ISA_V3 && optimize_size
457 && (exact_log2 (INTVAL (operands[3])) != -1)
458 && (exact_log2 (INTVAL (operands[3])) <= 31)"
460 /* Get floor_log2 of the immediate value
461 so that we can generate 'sub_slli' instruction. */
462 operands[3] = GEN_INT (floor_log2 (INTVAL (operands[3])));
464 return "sub_slli\t%0, %1, %2, %3";
466 [(set_attr "type" "alu_shift")
467 (set_attr "combo" "2")
468 (set_attr "length" "4")])
470 (define_insn "*sub_srli"
471 [(set (match_operand:SI 0 "register_operand" "= r")
472 (minus:SI (match_operand:SI 1 "register_operand" " r")
473 (lshiftrt:SI (match_operand:SI 2 "register_operand" " r")
474 (match_operand:SI 3 "nds32_imm5u_operand" " Iu05"))))]
475 "TARGET_ISA_V3 && optimize_size"
476 "sub_srli\t%0, %1, %2, %3"
477 [(set_attr "type" "alu_shift")
478 (set_attr "combo" "2")
479 (set_attr "length" "4")])
482 ;; Multiplication instructions.
484 (define_insn "mulsi3"
485 [(set (match_operand:SI 0 "register_operand" "=w, r")
486 (mult:SI (match_operand:SI 1 "register_operand" "%0, r")
487 (match_operand:SI 2 "register_operand" " w, r")))]
492 [(set_attr "type" "mul,mul")
493 (set_attr "length" " 2, 4")
494 (set_attr "feature" "v3m, v1")])
496 (define_insn "mulsidi3"
497 [(set (match_operand:DI 0 "register_operand" "=r")
498 (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r"))
499 (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
500 "TARGET_ISA_V2 || TARGET_ISA_V3"
501 "mulsr64\t%0, %1, %2"
502 [(set_attr "type" "mul")
503 (set_attr "length" "4")])
505 (define_insn "umulsidi3"
506 [(set (match_operand:DI 0 "register_operand" "=r")
507 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
508 (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
509 "TARGET_ISA_V2 || TARGET_ISA_V3"
511 [(set_attr "type" "mul")
512 (set_attr "length" "4")])
515 ;; Multiply-accumulate instructions.
517 (define_insn "*maddr32_0"
518 [(set (match_operand:SI 0 "register_operand" "=r")
519 (plus:SI (match_operand:SI 3 "register_operand" " 0")
520 (mult:SI (match_operand:SI 1 "register_operand" " r")
521 (match_operand:SI 2 "register_operand" " r"))))]
523 "maddr32\t%0, %1, %2"
524 [(set_attr "type" "mac")
525 (set_attr "length" "4")])
527 (define_insn "*maddr32_1"
528 [(set (match_operand:SI 0 "register_operand" "=r")
529 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
530 (match_operand:SI 2 "register_operand" " r"))
531 (match_operand:SI 3 "register_operand" " 0")))]
533 "maddr32\t%0, %1, %2"
534 [(set_attr "type" "mac")
535 (set_attr "length" "4")])
537 (define_insn "*msubr32"
538 [(set (match_operand:SI 0 "register_operand" "=r")
539 (minus:SI (match_operand:SI 3 "register_operand" " 0")
540 (mult:SI (match_operand:SI 1 "register_operand" " r")
541 (match_operand:SI 2 "register_operand" " r"))))]
543 "msubr32\t%0, %1, %2"
544 [(set_attr "type" "mac")
545 (set_attr "length" "4")])
550 (define_insn "divmodsi4"
551 [(set (match_operand:SI 0 "register_operand" "=r")
552 (div:SI (match_operand:SI 1 "register_operand" " r")
553 (match_operand:SI 2 "register_operand" " r")))
554 (set (match_operand:SI 3 "register_operand" "=r")
555 (mod:SI (match_dup 1) (match_dup 2)))]
557 "divsr\t%0, %3, %1, %2"
558 [(set_attr "type" "div")
559 (set_attr "length" "4")])
561 (define_insn "udivmodsi4"
562 [(set (match_operand:SI 0 "register_operand" "=r")
563 (udiv:SI (match_operand:SI 1 "register_operand" " r")
564 (match_operand:SI 2 "register_operand" " r")))
565 (set (match_operand:SI 3 "register_operand" "=r")
566 (umod:SI (match_dup 1) (match_dup 2)))]
568 "divr\t%0, %3, %1, %2"
569 [(set_attr "type" "div")
570 (set_attr "length" "4")])
572 ;; divsr/divr will keep quotient only when quotient and remainder is the same
573 ;; register in our ISA spec, it's can reduce 1 register presure if we don't
575 (define_insn "divsi4"
576 [(set (match_operand:SI 0 "register_operand" "=r")
577 (div:SI (match_operand:SI 1 "register_operand" " r")
578 (match_operand:SI 2 "register_operand" " r")))]
580 "divsr\t%0, %0, %1, %2"
581 [(set_attr "type" "div")
582 (set_attr "length" "4")])
584 (define_insn "udivsi4"
585 [(set (match_operand:SI 0 "register_operand" "=r")
586 (udiv:SI (match_operand:SI 1 "register_operand" " r")
587 (match_operand:SI 2 "register_operand" " r")))]
589 "divr\t%0, %0, %1, %2"
590 [(set_attr "type" "div")
591 (set_attr "length" "4")])
593 ;; ----------------------------------------------------------------------------
595 ;; Boolean instructions.
596 ;; Note: We define the DImode versions in nds32-doubleword.md.
598 ;; ----------------------------------------------------------------------------
600 ;; ----------------------------------------------------------------------------
603 [(set (match_operand:SI 0 "register_operand" "=r")
604 (and:SI (not:SI (match_operand:SI 1 "register_operand" " r"))
605 (match_operand:SI 2 "register_operand" " r")))]
608 [(set_attr "type" "alu")
609 (set_attr "length" "4")]
612 (define_expand "andsi3"
613 [(set (match_operand:SI 0 "register_operand" "")
614 (and:SI (match_operand:SI 1 "register_operand" "")
615 (match_operand:SI 2 "nds32_reg_constant_operand" "")))]
618 if (CONST_INT_P (operands[2])
619 && !nds32_and_operand (operands[2], SImode))
621 nds32_expand_constant (SImode, INTVAL (operands[2]),
622 operands[0], operands[1]);
627 (define_insn "*andsi3"
628 [(set (match_operand:SI 0 "register_operand" "=l, r, l, l, l, l, l, l, r, r, r, r, r")
629 (and:SI (match_operand:SI 1 "register_operand" "%0, r, l, l, l, l, 0, 0, r, r, r, r, r")
630 (match_operand:SI 2 "nds32_and_operand" " l, r,Izeb,Izeh,Ixls,Ix11,Ibms,Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
633 HOST_WIDE_INT mask = INTVAL (operands[2]);
635 /* 16-bit andi instructions:
636 andi Rt3,Ra3,0xff -> zeb33 Rt3,Ra3
637 andi Rt3,Ra3,0xffff -> zeh33 Rt3,Ra3
638 andi Rt3,Ra3,0x01 -> xlsb33 Rt3,Ra3
639 andi Rt3,Ra3,0x7ff -> x11b33 Rt3,Ra3
640 andi Rt3,Rt3,2^imm3u -> bmski33 Rt3,imm3u
641 andi Rt3,Rt3,(2^(imm3u+1))-1 -> fexti33 Rt3,imm3u. */
643 switch (which_alternative)
646 return "and33\t%0, %2";
648 return "and\t%0, %1, %2";
650 return "zeb33\t%0, %1";
652 return "zeh33\t%0, %1";
654 return "xlsb33\t%0, %1";
656 return "x11b33\t%0, %1";
658 return "bmski33\t%0, %B2";
660 operands[2] = GEN_INT (floor_log2 (mask + 1) - 1);
661 return "fexti33\t%0, %2";
663 return "zeb\t%0, %1";
665 return "zeh\t%0, %1";
667 return "andi\t%0, %1, %2";
669 operands[2] = GEN_INT (~mask);
670 return "bitci\t%0, %1, %2";
672 return "bclr\t%0, %1, %b2";
678 [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
679 (set_attr "length" " 2, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4")
680 (set_attr "feature" "v3m, v1, v1, v1, v1, v1,v3m,v3m, v1, v1, v1, v3,pe1")])
682 (define_insn "*and_slli"
683 [(set (match_operand:SI 0 "register_operand" "= r")
684 (and:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
685 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
686 (match_operand:SI 3 "register_operand" " r")))]
687 "TARGET_ISA_V3 && optimize_size"
688 "and_slli\t%0, %3, %1, %2"
689 [(set_attr "type" "alu_shift")
690 (set_attr "length" "4")])
692 (define_insn "*and_srli"
693 [(set (match_operand:SI 0 "register_operand" "= r")
694 (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
695 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
696 (match_operand:SI 3 "register_operand" " r")))]
697 "TARGET_ISA_V3 && optimize_size"
698 "and_srli\t%0, %3, %1, %2"
699 [(set_attr "type" "alu_shift")
700 (set_attr "length" "4")])
703 ;; ----------------------------------------------------------------------------
705 ;; ----------------------------------------------------------------------------
707 ;; For V3/V3M ISA, we have 'or33' instruction.
708 ;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2.
710 (define_expand "iorsi3"
711 [(set (match_operand:SI 0 "register_operand" "")
712 (ior:SI (match_operand:SI 1 "register_operand" "")
713 (match_operand:SI 2 "general_operand" "")))]
716 if (!nds32_ior_operand (operands[2], SImode))
717 operands[2] = force_reg (SImode, operands[2]);
720 (define_insn "*iorsi3"
721 [(set (match_operand:SI 0 "register_operand" "=l, r, r, r")
722 (ior:SI (match_operand:SI 1 "register_operand" "%0, r, r, r")
723 (match_operand:SI 2 "nds32_ior_operand" " l, r, Iu15, Ie15")))]
730 [(set_attr "type" "alu,alu,alu,alu")
731 (set_attr "length" " 2, 4, 4, 4")
732 (set_attr "feature" "v3m, v1, v1,pe1")])
734 (define_insn "*or_slli"
735 [(set (match_operand:SI 0 "register_operand" "= r")
736 (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
737 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
738 (match_operand:SI 3 "register_operand" " r")))]
739 "TARGET_ISA_V3 && optimize_size"
740 "or_slli\t%0, %3, %1, %2"
741 [(set_attr "type" "alu_shift")
742 (set_attr "length" "4")])
744 (define_insn "*or_srli"
745 [(set (match_operand:SI 0 "register_operand" "= r")
746 (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
747 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
748 (match_operand:SI 3 "register_operand" " r")))]
749 "TARGET_ISA_V3 && optimize_size"
750 "or_srli\t%0, %3, %1, %2"
751 [(set_attr "type" "alu_shift")
752 (set_attr "length" "4")])
755 ;; ----------------------------------------------------------------------------
757 ;; ----------------------------------------------------------------------------
759 ;; For V3/V3M ISA, we have 'xor33' instruction.
760 ;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2.
762 (define_expand "xorsi3"
763 [(set (match_operand:SI 0 "register_operand" "")
764 (xor:SI (match_operand:SI 1 "register_operand" "")
765 (match_operand:SI 2 "general_operand" "")))]
768 if (!nds32_xor_operand (operands[2], SImode))
769 operands[2] = force_reg (SImode, operands[2]);
772 (define_insn "*xorsi3"
773 [(set (match_operand:SI 0 "register_operand" "=l, r, r, r")
774 (xor:SI (match_operand:SI 1 "register_operand" "%0, r, r, r")
775 (match_operand:SI 2 "nds32_xor_operand" " l, r, Iu15, It15")))]
782 [(set_attr "type" "alu,alu,alu,alu")
783 (set_attr "length" " 2, 4, 4, 4")
784 (set_attr "feature" "v3m, v1, v1,pe1")])
786 (define_insn "*xor_slli"
787 [(set (match_operand:SI 0 "register_operand" "= r")
788 (xor:SI (ashift:SI (match_operand:SI 1 "register_operand" " r")
789 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
790 (match_operand:SI 3 "register_operand" " r")))]
791 "TARGET_ISA_V3 && optimize_size"
792 "xor_slli\t%0, %3, %1, %2"
793 [(set_attr "type" "alu_shift")
794 (set_attr "length" "4")])
796 (define_insn "*xor_srli"
797 [(set (match_operand:SI 0 "register_operand" "= r")
798 (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r")
799 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
800 (match_operand:SI 3 "register_operand" " r")))]
801 "TARGET_ISA_V3 && optimize_size"
802 "xor_srli\t%0, %3, %1, %2"
803 [(set_attr "type" "alu_shift")
804 (set_attr "length" "4")])
806 ;; Rotate Right Instructions.
808 (define_insn "*rotrsi3"
809 [(set (match_operand:SI 0 "register_operand" "= r, r")
810 (rotatert:SI (match_operand:SI 1 "register_operand" " r, r")
811 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))]
816 [(set_attr "type" " alu, alu")
817 (set_attr "subtype" "shift,shift")
818 (set_attr "length" " 4, 4")])
821 ;; ----------------------------------------------------------------------------
823 ;; ----------------------------------------------------------------------------
825 ;; For V3/V3M ISA, we have 'neg33' instruction.
826 ;; So we can identify 'xor Rt3,Ra3' case and set its length to be 2.
827 ;; And for V2 ISA, there is NO 'neg33' instruction.
828 ;; The only option is to use 'subri A,B,0' (its semantic is 'A = 0 - B').
829 (define_insn "negsi2"
830 [(set (match_operand:SI 0 "register_operand" "=l, r")
831 (neg:SI (match_operand:SI 1 "register_operand" " l, r")))]
836 [(set_attr "type" "alu,alu")
837 (set_attr "length" " 2, 4")
838 (set_attr "feature" "v3m, v1")])
840 (define_expand "negsf2"
841 [(set (match_operand:SF 0 "register_operand" "")
842 (neg:SF (match_operand:SF 1 "register_operand" "")))]
845 if (!TARGET_FPU_SINGLE && !TARGET_EXT_PERF)
847 rtx new_dst = simplify_gen_subreg (SImode, operands[0], SFmode, 0);
848 rtx new_src = simplify_gen_subreg (SImode, operands[1], SFmode, 0);
850 emit_insn (gen_xorsi3 (new_dst,
852 gen_int_mode (0x80000000, SImode)));
858 (define_expand "negdf2"
859 [(set (match_operand:DF 0 "register_operand" "")
860 (neg:DF (match_operand:DF 1 "register_operand" "")))]
865 (define_insn_and_split "soft_negdf2"
866 [(set (match_operand:DF 0 "register_operand" "")
867 (neg:DF (match_operand:DF 1 "register_operand" "")))]
873 rtx src = operands[1];
874 rtx dst = operands[0];
875 rtx ori_dst = operands[0];
877 bool need_extra_move_for_dst_p;
878 /* FPU register can't change mode to SI directly, so we need create a
879 tmp register to handle it, and FPU register can't do `xor` or btgl. */
880 if (HARD_REGISTER_P (src)
881 && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (src)))
883 rtx tmp = gen_reg_rtx (DFmode);
884 emit_move_insn (tmp, src);
888 if (HARD_REGISTER_P (dst)
889 && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (dst)))
891 need_extra_move_for_dst_p = true;
892 rtx tmp = gen_reg_rtx (DFmode);
896 rtx dst_high_part = simplify_gen_subreg (
898 DFmode, subreg_highpart_offset (SImode, DFmode));
899 rtx dst_low_part = simplify_gen_subreg (
901 DFmode, subreg_lowpart_offset (SImode, DFmode));
902 rtx src_high_part = simplify_gen_subreg (
904 DFmode, subreg_highpart_offset (SImode, DFmode));
905 rtx src_low_part = simplify_gen_subreg (
907 DFmode, subreg_lowpart_offset (SImode, DFmode));
909 emit_insn (gen_xorsi3 (dst_high_part,
911 gen_int_mode (0x80000000, SImode)));
912 emit_move_insn (dst_low_part, src_low_part);
914 if (need_extra_move_for_dst_p)
915 emit_move_insn (ori_dst, dst);
921 ;; ----------------------------------------------------------------------------
922 ;; 'ONE_COMPLIMENT' operation
923 ;; ----------------------------------------------------------------------------
925 ;; For V3/V3M ISA, we have 'not33' instruction.
926 ;; So we can identify 'not Rt3,Ra3' case and set its length to be 2.
927 (define_insn "one_cmplsi2"
928 [(set (match_operand:SI 0 "register_operand" "=w, r")
929 (not:SI (match_operand:SI 1 "register_operand" " w, r")))]
934 [(set_attr "type" "alu,alu")
935 (set_attr "length" " 2, 4")
936 (set_attr "feature" "v3m, v1")])
939 ;; ----------------------------------------------------------------------------
941 ;; Shift instructions.
943 (define_expand "<shift>si3"
944 [(set (match_operand:SI 0 "register_operand" "")
945 (shift_rotate:SI (match_operand:SI 1 "register_operand" "")
946 (match_operand:SI 2 "nds32_rimm5u_operand" "")))]
949 if (operands[2] == const0_rtx)
951 emit_move_insn (operands[0], operands[1]);
956 (define_insn "*ashlsi3"
957 [(set (match_operand:SI 0 "register_operand" "= l, r, r")
958 (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r")
959 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu03, Iu05, r")))]
965 [(set_attr "type" " alu, alu, alu")
966 (set_attr "subtype" "shift,shift,shift")
967 (set_attr "length" " 2, 4, 4")])
969 (define_insn "*ashrsi3"
970 [(set (match_operand:SI 0 "register_operand" "= d, r, r")
971 (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r")
972 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
978 [(set_attr "type" " alu, alu, alu")
979 (set_attr "subtype" "shift,shift,shift")
980 (set_attr "length" " 2, 4, 4")])
982 (define_insn "*lshrsi3"
983 [(set (match_operand:SI 0 "register_operand" "= d, r, r")
984 (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r")
985 (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
991 [(set_attr "type" " alu, alu, alu")
992 (set_attr "subtype" "shift,shift,shift")
993 (set_attr "length" " 2, 4, 4")])
996 ;; ----------------------------------------------------------------------------
998 ;; ----------------------------------------------------------------------------
999 ;; Conditional Move patterns
1000 ;; ----------------------------------------------------------------------------
1002 (define_expand "mov<mode>cc"
1003 [(set (match_operand:QIHISI 0 "register_operand" "")
1004 (if_then_else:QIHISI (match_operand 1 "nds32_movecc_comparison_operator" "")
1005 (match_operand:QIHISI 2 "register_operand" "")
1006 (match_operand:QIHISI 3 "register_operand" "")))]
1007 "TARGET_CMOV && !optimize_size"
1009 enum nds32_expand_result_type result = nds32_expand_movcc (operands);
1018 case EXPAND_CREATE_TEMPLATE:
1025 (define_insn "cmovz<mode>"
1026 [(set (match_operand:QIHISI 0 "register_operand" "=r, r")
1027 (if_then_else:QIHISI (eq (match_operand:SI 1 "register_operand" " r, r")
1029 (match_operand:QIHISI 2 "register_operand" " r, 0")
1030 (match_operand:QIHISI 3 "register_operand" " 0, r")))]
1035 [(set_attr "type" "alu")
1036 (set_attr "length" "4")])
1038 (define_insn "cmovn<mode>"
1039 [(set (match_operand:QIHISI 0 "register_operand" "=r, r")
1040 (if_then_else:QIHISI (ne (match_operand:SI 1 "register_operand" " r, r")
1042 (match_operand:QIHISI 2 "register_operand" " r, 0")
1043 (match_operand:QIHISI 3 "register_operand" " 0, r")))]
1048 [(set_attr "type" "alu")
1049 (set_attr "length" "4")])
1051 ;; A hotfix to help RTL combiner to merge a cmovn insn and a zero_extend insn.
1052 ;; It should be removed once after we change the expansion form of the cmovn.
1053 (define_insn "*cmovn_simplified_<mode>"
1054 [(set (match_operand:QIHISI 0 "register_operand" "=r")
1055 (if_then_else:QIHISI (match_operand:SI 1 "register_operand" "r")
1056 (match_operand:QIHISI 2 "register_operand" "r")
1057 (match_operand:QIHISI 3 "register_operand" "0")))]
1060 [(set_attr "type" "alu")])
1062 ;; ----------------------------------------------------------------------------
1063 ;; Conditional Branch patterns
1064 ;; ----------------------------------------------------------------------------
1066 (define_expand "cbranchsi4"
1068 (if_then_else (match_operator 0 "comparison_operator"
1069 [(match_operand:SI 1 "register_operand" "")
1070 (match_operand:SI 2 "nds32_reg_constant_operand" "")])
1071 (label_ref (match_operand 3 "" ""))
1075 enum nds32_expand_result_type result = nds32_expand_cbranch (operands);
1084 case EXPAND_CREATE_TEMPLATE:
1092 (define_insn "cbranchsi4_equality_zero"
1094 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1095 [(match_operand:SI 1 "register_operand" "t,l, r")
1097 (label_ref (match_operand 2 "" ""))
1101 return nds32_output_cbranchsi4_equality_zero (insn, operands);
1103 [(set_attr "type" "branch")
1104 (set_attr_alternative "enabled"
1107 (if_then_else (match_test "TARGET_16_BIT")
1108 (const_string "yes")
1109 (const_string "no"))
1111 (if_then_else (match_test "TARGET_16_BIT")
1112 (const_string "yes")
1113 (const_string "no"))
1115 (const_string "yes")
1117 (set_attr_alternative "length"
1120 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1121 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
1122 (le (minus (match_dup 2) (pc)) (const_int 250)))
1123 (if_then_else (match_test "TARGET_16_BIT")
1126 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1127 (le (minus (match_dup 2) (pc)) (const_int 65500)))
1129 (if_then_else (match_test "TARGET_16_BIT")
1134 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1135 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
1136 (le (minus (match_dup 2) (pc)) (const_int 250)))
1137 (if_then_else (match_test "TARGET_16_BIT")
1140 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1141 (le (minus (match_dup 2) (pc)) (const_int 65500)))
1143 (if_then_else (match_test "TARGET_16_BIT")
1148 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1149 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1150 (le (minus (match_dup 2) (pc)) (const_int 65500)))
1157 ;; This pattern is dedicated to V2 ISA,
1158 ;; because V2 DOES NOT HAVE beqc/bnec instruction.
1159 (define_insn "cbranchsi4_equality_reg"
1161 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1162 [(match_operand:SI 1 "register_operand" "v, r")
1163 (match_operand:SI 2 "register_operand" "l, r")])
1164 (label_ref (match_operand 3 "" ""))
1168 return nds32_output_cbranchsi4_equality_reg (insn, operands);
1170 [(set_attr "type" "branch")
1171 (set_attr_alternative "enabled"
1174 (if_then_else (match_test "TARGET_16_BIT")
1175 (const_string "yes")
1176 (const_string "no"))
1178 (const_string "yes")
1180 (set_attr_alternative "length"
1183 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1184 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1185 (le (minus (match_dup 3) (pc)) (const_int 250)))
1187 (if_then_else (and (ge (minus (match_dup 3) (pc))
1189 (le (minus (match_dup 3) (pc))
1195 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1196 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
1197 (le (minus (match_dup 3) (pc)) (const_int 16350)))
1204 ;; This pattern is dedicated to V3/V3M,
1205 ;; because V3/V3M DO HAVE beqc/bnec instruction.
1206 (define_insn "cbranchsi4_equality_reg_or_const_int"
1208 (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1209 [(match_operand:SI 1 "register_operand" "v, r, r")
1210 (match_operand:SI 2 "nds32_rimm11s_operand" "l, r, Is11")])
1211 (label_ref (match_operand 3 "" ""))
1213 "TARGET_ISA_V3 || TARGET_ISA_V3M"
1215 return nds32_output_cbranchsi4_equality_reg_or_const_int (insn, operands);
1217 [(set_attr "type" "branch")
1218 (set_attr_alternative "enabled"
1221 (if_then_else (match_test "TARGET_16_BIT")
1222 (const_string "yes")
1223 (const_string "no"))
1225 (const_string "yes")
1227 (const_string "yes")
1229 (set_attr_alternative "length"
1232 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1233 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1234 (le (minus (match_dup 3) (pc)) (const_int 250)))
1236 (if_then_else (and (ge (minus (match_dup 3) (pc))
1238 (le (minus (match_dup 3) (pc))
1244 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1245 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
1246 (le (minus (match_dup 3) (pc)) (const_int 16350)))
1251 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1252 (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1253 (le (minus (match_dup 3) (pc)) (const_int 250)))
1260 (define_insn "*cbranchsi4_greater_less_zero"
1262 (if_then_else (match_operator 0 "nds32_greater_less_comparison_operator"
1263 [(match_operand:SI 1 "register_operand" "r")
1265 (label_ref (match_operand 2 "" ""))
1269 return nds32_output_cbranchsi4_greater_less_zero (insn, operands);
1271 [(set_attr "type" "branch")
1272 (set (attr "length")
1273 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1274 (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1275 (le (minus (match_dup 2) (pc)) (const_int 65500)))
1281 (define_expand "cstoresi4"
1282 [(set (match_operand:SI 0 "register_operand" "")
1283 (match_operator:SI 1 "comparison_operator"
1284 [(match_operand:SI 2 "register_operand" "")
1285 (match_operand:SI 3 "nonmemory_operand" "")]))]
1288 enum nds32_expand_result_type result = nds32_expand_cstore (operands);
1297 case EXPAND_CREATE_TEMPLATE:
1305 (define_expand "slts_compare"
1306 [(set (match_operand:SI 0 "register_operand" "")
1307 (lt:SI (match_operand:SI 1 "general_operand" "")
1308 (match_operand:SI 2 "general_operand" "")))]
1311 if (!REG_P (operands[1]))
1312 operands[1] = force_reg (SImode, operands[1]);
1314 if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2]))
1315 operands[2] = force_reg (SImode, operands[2]);
1318 (define_insn "slts_compare_impl"
1319 [(set (match_operand:SI 0 "register_operand" "=t, t, r, r")
1320 (lt:SI (match_operand:SI 1 "register_operand" " d, d, r, r")
1321 (match_operand:SI 2 "nds32_rimm15s_operand" " r,Iu05, r, Is15")))]
1328 [(set_attr "type" "alu, alu, alu, alu")
1329 (set_attr "length" " 2, 2, 4, 4")])
1331 (define_insn "slt_eq0"
1332 [(set (match_operand:SI 0 "register_operand" "=t, r")
1333 (eq:SI (match_operand:SI 1 "register_operand" " d, r")
1339 [(set_attr "type" "alu, alu")
1340 (set_attr "length" " 2, 4")])
1342 (define_expand "slt_compare"
1343 [(set (match_operand:SI 0 "register_operand" "")
1344 (ltu:SI (match_operand:SI 1 "general_operand" "")
1345 (match_operand:SI 2 "general_operand" "")))]
1348 if (!REG_P (operands[1]))
1349 operands[1] = force_reg (SImode, operands[1]);
1351 if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2]))
1352 operands[2] = force_reg (SImode, operands[2]);
1355 (define_insn "slt_compare_impl"
1356 [(set (match_operand:SI 0 "register_operand" "=t, t, r, r")
1357 (ltu:SI (match_operand:SI 1 "register_operand" " d, d, r, r")
1358 (match_operand:SI 2 "nds32_rimm15s_operand" " r, Iu05, r, Is15")))]
1365 [(set_attr "type" "alu, alu, alu, alu")
1366 (set_attr "length" " 2, 2, 4, 4")])
1369 ;; ----------------------------------------------------------------------------
1371 ;; Unconditional and other jump instructions.
1374 [(set (pc) (label_ref (match_operand 0 "" "")))]
1377 /* This unconditional jump has two forms:
1378 32-bit instruction => j imm24s << 1
1379 16-bit instruction => j8 imm8s << 1
1382 we assume it is always reachable.
1384 it must satisfy { 255 >= (label - pc) >= -256 } condition.
1385 However, since the $pc for nds32 is at the beginning of the instruction,
1386 we should leave some length space for current insn.
1387 So we use range -250 ~ 250. */
1388 switch (get_attr_length (insn))
1398 [(set_attr "type" "branch")
1399 (set_attr "enabled" "yes")
1400 (set (attr "length")
1401 (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1402 (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250))
1403 (le (minus (match_dup 0) (pc)) (const_int 250)))
1404 (if_then_else (match_test "TARGET_16_BIT")
1410 (define_insn "indirect_jump"
1411 [(set (pc) (match_operand:SI 0 "register_operand" "r, r"))]
1416 [(set_attr "type" "branch,branch")
1417 (set_attr "length" " 2, 4")])
1419 ;; Subroutine call instruction returning no value.
1420 ;; operands[0]: It should be a mem RTX whose address is
1421 ;; the address of the function.
1422 ;; operands[1]: It is the number of bytes of arguments pushed as a const_int.
1423 ;; operands[2]: It is the number of registers used as operands.
1425 (define_expand "call"
1426 [(parallel [(call (match_operand 0 "memory_operand" "")
1428 (clobber (reg:SI LP_REGNUM))
1429 (clobber (reg:SI TA_REGNUM))])]
1434 (define_insn "call_internal"
1435 [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i"))
1437 (clobber (reg:SI LP_REGNUM))
1438 (clobber (reg:SI TA_REGNUM))])]
1441 rtx_insn *next_insn = next_active_insn (insn);
1442 bool align_p = (!(next_insn && get_attr_length (next_insn) == 2))
1443 && NDS32_ALIGN_P ();
1444 switch (which_alternative)
1450 return "jral5\t%0\;.align 2";
1457 return "jral\t%0\;.align 2";
1462 return nds32_output_call (insn, operands, operands[0],
1463 "bal\t%0", "jal\t%0", align_p);
1468 [(set_attr "enabled" "yes")
1469 (set_attr "type" "branch")
1470 (set_attr_alternative "length"
1473 (if_then_else (match_test "TARGET_16_BIT")
1477 (if_then_else (match_test "nds32_long_call_p (operands[0])")
1483 ;; Subroutine call instruction returning a value.
1484 ;; operands[0]: It is the hard regiser in which the value is returned.
1485 ;; The rest three operands are the same as the
1486 ;; three operands of the 'call' instruction.
1487 ;; (but with numbers increased by one)
1489 (define_expand "call_value"
1490 [(parallel [(set (match_operand 0)
1491 (call (match_operand 1 "memory_operand" "")
1493 (clobber (reg:SI LP_REGNUM))
1494 (clobber (reg:SI TA_REGNUM))])]
1497 (define_insn "call_value_internal"
1498 [(parallel [(set (match_operand 0)
1499 (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i"))
1501 (clobber (reg:SI LP_REGNUM))
1502 (clobber (reg:SI TA_REGNUM))])]
1505 rtx_insn *next_insn = next_active_insn (insn);
1506 bool align_p = (!(next_insn && get_attr_length (next_insn) == 2))
1507 && NDS32_ALIGN_P ();
1508 switch (which_alternative)
1514 return "jral5\t%1\;.align 2";
1521 return "jral\t%1\;.align 2";
1526 return nds32_output_call (insn, operands, operands[1],
1527 "bal\t%1", "jal\t%1", align_p);
1532 [(set_attr "enabled" "yes")
1533 (set_attr "type" "branch")
1534 (set_attr_alternative "length"
1537 (if_then_else (match_test "TARGET_16_BIT")
1541 (if_then_else (match_test "nds32_long_call_p (operands[1])")
1547 ;; Call subroutine returning any type.
1549 (define_expand "untyped_call"
1550 [(parallel [(call (match_operand 0 "" "")
1552 (match_operand 1 "" "")
1553 (match_operand 2 "" "")])]
1558 emit_call_insn (gen_call (operands[0], const0_rtx));
1560 for (i = 0; i < XVECLEN (operands[2], 0); i++)
1562 rtx set = XVECEXP (operands[2], 0, i);
1563 emit_move_insn (SET_DEST (set), SET_SRC (set));
1566 /* The optimizer does not know that the call sets the function value
1567 registers we stored in the result block. We avoid problems by
1568 claiming that all hard registers are used and clobbered at this
1570 emit_insn (gen_blockage ());
1574 ;; ----------------------------------------------------------------------------
1576 ;; The sibcall patterns.
1581 (define_expand "sibcall"
1582 [(parallel [(call (match_operand 0 "memory_operand" "")
1584 (clobber (reg:SI TA_REGNUM))
1588 (define_insn "sibcall_internal"
1589 [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i"))
1591 (clobber (reg:SI TA_REGNUM))
1595 switch (which_alternative)
1603 if (nds32_long_call_p (operands[0]))
1611 [(set_attr "enabled" "yes")
1612 (set_attr "type" "branch")
1613 (set_attr_alternative "length"
1616 (if_then_else (match_test "TARGET_16_BIT")
1620 (if_then_else (match_test "nds32_long_call_p (operands[0])")
1627 ;; sibcall_value_internal
1628 ;; sibcall_value_immediate
1630 (define_expand "sibcall_value"
1631 [(parallel [(set (match_operand 0)
1632 (call (match_operand 1 "memory_operand" "")
1634 (clobber (reg:SI TA_REGNUM))
1638 (define_insn "sibcall_value_internal"
1639 [(parallel [(set (match_operand 0)
1640 (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i"))
1642 (clobber (reg:SI TA_REGNUM))
1646 switch (which_alternative)
1654 if (nds32_long_call_p (operands[1]))
1662 [(set_attr "enabled" "yes")
1663 (set_attr "type" "branch")
1664 (set_attr_alternative "length"
1667 (if_then_else (match_test "TARGET_16_BIT")
1671 (if_then_else (match_test "nds32_long_call_p (operands[1])")
1677 ;; ----------------------------------------------------------------------------
1679 ;; prologue and epilogue.
1681 (define_expand "prologue" [(const_int 0)]
1684 /* Note that only under V3/V3M ISA, we could use v3push prologue.
1685 In addition, we need to check if v3push is indeed available. */
1686 if (NDS32_V3PUSH_AVAILABLE_P)
1687 nds32_expand_prologue_v3push ();
1689 nds32_expand_prologue ();
1693 (define_expand "epilogue" [(const_int 0)]
1696 /* Note that only under V3/V3M ISA, we could use v3pop epilogue.
1697 In addition, we need to check if v3push is indeed available. */
1698 if (NDS32_V3PUSH_AVAILABLE_P)
1699 nds32_expand_epilogue_v3pop (false);
1701 nds32_expand_epilogue (false);
1705 (define_expand "sibcall_epilogue" [(const_int 0)]
1708 /* Pass true to indicate that this is sibcall epilogue and
1709 exit from a function without the final branch back to the
1710 calling function. */
1711 nds32_expand_epilogue (true);
1728 [(set_attr "type" "misc")
1729 (set_attr "enabled" "yes")
1730 (set (attr "length")
1731 (if_then_else (match_test "TARGET_16_BIT")
1736 ;; ----------------------------------------------------------------------------
1737 ;; Stack push/pop operations
1738 ;; ----------------------------------------------------------------------------
1740 ;; The pattern for stack push.
1741 ;; Both stack_push_multiple and stack_v3push use the following pattern.
1742 ;; So we need to use TARGET_V3PUSH to determine the instruction length.
1743 (define_insn "*stack_push"
1744 [(match_parallel 0 "nds32_stack_push_operation"
1745 [(set (mem:SI (plus:SI (reg:SI SP_REGNUM)
1746 (match_operand:SI 1 "const_int_operand" "")))
1747 (match_operand:SI 2 "register_operand" ""))
1751 return nds32_output_stack_push (operands[0]);
1753 [(set_attr "type" "store_multiple")
1754 (set_attr "combo" "12")
1755 (set_attr "enabled" "yes")
1756 (set (attr "length")
1757 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
1762 ;; The pattern for stack pop.
1763 ;; Both stack_pop_multiple and stack_v3pop use the following pattern.
1764 ;; So we need to use TARGET_V3PUSH to determine the instruction length.
1765 (define_insn "*stack_pop"
1766 [(match_parallel 0 "nds32_stack_pop_operation"
1767 [(set (match_operand:SI 1 "register_operand" "")
1768 (mem:SI (reg:SI SP_REGNUM)))
1772 return nds32_output_stack_pop (operands[0]);
1774 [(set_attr "type" "load_multiple")
1775 (set_attr "combo" "12")
1776 (set_attr "enabled" "yes")
1777 (set (attr "length")
1778 (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
1783 ;; ----------------------------------------------------------------------------
1784 ;; Return operation patterns
1785 ;; ----------------------------------------------------------------------------
1787 ;; Use this pattern to expand a return instruction
1788 ;; with simple_return rtx if no epilogue is required.
1789 (define_expand "return"
1790 [(parallel [(return)
1791 (clobber (reg:SI FP_REGNUM))])]
1792 "nds32_can_use_return_insn ()"
1794 /* Emit as the simple return. */
1795 if (cfun->machine->naked_p
1796 && (cfun->machine->va_args_size == 0))
1798 emit_jump_insn (gen_return_internal ());
1803 ;; This pattern is expanded only by the shrink-wrapping optimization
1804 ;; on paths where the function prologue has not been executed.
1805 (define_expand "simple_return"
1811 (define_insn "*nds32_return"
1812 [(parallel [(return)
1813 (clobber (reg:SI FP_REGNUM))])]
1816 return nds32_output_return ();
1818 [(set_attr "type" "branch")
1819 (set_attr "enabled" "yes")
1820 (set_attr "length" "4")])
1822 (define_insn "return_internal"
1831 [(set_attr "type" "branch")
1832 (set_attr "enabled" "yes")
1833 (set (attr "length")
1834 (if_then_else (match_test "TARGET_16_BIT")
1839 ;; ----------------------------------------------------------------------------
1840 ;; Jump Table patterns
1841 ;; ----------------------------------------------------------------------------
1842 ;; Need to implement ASM_OUTPUT_ADDR_VEC_ELT (for normal jump table)
1843 ;; or ASM_OUTPUT_ADDR_DIFF_ELT (for pc relative jump table) as well.
1845 ;; operands[0]: The index to dispatch on.
1846 ;; operands[1]: The lower bound for indices in the table.
1847 ;; operands[2]: The total range of indices int the table.
1848 ;; i.e. The largest index minus the smallest one.
1849 ;; operands[3]: A label that precedes the table itself.
1850 ;; operands[4]: A label to jump to if the index has a value outside the bounds.
1852 ;; We need to create following sequences for jump table code generation:
1853 ;; A) k <-- (plus (operands[0]) (-operands[1]))
1854 ;; B) if (gtu k operands[2]) then goto operands[4]
1855 ;; C) t <-- operands[3]
1856 ;; D) z <-- (mem (plus (k << 0 or 1 or 2) t))
1857 ;; E) z <-- t + z (NOTE: This is only required for pc relative jump table.)
1858 ;; F) jump to target with register t or z
1860 ;; The steps C, D, E, and F are performed by casesi_internal pattern.
1861 (define_expand "casesi"
1862 [(match_operand:SI 0 "register_operand" "r") ; index to jump on
1863 (match_operand:SI 1 "immediate_operand" "i") ; lower bound
1864 (match_operand:SI 2 "immediate_operand" "i") ; total range
1865 (match_operand:SI 3 "" "") ; table label
1866 (match_operand:SI 4 "" "")] ; Out of range label
1872 /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */
1873 if (operands[1] != const0_rtx)
1875 reg = gen_reg_rtx (SImode);
1876 add_tmp = gen_int_mode (-INTVAL (operands[1]), SImode);
1878 /* If the integer value is not in the range of imm15s,
1879 we need to force register first because our addsi3 pattern
1880 only accept nds32_rimm15s_operand predicate. */
1881 add_tmp = force_reg (SImode, add_tmp);
1883 emit_insn (gen_addsi3 (reg, operands[0], add_tmp));
1887 /* Step B: "if (gtu k operands[2]) then goto operands[4]". */
1888 test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]);
1889 emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2],
1892 /* Step C, D, E, and F, using another temporary register. */
1893 rtx tmp = gen_reg_rtx (SImode);
1894 emit_jump_insn (gen_casesi_internal (operands[0], operands[3], tmp));
1898 ;; We are receiving operands from casesi pattern:
1900 ;; operands[0]: The index that have been substracted with lower bound.
1901 ;; operands[1]: A label that precedes the table itself.
1902 ;; operands[2]: A temporary register to retrieve value in table.
1904 ;; We need to perform steps C, D, E, and F:
1906 ;; C) t <-- operands[1]
1907 ;; D) z <-- (mem (plus (operands[0] << m) t))
1908 ;; m is 2 for normal jump table.
1909 ;; m is 0, 1, or 2 for pc relative jump table based on diff size.
1910 ;; E) t <-- z + t (NOTE: This is only required for pc relative jump table.)
1911 ;; F) Jump to target with register t or z.
1913 ;; The USE in this pattern is needed to tell flow analysis that this is
1914 ;; a CASESI insn. It has no other purpose.
1915 (define_insn "casesi_internal"
1916 [(parallel [(set (pc)
1917 (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
1919 (label_ref (match_operand 1 "" "")))))
1920 (use (label_ref (match_dup 1)))
1921 (clobber (match_operand:SI 2 "register_operand" "=r"))
1922 (clobber (reg:SI TA_REGNUM))])]
1925 if (CASE_VECTOR_PC_RELATIVE)
1926 return nds32_output_casesi_pc_relative (operands);
1928 return nds32_output_casesi (operands);
1930 [(set_attr "length" "20")
1931 (set_attr "type" "branch")])
1933 ;; ----------------------------------------------------------------------------
1935 ;; Performance Extension
1937 (define_insn "clzsi2"
1938 [(set (match_operand:SI 0 "register_operand" "=r")
1939 (clz:SI (match_operand:SI 1 "register_operand" " r")))]
1942 [(set_attr "type" "alu")
1943 (set_attr "length" "4")])
1945 (define_insn "smaxsi3"
1946 [(set (match_operand:SI 0 "register_operand" "=r")
1947 (smax:SI (match_operand:SI 1 "register_operand" " r")
1948 (match_operand:SI 2 "register_operand" " r")))]
1951 [(set_attr "type" "alu")
1952 (set_attr "length" "4")])
1954 (define_insn "sminsi3"
1955 [(set (match_operand:SI 0 "register_operand" "=r")
1956 (smin:SI (match_operand:SI 1 "register_operand" " r")
1957 (match_operand:SI 2 "register_operand" " r")))]
1960 [(set_attr "type" "alu")
1961 (set_attr "length" "4")])
1964 [(set (match_operand:SI 0 "register_operand" "= r")
1965 (zero_extract:SI (match_operand:SI 1 "register_operand" " r")
1967 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")))]
1970 [(set_attr "type" "alu")
1971 (set_attr "length" "4")])
1974 [(set (match_operand:SI 0 "register_operand" "=r")
1979 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
1980 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
1985 [(set_attr "type" "alu")
1986 (set_attr "length" "4")])
1988 ;; ----------------------------------------------------------------------------
1992 (define_insn "relax_group"
1993 [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)]
1996 [(set_attr "length" "0")]
1999 (define_insn "pop25return"
2001 (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_POP25_RETURN)]
2003 "! return for pop 25"
2004 [(set_attr "length" "0")]
2007 ;; ----------------------------------------------------------------------------
2009 ;; Patterns for exception handling
2011 (define_expand "eh_return"
2012 [(use (match_operand 0 "general_operand"))]
2015 emit_insn (gen_nds32_eh_return (operands[0]));
2019 (define_insn_and_split "nds32_eh_return"
2020 [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_EH_RETURN)]
2029 /* The operands[0] is the handler address. We need to assign it
2030 to return address rtx so that we can jump to exception handler
2031 when returning from current function. */
2033 if (cfun->machine->lp_size == 0)
2035 /* If $lp is not saved in the stack frame, we can take $lp directly. */
2036 place = gen_rtx_REG (SImode, LP_REGNUM);
2040 /* Otherwise, we need to locate the stack slot of return address.
2041 The return address is generally saved in [$fp-4] location.
2042 However, DSE (dead store elimination) does not detect an alias
2043 between [$fp-x] and [$sp+y]. This can result in a store to save
2044 $lp introduced by builtin_eh_return() being incorrectly deleted
2045 if it is based on $fp. The solution we take here is to compute
2046 the offset relative to stack pointer and then use $sp to access
2047 location so that the alias can be detected.
2048 FIXME: What if the immediate value "offset" is too large to be
2049 fit in a single addi instruction? */
2050 HOST_WIDE_INT offset;
2052 offset = (cfun->machine->fp_size
2053 + cfun->machine->gp_size
2054 + cfun->machine->lp_size
2055 + cfun->machine->callee_saved_gpr_regs_size
2056 + cfun->machine->callee_saved_area_gpr_padding_bytes
2057 + cfun->machine->callee_saved_fpr_regs_size
2058 + cfun->machine->eh_return_data_regs_size
2059 + cfun->machine->local_size
2060 + cfun->machine->out_args_size);
2062 addr = plus_constant (Pmode, stack_pointer_rtx, offset - 4);
2063 place = gen_frame_mem (SImode, addr);
2066 emit_move_insn (place, operands[0]);
2070 ;; ----------------------------------------------------------------------------