[NDS32] New option -malways-align and -malign-functions.
[official-gcc.git] / gcc / config / nds32 / nds32-md-auxiliary.c
blob720e85a20eb321e040bcbda5e764ae942455b642
1 /* Auxiliary functions for output asm template or expand rtl
2 pattern of Andes NDS32 cpu for GNU compiler
3 Copyright (C) 2012-2018 Free Software Foundation, Inc.
4 Contributed by Andes Technology Corporation.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published
10 by the Free Software Foundation; either version 3, or (at your
11 option) any later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* ------------------------------------------------------------------------ */
24 #define IN_TARGET_CODE 1
26 #include "config.h"
27 #include "system.h"
28 #include "coretypes.h"
29 #include "backend.h"
30 #include "target.h"
31 #include "rtl.h"
32 #include "tree.h"
33 #include "memmodel.h"
34 #include "tm_p.h"
35 #include "optabs.h" /* For GEN_FCN. */
36 #include "recog.h"
37 #include "output.h"
38 #include "tm-constrs.h"
39 #include "expr.h"
40 #include "emit-rtl.h"
41 #include "explow.h"
43 /* ------------------------------------------------------------------------ */
45 static int
46 nds32_regno_to_enable4 (unsigned regno)
48 switch (regno)
50 case 28: /* $r28/fp */
51 return 0x8;
52 case 29: /* $r29/gp */
53 return 0x4;
54 case 30: /* $r30/lp */
55 return 0x2;
56 case 31: /* $r31/sp */
57 return 0x1;
58 default:
59 gcc_unreachable ();
63 /* A helper function to return character based on byte size. */
64 static char
65 nds32_byte_to_size (int byte)
67 switch (byte)
69 case 4:
70 return 'w';
71 case 2:
72 return 'h';
73 case 1:
74 return 'b';
75 default:
76 /* Normally it should not be here. */
77 gcc_unreachable ();
81 static int
82 nds32_inverse_cond_code (int code)
84 switch (code)
86 case NE:
87 return EQ;
88 case EQ:
89 return NE;
90 case GT:
91 return LE;
92 case LE:
93 return GT;
94 case GE:
95 return LT;
96 case LT:
97 return GE;
98 default:
99 gcc_unreachable ();
103 static const char *
104 nds32_cond_code_str (int code)
106 switch (code)
108 case NE:
109 return "ne";
110 case EQ:
111 return "eq";
112 case GT:
113 return "gt";
114 case LE:
115 return "le";
116 case GE:
117 return "ge";
118 case LT:
119 return "lt";
120 default:
121 gcc_unreachable ();
125 static void
126 output_cond_branch (int code, const char *suffix, bool r5_p,
127 bool long_jump_p, rtx *operands)
129 char pattern[256];
130 const char *cond_code;
131 bool align_p = NDS32_ALIGN_P ();
132 const char *align = align_p ? "\t.align\t2\n" : "";
134 if (r5_p && REGNO (operands[2]) == 5 && TARGET_16_BIT)
136 /* This is special case for beqs38 and bnes38,
137 second operand 2 can't be $r5 and it's almost meanless,
138 however it may occur after copy propgation. */
139 if (code == EQ)
141 /* $r5 == $r5 always taken! */
142 if (long_jump_p)
143 snprintf (pattern, sizeof (pattern),
144 "j\t%%3");
145 else
146 snprintf (pattern, sizeof (pattern),
147 "j8\t%%3");
149 else
150 /* Don't output anything since $r5 != $r5 never taken! */
151 pattern[0] = '\0';
153 else if (long_jump_p)
155 int inverse_code = nds32_inverse_cond_code (code);
156 cond_code = nds32_cond_code_str (inverse_code);
158 /* b<cond><suffix> $r0, $r1, .L0
160 b<inverse_cond><suffix> $r0, $r1, .LCB0
161 j .L0
162 .LCB0:
166 b<cond><suffix> $r0, $r1, .L0
168 b<inverse_cond><suffix> $r0, $r1, .LCB0
169 j .L0
170 .LCB0:
172 if (r5_p && TARGET_16_BIT)
174 snprintf (pattern, sizeof (pattern),
175 "b%ss38\t %%2, .LCB%%=\n\tj\t%%3\n%s.LCB%%=:",
176 cond_code, align);
178 else
180 snprintf (pattern, sizeof (pattern),
181 "b%s%s\t%%1, %%2, .LCB%%=\n\tj\t%%3\n%s.LCB%%=:",
182 cond_code, suffix, align);
185 else
187 cond_code = nds32_cond_code_str (code);
188 if (r5_p && TARGET_16_BIT)
190 /* b<cond>s38 $r1, .L0 */
191 snprintf (pattern, sizeof (pattern),
192 "b%ss38\t %%2, %%3", cond_code);
194 else
196 /* b<cond><suffix> $r0, $r1, .L0 */
197 snprintf (pattern, sizeof (pattern),
198 "b%s%s\t%%1, %%2, %%3", cond_code, suffix);
202 output_asm_insn (pattern, operands);
205 static void
206 output_cond_branch_compare_zero (int code, const char *suffix,
207 bool long_jump_p, rtx *operands,
208 bool ta_implied_p)
210 char pattern[256];
211 const char *cond_code;
212 bool align_p = NDS32_ALIGN_P ();
213 const char *align = align_p ? "\t.align\t2\n" : "";
214 if (long_jump_p)
216 int inverse_code = nds32_inverse_cond_code (code);
217 cond_code = nds32_cond_code_str (inverse_code);
219 if (ta_implied_p && TARGET_16_BIT)
221 /* b<cond>z<suffix> .L0
223 b<inverse_cond>z<suffix> .LCB0
224 j .L0
225 .LCB0:
227 snprintf (pattern, sizeof (pattern),
228 "b%sz%s\t.LCB%%=\n\tj\t%%2\n%s.LCB%%=:",
229 cond_code, suffix, align);
231 else
233 /* b<cond>z<suffix> $r0, .L0
235 b<inverse_cond>z<suffix> $r0, .LCB0
236 j .L0
237 .LCB0:
239 snprintf (pattern, sizeof (pattern),
240 "b%sz%s\t%%1, .LCB%%=\n\tj\t%%2\n%s.LCB%%=:",
241 cond_code, suffix, align);
244 else
246 cond_code = nds32_cond_code_str (code);
247 if (ta_implied_p && TARGET_16_BIT)
249 /* b<cond>z<suffix> .L0 */
250 snprintf (pattern, sizeof (pattern),
251 "b%sz%s\t%%2", cond_code, suffix);
253 else
255 /* b<cond>z<suffix> $r0, .L0 */
256 snprintf (pattern, sizeof (pattern),
257 "b%sz%s\t%%1, %%2", cond_code, suffix);
261 output_asm_insn (pattern, operands);
264 /* ------------------------------------------------------------------------ */
266 /* Auxiliary function for expand RTL pattern. */
268 enum nds32_expand_result_type
269 nds32_expand_cbranch (rtx *operands)
271 rtx tmp_reg;
272 enum rtx_code code;
274 code = GET_CODE (operands[0]);
276 /* If operands[2] is (const_int 0),
277 we can use beqz,bnez,bgtz,bgez,bltz,or blez instructions.
278 So we have gcc generate original template rtx. */
279 if (GET_CODE (operands[2]) == CONST_INT)
280 if (INTVAL (operands[2]) == 0)
281 if ((code != GTU)
282 && (code != GEU)
283 && (code != LTU)
284 && (code != LEU))
285 return EXPAND_CREATE_TEMPLATE;
287 /* For other comparison, NDS32 ISA only has slt (Set-on-Less-Than)
288 behavior for the comparison, we might need to generate other
289 rtx patterns to achieve same semantic. */
290 switch (code)
292 case GT:
293 case GTU:
294 if (GET_CODE (operands[2]) == CONST_INT)
296 /* GT reg_A, const_int => !(LT reg_A, const_int + 1) */
297 if (optimize_size || optimize == 0)
298 tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
299 else
300 tmp_reg = gen_reg_rtx (SImode);
302 /* We want to plus 1 into the integer value
303 of operands[2] to create 'slt' instruction.
304 This caculation is performed on the host machine,
305 which may be 64-bit integer.
306 So the meaning of caculation result may be
307 different from the 32-bit nds32 target.
309 For example:
310 0x7fffffff + 0x1 -> 0x80000000,
311 this value is POSITIVE on 64-bit machine,
312 but the expected value on 32-bit nds32 target
313 should be NEGATIVE value.
315 Hence, instead of using GEN_INT(), we use gen_int_mode() to
316 explicitly create SImode constant rtx. */
317 enum rtx_code cmp_code;
319 rtx plus1 = gen_int_mode (INTVAL (operands[2]) + 1, SImode);
320 if (satisfies_constraint_Is15 (plus1))
322 operands[2] = plus1;
323 cmp_code = EQ;
324 if (code == GT)
326 /* GT, use slts instruction */
327 emit_insn (
328 gen_slts_compare (tmp_reg, operands[1], operands[2]));
330 else
332 /* GTU, use slt instruction */
333 emit_insn (
334 gen_slt_compare (tmp_reg, operands[1], operands[2]));
337 else
339 cmp_code = NE;
340 if (code == GT)
342 /* GT, use slts instruction */
343 emit_insn (
344 gen_slts_compare (tmp_reg, operands[2], operands[1]));
346 else
348 /* GTU, use slt instruction */
349 emit_insn (
350 gen_slt_compare (tmp_reg, operands[2], operands[1]));
354 PUT_CODE (operands[0], cmp_code);
355 operands[1] = tmp_reg;
356 operands[2] = const0_rtx;
357 emit_insn (gen_cbranchsi4 (operands[0], operands[1],
358 operands[2], operands[3]));
360 return EXPAND_DONE;
362 else
364 /* GT reg_A, reg_B => LT reg_B, reg_A */
365 if (optimize_size || optimize == 0)
366 tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
367 else
368 tmp_reg = gen_reg_rtx (SImode);
370 if (code == GT)
372 /* GT, use slts instruction */
373 emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1]));
375 else
377 /* GTU, use slt instruction */
378 emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1]));
381 PUT_CODE (operands[0], NE);
382 operands[1] = tmp_reg;
383 operands[2] = const0_rtx;
384 emit_insn (gen_cbranchsi4 (operands[0], operands[1],
385 operands[2], operands[3]));
387 return EXPAND_DONE;
390 case GE:
391 case GEU:
392 /* GE reg_A, reg_B => !(LT reg_A, reg_B) */
393 /* GE reg_A, const_int => !(LT reg_A, const_int) */
394 if (optimize_size || optimize == 0)
395 tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
396 else
397 tmp_reg = gen_reg_rtx (SImode);
399 if (code == GE)
401 /* GE, use slts instruction */
402 emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2]));
404 else
406 /* GEU, use slt instruction */
407 emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2]));
410 PUT_CODE (operands[0], EQ);
411 operands[1] = tmp_reg;
412 operands[2] = const0_rtx;
413 emit_insn (gen_cbranchsi4 (operands[0], operands[1],
414 operands[2], operands[3]));
416 return EXPAND_DONE;
418 case LT:
419 case LTU:
420 /* LT reg_A, reg_B => LT reg_A, reg_B */
421 /* LT reg_A, const_int => LT reg_A, const_int */
422 if (optimize_size || optimize == 0)
423 tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
424 else
425 tmp_reg = gen_reg_rtx (SImode);
427 if (code == LT)
429 /* LT, use slts instruction */
430 emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2]));
432 else
434 /* LTU, use slt instruction */
435 emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2]));
438 PUT_CODE (operands[0], NE);
439 operands[1] = tmp_reg;
440 operands[2] = const0_rtx;
441 emit_insn (gen_cbranchsi4 (operands[0], operands[1],
442 operands[2], operands[3]));
444 return EXPAND_DONE;
446 case LE:
447 case LEU:
448 if (GET_CODE (operands[2]) == CONST_INT)
450 /* LE reg_A, const_int => LT reg_A, const_int + 1 */
451 if (optimize_size || optimize == 0)
452 tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
453 else
454 tmp_reg = gen_reg_rtx (SImode);
456 enum rtx_code cmp_code;
457 /* Note that (le:SI X INT_MAX) is not the same as (lt:SI X INT_MIN).
458 We better have an assert here in case GCC does not properly
459 optimize it away. The INT_MAX here is 0x7fffffff for target. */
460 rtx plus1 = gen_int_mode (INTVAL (operands[2]) + 1, SImode);
461 if (satisfies_constraint_Is15 (plus1))
463 operands[2] = plus1;
464 cmp_code = NE;
465 if (code == LE)
467 /* LE, use slts instruction */
468 emit_insn (
469 gen_slts_compare (tmp_reg, operands[1], operands[2]));
471 else
473 /* LEU, use slt instruction */
474 emit_insn (
475 gen_slt_compare (tmp_reg, operands[1], operands[2]));
478 else
480 cmp_code = EQ;
481 if (code == LE)
483 /* LE, use slts instruction */
484 emit_insn (
485 gen_slts_compare (tmp_reg, operands[2], operands[1]));
487 else
489 /* LEU, use slt instruction */
490 emit_insn (
491 gen_slt_compare (tmp_reg, operands[2], operands[1]));
495 PUT_CODE (operands[0], cmp_code);
496 operands[1] = tmp_reg;
497 operands[2] = const0_rtx;
498 emit_insn (gen_cbranchsi4 (operands[0], operands[1],
499 operands[2], operands[3]));
501 return EXPAND_DONE;
503 else
505 /* LE reg_A, reg_B => !(LT reg_B, reg_A) */
506 if (optimize_size || optimize == 0)
507 tmp_reg = gen_rtx_REG (SImode, TA_REGNUM);
508 else
509 tmp_reg = gen_reg_rtx (SImode);
511 if (code == LE)
513 /* LE, use slts instruction */
514 emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1]));
516 else
518 /* LEU, use slt instruction */
519 emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1]));
522 PUT_CODE (operands[0], EQ);
523 operands[1] = tmp_reg;
524 operands[2] = const0_rtx;
525 emit_insn (gen_cbranchsi4 (operands[0], operands[1],
526 operands[2], operands[3]));
528 return EXPAND_DONE;
531 case EQ:
532 case NE:
533 /* NDS32 ISA has various form for eq/ne behavior no matter
534 what kind of the operand is.
535 So just generate original template rtx. */
537 /* Put operands[2] into register if operands[2] is a large
538 const_int or ISAv2. */
539 if (GET_CODE (operands[2]) == CONST_INT
540 && (!satisfies_constraint_Is11 (operands[2])
541 || TARGET_ISA_V2))
542 operands[2] = force_reg (SImode, operands[2]);
544 return EXPAND_CREATE_TEMPLATE;
546 default:
547 return EXPAND_FAIL;
551 enum nds32_expand_result_type
552 nds32_expand_cstore (rtx *operands)
554 rtx tmp_reg;
555 enum rtx_code code;
557 code = GET_CODE (operands[1]);
559 switch (code)
561 case EQ:
562 case NE:
563 if (GET_CODE (operands[3]) == CONST_INT)
565 /* reg_R = (reg_A == const_int_B)
566 --> xori reg_C, reg_A, const_int_B
567 slti reg_R, reg_C, const_int_1
568 reg_R = (reg_A != const_int_B)
569 --> xori reg_C, reg_A, const_int_B
570 slti reg_R, const_int0, reg_C */
571 tmp_reg = gen_reg_rtx (SImode);
573 /* If the integer value is not in the range of imm15s,
574 we need to force register first because our addsi3 pattern
575 only accept nds32_rimm15s_operand predicate. */
576 rtx new_imm = gen_int_mode (-INTVAL (operands[3]), SImode);
577 if (satisfies_constraint_Is15 (new_imm))
578 emit_insn (gen_addsi3 (tmp_reg, operands[2], new_imm));
579 else
581 if (!(satisfies_constraint_Iu15 (operands[3])
582 || (TARGET_EXT_PERF
583 && satisfies_constraint_It15 (operands[3]))))
584 operands[3] = force_reg (SImode, operands[3]);
585 emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3]));
588 if (code == EQ)
589 emit_insn (gen_slt_eq0 (operands[0], tmp_reg));
590 else
591 emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg));
593 return EXPAND_DONE;
595 else
597 /* reg_R = (reg_A == reg_B)
598 --> xor reg_C, reg_A, reg_B
599 slti reg_R, reg_C, const_int_1
600 reg_R = (reg_A != reg_B)
601 --> xor reg_C, reg_A, reg_B
602 slti reg_R, const_int0, reg_C */
603 tmp_reg = gen_reg_rtx (SImode);
604 emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3]));
605 if (code == EQ)
606 emit_insn (gen_slt_eq0 (operands[0], tmp_reg));
607 else
608 emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg));
610 return EXPAND_DONE;
612 case GT:
613 case GTU:
614 /* reg_R = (reg_A > reg_B) --> slt reg_R, reg_B, reg_A */
615 /* reg_R = (reg_A > const_int_B) --> slt reg_R, const_int_B, reg_A */
616 if (code == GT)
618 /* GT, use slts instruction */
619 emit_insn (gen_slts_compare (operands[0], operands[3], operands[2]));
621 else
623 /* GTU, use slt instruction */
624 emit_insn (gen_slt_compare (operands[0], operands[3], operands[2]));
627 return EXPAND_DONE;
629 case GE:
630 case GEU:
631 if (GET_CODE (operands[3]) == CONST_INT)
633 /* reg_R = (reg_A >= const_int_B)
634 --> movi reg_C, const_int_B - 1
635 slt reg_R, reg_C, reg_A */
636 tmp_reg = gen_reg_rtx (SImode);
638 emit_insn (gen_movsi (tmp_reg,
639 gen_int_mode (INTVAL (operands[3]) - 1,
640 SImode)));
641 if (code == GE)
643 /* GE, use slts instruction */
644 emit_insn (gen_slts_compare (operands[0], tmp_reg, operands[2]));
646 else
648 /* GEU, use slt instruction */
649 emit_insn (gen_slt_compare (operands[0], tmp_reg, operands[2]));
652 return EXPAND_DONE;
654 else
656 /* reg_R = (reg_A >= reg_B)
657 --> slt reg_R, reg_A, reg_B
658 xori reg_R, reg_R, const_int_1 */
659 if (code == GE)
661 /* GE, use slts instruction */
662 emit_insn (gen_slts_compare (operands[0],
663 operands[2], operands[3]));
665 else
667 /* GEU, use slt instruction */
668 emit_insn (gen_slt_compare (operands[0],
669 operands[2], operands[3]));
672 /* perform 'not' behavior */
673 emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
675 return EXPAND_DONE;
678 case LT:
679 case LTU:
680 /* reg_R = (reg_A < reg_B) --> slt reg_R, reg_A, reg_B */
681 /* reg_R = (reg_A < const_int_B) --> slt reg_R, reg_A, const_int_B */
682 if (code == LT)
684 /* LT, use slts instruction */
685 emit_insn (gen_slts_compare (operands[0], operands[2], operands[3]));
687 else
689 /* LTU, use slt instruction */
690 emit_insn (gen_slt_compare (operands[0], operands[2], operands[3]));
693 return EXPAND_DONE;
695 case LE:
696 case LEU:
697 if (GET_CODE (operands[3]) == CONST_INT)
699 /* reg_R = (reg_A <= const_int_B)
700 --> movi reg_C, const_int_B + 1
701 slt reg_R, reg_A, reg_C */
702 tmp_reg = gen_reg_rtx (SImode);
704 emit_insn (gen_movsi (tmp_reg,
705 gen_int_mode (INTVAL (operands[3]) + 1,
706 SImode)));
707 if (code == LE)
709 /* LE, use slts instruction */
710 emit_insn (gen_slts_compare (operands[0], operands[2], tmp_reg));
712 else
714 /* LEU, use slt instruction */
715 emit_insn (gen_slt_compare (operands[0], operands[2], tmp_reg));
718 return EXPAND_DONE;
720 else
722 /* reg_R = (reg_A <= reg_B) --> slt reg_R, reg_B, reg_A
723 xori reg_R, reg_R, const_int_1 */
724 if (code == LE)
726 /* LE, use slts instruction */
727 emit_insn (gen_slts_compare (operands[0],
728 operands[3], operands[2]));
730 else
732 /* LEU, use slt instruction */
733 emit_insn (gen_slt_compare (operands[0],
734 operands[3], operands[2]));
737 /* perform 'not' behavior */
738 emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
740 return EXPAND_DONE;
744 default:
745 gcc_unreachable ();
749 void
750 nds32_expand_float_cbranch (rtx *operands)
752 enum rtx_code code = GET_CODE (operands[0]);
753 enum rtx_code new_code = code;
754 rtx cmp_op0 = operands[1];
755 rtx cmp_op1 = operands[2];
756 rtx tmp_reg;
757 rtx tmp;
759 int reverse = 0;
761 /* Main Goal: Use compare instruction + branch instruction.
763 For example:
764 GT, GE: swap condition and swap operands and generate
765 compare instruction(LT, LE) + branch not equal instruction.
767 UNORDERED, LT, LE, EQ: no need to change and generate
768 compare instruction(UNORDERED, LT, LE, EQ) + branch not equal instruction.
770 ORDERED, NE: reverse condition and generate
771 compare instruction(EQ) + branch equal instruction. */
773 switch (code)
775 case GT:
776 case GE:
777 tmp = cmp_op0;
778 cmp_op0 = cmp_op1;
779 cmp_op1 = tmp;
780 new_code = swap_condition (new_code);
781 break;
782 case UNORDERED:
783 case LT:
784 case LE:
785 case EQ:
786 break;
787 case ORDERED:
788 case NE:
789 new_code = reverse_condition (new_code);
790 reverse = 1;
791 break;
792 case UNGT:
793 case UNGE:
794 new_code = reverse_condition_maybe_unordered (new_code);
795 reverse = 1;
796 break;
797 case UNLT:
798 case UNLE:
799 new_code = reverse_condition_maybe_unordered (new_code);
800 tmp = cmp_op0;
801 cmp_op0 = cmp_op1;
802 cmp_op1 = tmp;
803 new_code = swap_condition (new_code);
804 reverse = 1;
805 break;
806 default:
807 return;
810 tmp_reg = gen_reg_rtx (SImode);
811 emit_insn (gen_rtx_SET (tmp_reg,
812 gen_rtx_fmt_ee (new_code, SImode,
813 cmp_op0, cmp_op1)));
815 PUT_CODE (operands[0], reverse ? EQ : NE);
816 emit_insn (gen_cbranchsi4 (operands[0], tmp_reg,
817 const0_rtx, operands[3]));
820 void
821 nds32_expand_float_cstore (rtx *operands)
823 enum rtx_code code = GET_CODE (operands[1]);
824 enum rtx_code new_code = code;
825 machine_mode mode = GET_MODE (operands[2]);
827 rtx cmp_op0 = operands[2];
828 rtx cmp_op1 = operands[3];
829 rtx tmp;
831 /* Main Goal: Use compare instruction to store value.
833 For example:
834 GT, GE: swap condition and swap operands.
835 reg_R = (reg_A > reg_B) --> fcmplt reg_R, reg_B, reg_A
836 reg_R = (reg_A >= reg_B) --> fcmple reg_R, reg_B, reg_A
838 LT, LE, EQ: no need to change, it is already LT, LE, EQ.
839 reg_R = (reg_A < reg_B) --> fcmplt reg_R, reg_A, reg_B
840 reg_R = (reg_A <= reg_B) --> fcmple reg_R, reg_A, reg_B
841 reg_R = (reg_A == reg_B) --> fcmpeq reg_R, reg_A, reg_B
843 ORDERED: reverse condition and using xor insturction to achieve 'ORDERED'.
844 reg_R = (reg_A != reg_B) --> fcmpun reg_R, reg_A, reg_B
845 xor reg_R, reg_R, const1_rtx
847 NE: reverse condition and using xor insturction to achieve 'NE'.
848 reg_R = (reg_A != reg_B) --> fcmpeq reg_R, reg_A, reg_B
849 xor reg_R, reg_R, const1_rtx */
850 switch (code)
852 case GT:
853 case GE:
854 tmp = cmp_op0;
855 cmp_op0 = cmp_op1;
856 cmp_op1 =tmp;
857 new_code = swap_condition (new_code);
858 break;
859 case UNORDERED:
860 case LT:
861 case LE:
862 case EQ:
863 break;
864 case ORDERED:
865 if (mode == SFmode)
866 emit_insn (gen_cmpsf_un (operands[0], cmp_op0, cmp_op1));
867 else
868 emit_insn (gen_cmpdf_un (operands[0], cmp_op0, cmp_op1));
870 emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
871 return;
872 case NE:
873 if (mode == SFmode)
874 emit_insn (gen_cmpsf_eq (operands[0], cmp_op0, cmp_op1));
875 else
876 emit_insn (gen_cmpdf_eq (operands[0], cmp_op0, cmp_op1));
878 emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
879 return;
880 default:
881 return;
884 emit_insn (gen_rtx_SET (operands[0],
885 gen_rtx_fmt_ee (new_code, SImode,
886 cmp_op0, cmp_op1)));
889 enum nds32_expand_result_type
890 nds32_expand_movcc (rtx *operands)
892 enum rtx_code code = GET_CODE (operands[1]);
893 enum rtx_code new_code = code;
894 machine_mode cmp0_mode = GET_MODE (XEXP (operands[1], 0));
895 rtx cmp_op0 = XEXP (operands[1], 0);
896 rtx cmp_op1 = XEXP (operands[1], 1);
897 rtx tmp;
899 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
900 && XEXP (operands[1], 1) == const0_rtx)
902 /* If the operands[1] rtx is already (eq X 0) or (ne X 0),
903 we have gcc generate original template rtx. */
904 return EXPAND_CREATE_TEMPLATE;
906 else if ((TARGET_FPU_SINGLE && cmp0_mode == SFmode)
907 || (TARGET_FPU_DOUBLE && cmp0_mode == DFmode))
909 nds32_expand_float_movcc (operands);
911 else
913 /* Since there is only 'slt'(Set when Less Than) instruction for
914 comparison in Andes ISA, the major strategy we use here is to
915 convert conditional move into 'LT + EQ' or 'LT + NE' rtx combination.
916 We design constraints properly so that the reload phase will assist
917 to make one source operand to use same register as result operand.
918 Then we can use cmovz/cmovn to catch the other source operand
919 which has different register. */
920 int reverse = 0;
922 /* Main Goal: Use 'LT + EQ' or 'LT + NE' to target "then" part
923 Strategy : Reverse condition and swap comparison operands
925 For example:
927 a <= b ? P : Q (LE or LEU)
928 --> a > b ? Q : P (reverse condition)
929 --> b < a ? Q : P (swap comparison operands to achieve 'LT/LTU')
931 a >= b ? P : Q (GE or GEU)
932 --> a < b ? Q : P (reverse condition to achieve 'LT/LTU')
934 a < b ? P : Q (LT or LTU)
935 --> (NO NEED TO CHANGE, it is already 'LT/LTU')
937 a > b ? P : Q (GT or GTU)
938 --> b < a ? P : Q (swap comparison operands to achieve 'LT/LTU') */
939 switch (code)
941 case GE: case GEU: case LE: case LEU:
942 new_code = reverse_condition (code);
943 reverse = 1;
944 break;
945 case EQ:
946 case NE:
947 /* no need to reverse condition */
948 break;
949 default:
950 return EXPAND_FAIL;
953 /* For '>' comparison operator, we swap operands
954 so that we can have 'LT/LTU' operator. */
955 if (new_code == GT || new_code == GTU)
957 tmp = cmp_op0;
958 cmp_op0 = cmp_op1;
959 cmp_op1 = tmp;
961 new_code = swap_condition (new_code);
964 /* Use a temporary register to store slt/slts result. */
965 tmp = gen_reg_rtx (SImode);
967 if (new_code == EQ || new_code == NE)
969 emit_insn (gen_xorsi3 (tmp, cmp_op0, cmp_op1));
970 /* tmp == 0 if cmp_op0 == cmp_op1. */
971 operands[1] = gen_rtx_fmt_ee (new_code, VOIDmode, tmp, const0_rtx);
973 else
975 /* This emit_insn will create corresponding 'slt/slts'
976 insturction. */
977 if (new_code == LT)
978 emit_insn (gen_slts_compare (tmp, cmp_op0, cmp_op1));
979 else if (new_code == LTU)
980 emit_insn (gen_slt_compare (tmp, cmp_op0, cmp_op1));
981 else
982 gcc_unreachable ();
984 /* Change comparison semantic into (eq X 0) or (ne X 0) behavior
985 so that cmovz or cmovn will be matched later.
987 For reverse condition cases, we want to create a semantic that:
988 (eq X 0) --> pick up "else" part
989 For normal cases, we want to create a semantic that:
990 (ne X 0) --> pick up "then" part
992 Later we will have cmovz/cmovn instruction pattern to
993 match corresponding behavior and output instruction. */
994 operands[1] = gen_rtx_fmt_ee (reverse ? EQ : NE,
995 VOIDmode, tmp, const0_rtx);
998 return EXPAND_CREATE_TEMPLATE;
1001 void
1002 nds32_expand_float_movcc (rtx *operands)
1004 if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
1005 && GET_MODE (XEXP (operands[1], 0)) == SImode
1006 && XEXP (operands[1], 1) == const0_rtx)
1008 /* If the operands[1] rtx is already (eq X 0) or (ne X 0),
1009 we have gcc generate original template rtx. */
1010 return;
1012 else
1014 enum rtx_code code = GET_CODE (operands[1]);
1015 enum rtx_code new_code = code;
1016 machine_mode cmp0_mode = GET_MODE (XEXP (operands[1], 0));
1017 machine_mode cmp1_mode = GET_MODE (XEXP (operands[1], 1));
1018 rtx cmp_op0 = XEXP (operands[1], 0);
1019 rtx cmp_op1 = XEXP (operands[1], 1);
1020 rtx tmp;
1022 /* Compare instruction Operations: (cmp_op0 condition cmp_op1) ? 1 : 0,
1023 when result is 1, and 'reverse' be set 1 for fcmovzs instructuin. */
1024 int reverse = 0;
1026 /* Main Goal: Use cmpare instruction + conditional move instruction.
1027 Strategy : swap condition and swap comparison operands.
1029 For example:
1030 a > b ? P : Q (GT)
1031 --> a < b ? Q : P (swap condition)
1032 --> b < a ? Q : P (swap comparison operands to achieve 'GT')
1034 a >= b ? P : Q (GE)
1035 --> a <= b ? Q : P (swap condition)
1036 --> b <= a ? Q : P (swap comparison operands to achieve 'GE')
1038 a < b ? P : Q (LT)
1039 --> (NO NEED TO CHANGE, it is already 'LT')
1041 a >= b ? P : Q (LE)
1042 --> (NO NEED TO CHANGE, it is already 'LE')
1044 a == b ? P : Q (EQ)
1045 --> (NO NEED TO CHANGE, it is already 'EQ') */
1047 switch (code)
1049 case GT:
1050 case GE:
1051 tmp = cmp_op0;
1052 cmp_op0 = cmp_op1;
1053 cmp_op1 =tmp;
1054 new_code = swap_condition (new_code);
1055 break;
1056 case UNORDERED:
1057 case LT:
1058 case LE:
1059 case EQ:
1060 break;
1061 case ORDERED:
1062 case NE:
1063 reverse = 1;
1064 new_code = reverse_condition (new_code);
1065 break;
1066 case UNGT:
1067 case UNGE:
1068 new_code = reverse_condition_maybe_unordered (new_code);
1069 reverse = 1;
1070 break;
1071 case UNLT:
1072 case UNLE:
1073 new_code = reverse_condition_maybe_unordered (new_code);
1074 tmp = cmp_op0;
1075 cmp_op0 = cmp_op1;
1076 cmp_op1 = tmp;
1077 new_code = swap_condition (new_code);
1078 reverse = 1;
1079 break;
1080 default:
1081 return;
1084 /* Use a temporary register to store fcmpxxs result. */
1085 tmp = gen_reg_rtx (SImode);
1087 /* Create float compare instruction for SFmode and DFmode,
1088 other MODE using cstoresi create compare instruction. */
1089 if ((cmp0_mode == DFmode || cmp0_mode == SFmode)
1090 && (cmp1_mode == DFmode || cmp1_mode == SFmode))
1092 /* This emit_insn create corresponding float compare instruction */
1093 emit_insn (gen_rtx_SET (tmp,
1094 gen_rtx_fmt_ee (new_code, SImode,
1095 cmp_op0, cmp_op1)));
1097 else
1099 /* This emit_insn using cstoresi create corresponding
1100 compare instruction */
1101 PUT_CODE (operands[1], new_code);
1102 emit_insn (gen_cstoresi4 (tmp, operands[1],
1103 cmp_op0, cmp_op1));
1105 /* operands[1] crete corresponding condition move instruction
1106 for fcmovzs and fcmovns. */
1107 operands[1] = gen_rtx_fmt_ee (reverse ? EQ : NE,
1108 VOIDmode, tmp, const0_rtx);
1112 void
1113 nds32_emit_push_fpr_callee_saved (int base_offset)
1115 rtx fpu_insn;
1116 rtx reg, mem;
1117 unsigned int regno = cfun->machine->callee_saved_first_fpr_regno;
1118 unsigned int last_fpr = cfun->machine->callee_saved_last_fpr_regno;
1120 while (regno <= last_fpr)
1122 /* Handling two registers, using fsdi instruction. */
1123 reg = gen_rtx_REG (DFmode, regno);
1124 mem = gen_frame_mem (DFmode, plus_constant (Pmode,
1125 stack_pointer_rtx,
1126 base_offset));
1127 base_offset += 8;
1128 regno += 2;
1129 fpu_insn = emit_move_insn (mem, reg);
1130 RTX_FRAME_RELATED_P (fpu_insn) = 1;
1134 void
1135 nds32_emit_pop_fpr_callee_saved (int gpr_padding_size)
1137 rtx fpu_insn;
1138 rtx reg, mem, addr;
1139 rtx dwarf, adjust_sp_rtx;
1140 unsigned int regno = cfun->machine->callee_saved_first_fpr_regno;
1141 unsigned int last_fpr = cfun->machine->callee_saved_last_fpr_regno;
1142 int padding = 0;
1144 while (regno <= last_fpr)
1146 /* Handling two registers, using fldi.bi instruction. */
1147 if ((regno + 1) >= last_fpr)
1148 padding = gpr_padding_size;
1150 reg = gen_rtx_REG (DFmode, (regno));
1151 addr = gen_rtx_POST_MODIFY (Pmode, stack_pointer_rtx,
1152 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1153 GEN_INT (8 + padding)));
1154 mem = gen_frame_mem (DFmode, addr);
1155 regno += 2;
1156 fpu_insn = emit_move_insn (reg, mem);
1158 adjust_sp_rtx =
1159 gen_rtx_SET (stack_pointer_rtx,
1160 plus_constant (Pmode, stack_pointer_rtx,
1161 8 + padding));
1163 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, NULL_RTX);
1164 /* Tell gcc we adjust SP in this insn. */
1165 dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, copy_rtx (adjust_sp_rtx),
1166 dwarf);
1167 RTX_FRAME_RELATED_P (fpu_insn) = 1;
1168 REG_NOTES (fpu_insn) = dwarf;
1172 void
1173 nds32_emit_v3pop_fpr_callee_saved (int base)
1175 int fpu_base_addr = base;
1176 int regno;
1177 rtx fpu_insn;
1178 rtx reg, mem;
1179 rtx dwarf;
1181 regno = cfun->machine->callee_saved_first_fpr_regno;
1182 while (regno <= cfun->machine->callee_saved_last_fpr_regno)
1184 /* Handling two registers, using fldi instruction. */
1185 reg = gen_rtx_REG (DFmode, regno);
1186 mem = gen_frame_mem (DFmode, plus_constant (Pmode,
1187 stack_pointer_rtx,
1188 fpu_base_addr));
1189 fpu_base_addr += 8;
1190 regno += 2;
1191 fpu_insn = emit_move_insn (reg, mem);
1192 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, NULL_RTX);
1193 RTX_FRAME_RELATED_P (fpu_insn) = 1;
1194 REG_NOTES (fpu_insn) = dwarf;
1198 /* ------------------------------------------------------------------------ */
1200 /* Function to return memory format. */
1201 enum nds32_16bit_address_type
1202 nds32_mem_format (rtx op)
1204 machine_mode mode_test;
1205 int val;
1206 int regno;
1208 if (!TARGET_16_BIT)
1209 return ADDRESS_NOT_16BIT_FORMAT;
1211 mode_test = GET_MODE (op);
1213 op = XEXP (op, 0);
1215 /* 45 format. */
1216 if (GET_CODE (op) == REG
1217 && ((mode_test == SImode) || (mode_test == SFmode)))
1218 return ADDRESS_REG;
1220 /* 333 format for QI/HImode. */
1221 if (GET_CODE (op) == REG && (REGNO (op) < R8_REGNUM))
1222 return ADDRESS_LO_REG_IMM3U;
1224 /* post_inc 333 format. */
1225 if ((GET_CODE (op) == POST_INC)
1226 && ((mode_test == SImode) || (mode_test == SFmode)))
1228 regno = REGNO(XEXP (op, 0));
1230 if (regno < 8)
1231 return ADDRESS_POST_INC_LO_REG_IMM3U;
1234 /* post_inc 333 format. */
1235 if ((GET_CODE (op) == POST_MODIFY)
1236 && ((mode_test == SImode) || (mode_test == SFmode))
1237 && (REG_P (XEXP (XEXP (op, 1), 0)))
1238 && (CONST_INT_P (XEXP (XEXP (op, 1), 1))))
1240 regno = REGNO (XEXP (XEXP (op, 1), 0));
1241 val = INTVAL (XEXP (XEXP (op, 1), 1));
1242 if (regno < 8 && val > 0 && val < 32)
1243 return ADDRESS_POST_MODIFY_LO_REG_IMM3U;
1246 if ((GET_CODE (op) == PLUS)
1247 && (GET_CODE (XEXP (op, 0)) == REG)
1248 && (GET_CODE (XEXP (op, 1)) == CONST_INT))
1250 val = INTVAL (XEXP (op, 1));
1252 regno = REGNO(XEXP (op, 0));
1254 if (regno > 8
1255 && regno != SP_REGNUM
1256 && regno != FP_REGNUM)
1257 return ADDRESS_NOT_16BIT_FORMAT;
1259 switch (mode_test)
1261 case E_QImode:
1262 /* 333 format. */
1263 if (val >= 0 && val < 8 && regno < 8)
1264 return ADDRESS_LO_REG_IMM3U;
1265 break;
1267 case E_HImode:
1268 /* 333 format. */
1269 if (val >= 0 && val < 16 && (val % 2 == 0) && regno < 8)
1270 return ADDRESS_LO_REG_IMM3U;
1271 break;
1273 case E_SImode:
1274 case E_SFmode:
1275 case E_DFmode:
1276 /* r8 imply fe format. */
1277 if ((regno == 8) &&
1278 (val >= -128 && val <= -4 && (val % 4 == 0)))
1279 return ADDRESS_R8_IMM7U;
1280 /* fp imply 37 format. */
1281 if ((regno == FP_REGNUM) &&
1282 (val >= 0 && val < 512 && (val % 4 == 0)))
1283 return ADDRESS_FP_IMM7U;
1284 /* sp imply 37 format. */
1285 else if ((regno == SP_REGNUM) &&
1286 (val >= 0 && val < 512 && (val % 4 == 0)))
1287 return ADDRESS_SP_IMM7U;
1288 /* 333 format. */
1289 else if (val >= 0 && val < 32 && (val % 4 == 0) && regno < 8)
1290 return ADDRESS_LO_REG_IMM3U;
1291 break;
1293 default:
1294 break;
1298 return ADDRESS_NOT_16BIT_FORMAT;
1301 /* Output 16-bit store. */
1302 const char *
1303 nds32_output_16bit_store (rtx *operands, int byte)
1305 char pattern[100];
1306 char size;
1307 rtx code = XEXP (operands[0], 0);
1309 size = nds32_byte_to_size (byte);
1311 switch (nds32_mem_format (operands[0]))
1313 case ADDRESS_REG:
1314 operands[0] = code;
1315 output_asm_insn ("swi450\t%1, [%0]", operands);
1316 break;
1317 case ADDRESS_LO_REG_IMM3U:
1318 snprintf (pattern, sizeof (pattern), "s%ci333\t%%1, %%0", size);
1319 output_asm_insn (pattern, operands);
1320 break;
1321 case ADDRESS_POST_INC_LO_REG_IMM3U:
1322 snprintf (pattern, sizeof (pattern), "swi333.bi\t%%1, %%0, 4");
1323 output_asm_insn (pattern, operands);
1324 break;
1325 case ADDRESS_POST_MODIFY_LO_REG_IMM3U:
1326 snprintf (pattern, sizeof (pattern), "swi333.bi\t%%1, %%0");
1327 output_asm_insn (pattern, operands);
1328 break;
1329 case ADDRESS_FP_IMM7U:
1330 output_asm_insn ("swi37\t%1, %0", operands);
1331 break;
1332 case ADDRESS_SP_IMM7U:
1333 /* Get immediate value and set back to operands[1]. */
1334 operands[0] = XEXP (code, 1);
1335 output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands);
1336 break;
1337 default:
1338 break;
1341 return "";
1344 /* Output 16-bit load. */
1345 const char *
1346 nds32_output_16bit_load (rtx *operands, int byte)
1348 char pattern[100];
1349 unsigned char size;
1350 rtx code = XEXP (operands[1], 0);
1352 size = nds32_byte_to_size (byte);
1354 switch (nds32_mem_format (operands[1]))
1356 case ADDRESS_REG:
1357 operands[1] = code;
1358 output_asm_insn ("lwi450\t%0, [%1]", operands);
1359 break;
1360 case ADDRESS_LO_REG_IMM3U:
1361 snprintf (pattern, sizeof (pattern), "l%ci333\t%%0, %%1", size);
1362 output_asm_insn (pattern, operands);
1363 break;
1364 case ADDRESS_POST_INC_LO_REG_IMM3U:
1365 snprintf (pattern, sizeof (pattern), "lwi333.bi\t%%0, %%1, 4");
1366 output_asm_insn (pattern, operands);
1367 break;
1368 case ADDRESS_POST_MODIFY_LO_REG_IMM3U:
1369 snprintf (pattern, sizeof (pattern), "lwi333.bi\t%%0, %%1");
1370 output_asm_insn (pattern, operands);
1371 break;
1372 case ADDRESS_R8_IMM7U:
1373 output_asm_insn ("lwi45.fe\t%0, %e1", operands);
1374 break;
1375 case ADDRESS_FP_IMM7U:
1376 output_asm_insn ("lwi37\t%0, %1", operands);
1377 break;
1378 case ADDRESS_SP_IMM7U:
1379 /* Get immediate value and set back to operands[0]. */
1380 operands[1] = XEXP (code, 1);
1381 output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands);
1382 break;
1383 default:
1384 break;
1387 return "";
1390 /* Output 32-bit store. */
1391 const char *
1392 nds32_output_32bit_store (rtx *operands, int byte)
1394 char pattern[100];
1395 unsigned char size;
1396 rtx code = XEXP (operands[0], 0);
1398 size = nds32_byte_to_size (byte);
1400 switch (GET_CODE (code))
1402 case REG:
1403 /* (mem (reg X))
1404 => access location by using register,
1405 use "sbi / shi / swi" */
1406 snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size);
1407 break;
1409 case SYMBOL_REF:
1410 case CONST:
1411 /* (mem (symbol_ref X))
1412 (mem (const (...)))
1413 => access global variables,
1414 use "sbi.gp / shi.gp / swi.gp" */
1415 operands[0] = XEXP (operands[0], 0);
1416 snprintf (pattern, sizeof (pattern), "s%ci.gp\t%%1, [ + %%0]", size);
1417 break;
1419 case POST_INC:
1420 /* (mem (post_inc reg))
1421 => access location by using register which will be post increment,
1422 use "sbi.bi / shi.bi / swi.bi" */
1423 snprintf (pattern, sizeof (pattern),
1424 "s%ci.bi\t%%1, %%0, %d", size, byte);
1425 break;
1427 case POST_DEC:
1428 /* (mem (post_dec reg))
1429 => access location by using register which will be post decrement,
1430 use "sbi.bi / shi.bi / swi.bi" */
1431 snprintf (pattern, sizeof (pattern),
1432 "s%ci.bi\t%%1, %%0, -%d", size, byte);
1433 break;
1435 case POST_MODIFY:
1436 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
1438 case REG:
1439 case SUBREG:
1440 /* (mem (post_modify (reg) (plus (reg) (reg))))
1441 => access location by using register which will be
1442 post modified with reg,
1443 use "sb.bi/ sh.bi / sw.bi" */
1444 snprintf (pattern, sizeof (pattern), "s%c.bi\t%%1, %%0", size);
1445 break;
1446 case CONST_INT:
1447 /* (mem (post_modify (reg) (plus (reg) (const_int))))
1448 => access location by using register which will be
1449 post modified with const_int,
1450 use "sbi.bi/ shi.bi / swi.bi" */
1451 snprintf (pattern, sizeof (pattern), "s%ci.bi\t%%1, %%0", size);
1452 break;
1453 default:
1454 abort ();
1456 break;
1458 case PLUS:
1459 switch (GET_CODE (XEXP (code, 1)))
1461 case REG:
1462 case SUBREG:
1463 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
1464 => access location by adding two registers,
1465 use "sb / sh / sw" */
1466 snprintf (pattern, sizeof (pattern), "s%c\t%%1, %%0", size);
1467 break;
1468 case CONST_INT:
1469 /* (mem (plus reg const_int))
1470 => access location by adding one register with const_int,
1471 use "sbi / shi / swi" */
1472 snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size);
1473 break;
1474 default:
1475 abort ();
1477 break;
1479 case LO_SUM:
1480 operands[2] = XEXP (code, 1);
1481 operands[0] = XEXP (code, 0);
1482 snprintf (pattern, sizeof (pattern),
1483 "s%ci\t%%1, [%%0 + lo12(%%2)]", size);
1484 break;
1486 default:
1487 abort ();
1490 output_asm_insn (pattern, operands);
1491 return "";
1494 /* Output 32-bit load. */
1495 const char *
1496 nds32_output_32bit_load (rtx *operands, int byte)
1498 char pattern[100];
1499 unsigned char size;
1500 rtx code;
1502 code = XEXP (operands[1], 0);
1504 size = nds32_byte_to_size (byte);
1506 switch (GET_CODE (code))
1508 case REG:
1509 /* (mem (reg X))
1510 => access location by using register,
1511 use "lbi / lhi / lwi" */
1512 snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size);
1513 break;
1515 case SYMBOL_REF:
1516 case CONST:
1517 /* (mem (symbol_ref X))
1518 (mem (const (...)))
1519 => access global variables,
1520 use "lbi.gp / lhi.gp / lwi.gp" */
1521 operands[1] = XEXP (operands[1], 0);
1522 snprintf (pattern, sizeof (pattern), "l%ci.gp\t%%0, [ + %%1]", size);
1523 break;
1525 case POST_INC:
1526 /* (mem (post_inc reg))
1527 => access location by using register which will be post increment,
1528 use "lbi.bi / lhi.bi / lwi.bi" */
1529 snprintf (pattern, sizeof (pattern),
1530 "l%ci.bi\t%%0, %%1, %d", size, byte);
1531 break;
1533 case POST_DEC:
1534 /* (mem (post_dec reg))
1535 => access location by using register which will be post decrement,
1536 use "lbi.bi / lhi.bi / lwi.bi" */
1537 snprintf (pattern, sizeof (pattern),
1538 "l%ci.bi\t%%0, %%1, -%d", size, byte);
1539 break;
1541 case POST_MODIFY:
1542 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
1544 case REG:
1545 case SUBREG:
1546 /* (mem (post_modify (reg) (plus (reg) (reg))))
1547 => access location by using register which will be
1548 post modified with reg,
1549 use "lb.bi/ lh.bi / lw.bi" */
1550 snprintf (pattern, sizeof (pattern), "l%c.bi\t%%0, %%1", size);
1551 break;
1552 case CONST_INT:
1553 /* (mem (post_modify (reg) (plus (reg) (const_int))))
1554 => access location by using register which will be
1555 post modified with const_int,
1556 use "lbi.bi/ lhi.bi / lwi.bi" */
1557 snprintf (pattern, sizeof (pattern), "l%ci.bi\t%%0, %%1", size);
1558 break;
1559 default:
1560 abort ();
1562 break;
1564 case PLUS:
1565 switch (GET_CODE (XEXP (code, 1)))
1567 case REG:
1568 case SUBREG:
1569 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
1570 use "lb / lh / lw" */
1571 snprintf (pattern, sizeof (pattern), "l%c\t%%0, %%1", size);
1572 break;
1573 case CONST_INT:
1574 /* (mem (plus reg const_int))
1575 => access location by adding one register with const_int,
1576 use "lbi / lhi / lwi" */
1577 snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size);
1578 break;
1579 default:
1580 abort ();
1582 break;
1584 case LO_SUM:
1585 operands[2] = XEXP (code, 1);
1586 operands[1] = XEXP (code, 0);
1587 snprintf (pattern, sizeof (pattern),
1588 "l%ci\t%%0, [%%1 + lo12(%%2)]", size);
1589 break;
1591 default:
1592 abort ();
1595 output_asm_insn (pattern, operands);
1596 return "";
1599 /* Output 32-bit load with signed extension. */
1600 const char *
1601 nds32_output_32bit_load_s (rtx *operands, int byte)
1603 char pattern[100];
1604 unsigned char size;
1605 rtx code;
1607 code = XEXP (operands[1], 0);
1609 size = nds32_byte_to_size (byte);
1611 switch (GET_CODE (code))
1613 case REG:
1614 /* (mem (reg X))
1615 => access location by using register,
1616 use "lbsi / lhsi" */
1617 snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size);
1618 break;
1620 case SYMBOL_REF:
1621 case CONST:
1622 /* (mem (symbol_ref X))
1623 (mem (const (...)))
1624 => access global variables,
1625 use "lbsi.gp / lhsi.gp" */
1626 operands[1] = XEXP (operands[1], 0);
1627 snprintf (pattern, sizeof (pattern), "l%csi.gp\t%%0, [ + %%1]", size);
1628 break;
1630 case POST_INC:
1631 /* (mem (post_inc reg))
1632 => access location by using register which will be post increment,
1633 use "lbsi.bi / lhsi.bi" */
1634 snprintf (pattern, sizeof (pattern),
1635 "l%csi.bi\t%%0, %%1, %d", size, byte);
1636 break;
1638 case POST_DEC:
1639 /* (mem (post_dec reg))
1640 => access location by using register which will be post decrement,
1641 use "lbsi.bi / lhsi.bi" */
1642 snprintf (pattern, sizeof (pattern),
1643 "l%csi.bi\t%%0, %%1, -%d", size, byte);
1644 break;
1646 case POST_MODIFY:
1647 switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
1649 case REG:
1650 case SUBREG:
1651 /* (mem (post_modify (reg) (plus (reg) (reg))))
1652 => access location by using register which will be
1653 post modified with reg,
1654 use "lbs.bi/ lhs.bi" */
1655 snprintf (pattern, sizeof (pattern), "l%cs.bi\t%%0, %%1", size);
1656 break;
1657 case CONST_INT:
1658 /* (mem (post_modify (reg) (plus (reg) (const_int))))
1659 => access location by using register which will be
1660 post modified with const_int,
1661 use "lbsi.bi/ lhsi.bi" */
1662 snprintf (pattern, sizeof (pattern), "l%csi.bi\t%%0, %%1", size);
1663 break;
1664 default:
1665 abort ();
1667 break;
1669 case PLUS:
1670 switch (GET_CODE (XEXP (code, 1)))
1672 case REG:
1673 case SUBREG:
1674 /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg))
1675 use "lbs / lhs" */
1676 snprintf (pattern, sizeof (pattern), "l%cs\t%%0, %%1", size);
1677 break;
1678 case CONST_INT:
1679 /* (mem (plus reg const_int))
1680 => access location by adding one register with const_int,
1681 use "lbsi / lhsi" */
1682 snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size);
1683 break;
1684 default:
1685 abort ();
1687 break;
1689 case LO_SUM:
1690 operands[2] = XEXP (code, 1);
1691 operands[1] = XEXP (code, 0);
1692 snprintf (pattern, sizeof (pattern),
1693 "l%csi\t%%0, [%%1 + lo12(%%2)]", size);
1694 break;
1696 default:
1697 abort ();
1700 output_asm_insn (pattern, operands);
1701 return "";
1704 /* Function to output stack push operation.
1705 We need to deal with normal stack push multiple or stack v3push. */
1706 const char *
1707 nds32_output_stack_push (rtx par_rtx)
1709 /* A string pattern for output_asm_insn(). */
1710 char pattern[100];
1711 /* The operands array which will be used in output_asm_insn(). */
1712 rtx operands[3];
1713 /* Pick up varargs first regno and last regno for further use. */
1714 int rb_va_args = cfun->machine->va_args_first_regno;
1715 int re_va_args = cfun->machine->va_args_last_regno;
1716 int last_argument_regno = NDS32_FIRST_GPR_REGNUM
1717 + NDS32_MAX_GPR_REGS_FOR_ARGS
1718 - 1;
1719 /* Pick up first and last eh data regno for further use. */
1720 int rb_eh_data = cfun->machine->eh_return_data_first_regno;
1721 int re_eh_data = cfun->machine->eh_return_data_last_regno;
1722 int first_eh_data_regno = EH_RETURN_DATA_REGNO (0);
1723 /* Pick up callee-saved first regno and last regno for further use. */
1724 int rb_callee_saved = cfun->machine->callee_saved_first_gpr_regno;
1725 int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno;
1727 /* First we need to check if we are pushing argument registers not used
1728 for the named arguments. If so, we have to create 'smw.adm' (push.s)
1729 instruction. */
1730 if (reg_mentioned_p (gen_rtx_REG (SImode, last_argument_regno), par_rtx))
1732 /* Set operands[0] and operands[1]. */
1733 operands[0] = gen_rtx_REG (SImode, rb_va_args);
1734 operands[1] = gen_rtx_REG (SImode, re_va_args);
1735 /* Create assembly code pattern: "Rb, Re, { }". */
1736 snprintf (pattern, sizeof (pattern), "push.s\t%s", "%0, %1, { }");
1737 /* We use output_asm_insn() to output assembly code by ourself. */
1738 output_asm_insn (pattern, operands);
1739 return "";
1742 /* If last_argument_regno is not mentioned in par_rtx, we can confirm that
1743 we do not need to push argument registers for variadic function.
1744 But we still need to check if we need to push exception handling
1745 data registers. */
1746 if (reg_mentioned_p (gen_rtx_REG (SImode, first_eh_data_regno), par_rtx))
1748 /* Set operands[0] and operands[1]. */
1749 operands[0] = gen_rtx_REG (SImode, rb_eh_data);
1750 operands[1] = gen_rtx_REG (SImode, re_eh_data);
1751 /* Create assembly code pattern: "Rb, Re, { }". */
1752 snprintf (pattern, sizeof (pattern), "push.s\t%s", "%0, %1, { }");
1753 /* We use output_asm_insn() to output assembly code by ourself. */
1754 output_asm_insn (pattern, operands);
1755 return "";
1758 /* If we step here, we are going to do v3push or multiple push operation. */
1760 /* The v3push/v3pop instruction should only be applied on
1761 none-isr and none-variadic function. */
1762 if (TARGET_V3PUSH
1763 && !nds32_isr_function_p (current_function_decl)
1764 && (cfun->machine->va_args_size == 0))
1766 /* For stack v3push:
1767 operands[0]: Re
1768 operands[1]: imm8u */
1770 /* This variable is to check if 'push25 Re,imm8u' is available. */
1771 int sp_adjust;
1773 /* Set operands[0]. */
1774 operands[0] = gen_rtx_REG (SImode, re_callee_saved);
1776 /* Check if we can generate 'push25 Re,imm8u',
1777 otherwise, generate 'push25 Re,0'. */
1778 sp_adjust = cfun->machine->local_size
1779 + cfun->machine->out_args_size
1780 + cfun->machine->callee_saved_area_gpr_padding_bytes
1781 + cfun->machine->callee_saved_fpr_regs_size;
1782 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
1783 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust))
1784 operands[1] = GEN_INT (sp_adjust);
1785 else
1787 /* Allocate callee saved fpr space. */
1788 if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
1790 sp_adjust = cfun->machine->callee_saved_area_gpr_padding_bytes
1791 + cfun->machine->callee_saved_fpr_regs_size;
1792 operands[1] = GEN_INT (sp_adjust);
1794 else
1796 operands[1] = GEN_INT (0);
1800 /* Create assembly code pattern. */
1801 snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1");
1803 else
1805 /* For normal stack push multiple:
1806 operands[0]: Rb
1807 operands[1]: Re
1808 operands[2]: En4 */
1810 /* This variable is used to check if we only need to generate En4 field.
1811 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
1812 int push_en4_only_p = 0;
1814 /* Set operands[0] and operands[1]. */
1815 operands[0] = gen_rtx_REG (SImode, rb_callee_saved);
1816 operands[1] = gen_rtx_REG (SImode, re_callee_saved);
1818 /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
1819 if (!cfun->machine->fp_size
1820 && !cfun->machine->gp_size
1821 && !cfun->machine->lp_size
1822 && REGNO (operands[0]) == SP_REGNUM
1823 && REGNO (operands[1]) == SP_REGNUM)
1825 /* No need to generate instruction. */
1826 return "";
1828 else
1830 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
1831 if (REGNO (operands[0]) == SP_REGNUM
1832 && REGNO (operands[1]) == SP_REGNUM)
1833 push_en4_only_p = 1;
1835 /* Create assembly code pattern.
1836 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
1837 snprintf (pattern, sizeof (pattern),
1838 "push.s\t%s{%s%s%s }",
1839 push_en4_only_p ? "" : "%0, %1, ",
1840 cfun->machine->fp_size ? " $fp" : "",
1841 cfun->machine->gp_size ? " $gp" : "",
1842 cfun->machine->lp_size ? " $lp" : "");
1846 /* We use output_asm_insn() to output assembly code by ourself. */
1847 output_asm_insn (pattern, operands);
1848 return "";
1851 /* Function to output stack pop operation.
1852 We need to deal with normal stack pop multiple or stack v3pop. */
1853 const char *
1854 nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED)
1856 /* A string pattern for output_asm_insn(). */
1857 char pattern[100];
1858 /* The operands array which will be used in output_asm_insn(). */
1859 rtx operands[3];
1860 /* Pick up first and last eh data regno for further use. */
1861 int rb_eh_data = cfun->machine->eh_return_data_first_regno;
1862 int re_eh_data = cfun->machine->eh_return_data_last_regno;
1863 int first_eh_data_regno = EH_RETURN_DATA_REGNO (0);
1864 /* Pick up callee-saved first regno and last regno for further use. */
1865 int rb_callee_saved = cfun->machine->callee_saved_first_gpr_regno;
1866 int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno;
1868 /* We need to check if we need to push exception handling
1869 data registers. */
1870 if (reg_mentioned_p (gen_rtx_REG (SImode, first_eh_data_regno), par_rtx))
1872 /* Set operands[0] and operands[1]. */
1873 operands[0] = gen_rtx_REG (SImode, rb_eh_data);
1874 operands[1] = gen_rtx_REG (SImode, re_eh_data);
1875 /* Create assembly code pattern: "Rb, Re, { }". */
1876 snprintf (pattern, sizeof (pattern), "pop.s\t%s", "%0, %1, { }");
1877 /* We use output_asm_insn() to output assembly code by ourself. */
1878 output_asm_insn (pattern, operands);
1879 return "";
1882 /* If we step here, we are going to do v3pop or multiple pop operation. */
1884 /* The v3push/v3pop instruction should only be applied on
1885 none-isr and none-variadic function. */
1886 if (TARGET_V3PUSH
1887 && !nds32_isr_function_p (current_function_decl)
1888 && (cfun->machine->va_args_size == 0))
1890 /* For stack v3pop:
1891 operands[0]: Re
1892 operands[1]: imm8u */
1894 /* This variable is to check if 'pop25 Re,imm8u' is available. */
1895 int sp_adjust;
1897 /* Set operands[0]. */
1898 operands[0] = gen_rtx_REG (SImode, re_callee_saved);
1900 /* Check if we can generate 'pop25 Re,imm8u',
1901 otherwise, generate 'pop25 Re,0'.
1902 We have to consider alloca issue as well.
1903 If the function does call alloca(), the stack pointer is not fixed.
1904 In that case, we cannot use 'pop25 Re,imm8u' directly.
1905 We have to caculate stack pointer from frame pointer
1906 and then use 'pop25 Re,0'. */
1907 sp_adjust = cfun->machine->local_size
1908 + cfun->machine->out_args_size
1909 + cfun->machine->callee_saved_area_gpr_padding_bytes
1910 + cfun->machine->callee_saved_fpr_regs_size;
1911 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
1912 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
1913 && !cfun->calls_alloca)
1914 operands[1] = GEN_INT (sp_adjust);
1915 else
1917 if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
1919 /* If has fpr need to restore, the $sp on callee saved fpr
1920 position, so we need to consider gpr pading bytes and
1921 callee saved fpr size. */
1922 sp_adjust = cfun->machine->callee_saved_area_gpr_padding_bytes
1923 + cfun->machine->callee_saved_fpr_regs_size;
1924 operands[1] = GEN_INT (sp_adjust);
1926 else
1928 operands[1] = GEN_INT (0);
1932 /* Create assembly code pattern. */
1933 snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1");
1935 else
1937 /* For normal stack pop multiple:
1938 operands[0]: Rb
1939 operands[1]: Re
1940 operands[2]: En4 */
1942 /* This variable is used to check if we only need to generate En4 field.
1943 As long as Rb==Re=SP_REGNUM, we set this variable to 1. */
1944 int pop_en4_only_p = 0;
1946 /* Set operands[0] and operands[1]. */
1947 operands[0] = gen_rtx_REG (SImode, rb_callee_saved);
1948 operands[1] = gen_rtx_REG (SImode, re_callee_saved);
1950 /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
1951 if (!cfun->machine->fp_size
1952 && !cfun->machine->gp_size
1953 && !cfun->machine->lp_size
1954 && REGNO (operands[0]) == SP_REGNUM
1955 && REGNO (operands[1]) == SP_REGNUM)
1957 /* No need to generate instruction. */
1958 return "";
1960 else
1962 /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */
1963 if (REGNO (operands[0]) == SP_REGNUM
1964 && REGNO (operands[1]) == SP_REGNUM)
1965 pop_en4_only_p = 1;
1967 /* Create assembly code pattern.
1968 We need to handle the form: "Rb, Re, { $fp $gp $lp }". */
1969 snprintf (pattern, sizeof (pattern),
1970 "pop.s\t%s{%s%s%s }",
1971 pop_en4_only_p ? "" : "%0, %1, ",
1972 cfun->machine->fp_size ? " $fp" : "",
1973 cfun->machine->gp_size ? " $gp" : "",
1974 cfun->machine->lp_size ? " $lp" : "");
1978 /* We use output_asm_insn() to output assembly code by ourself. */
1979 output_asm_insn (pattern, operands);
1980 return "";
1983 /* Function to output return operation. */
1984 const char *
1985 nds32_output_return (void)
1987 /* A string pattern for output_asm_insn(). */
1988 char pattern[100];
1989 /* The operands array which will be used in output_asm_insn(). */
1990 rtx operands[2];
1991 /* For stack v3pop:
1992 operands[0]: Re
1993 operands[1]: imm8u */
1994 int re_callee_saved = cfun->machine->callee_saved_last_gpr_regno;
1995 int sp_adjust;
1997 /* Set operands[0]. */
1998 operands[0] = gen_rtx_REG (SImode, re_callee_saved);
2000 /* Check if we can generate 'pop25 Re,imm8u',
2001 otherwise, generate 'pop25 Re,0'.
2002 We have to consider alloca issue as well.
2003 If the function does call alloca(), the stack pointer is not fixed.
2004 In that case, we cannot use 'pop25 Re,imm8u' directly.
2005 We have to caculate stack pointer from frame pointer
2006 and then use 'pop25 Re,0'. */
2007 sp_adjust = cfun->machine->local_size
2008 + cfun->machine->out_args_size
2009 + cfun->machine->callee_saved_area_gpr_padding_bytes
2010 + cfun->machine->callee_saved_fpr_regs_size;
2011 if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust))
2012 && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)
2013 && !cfun->calls_alloca)
2014 operands[1] = GEN_INT (sp_adjust);
2015 else
2016 operands[1] = GEN_INT (0);
2018 /* Create assembly code pattern. */
2019 snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1");
2020 /* We use output_asm_insn() to output assembly code by ourself. */
2021 output_asm_insn (pattern, operands);
2022 return "";
2025 /* Function to generate PC relative jump table.
2026 Refer to nds32.md for more details.
2028 The following is the sample for the case that diff value
2029 can be presented in '.short' size.
2031 addi $r1, $r1, -(case_lower_bound)
2032 slti $ta, $r1, (case_number)
2033 beqz $ta, .L_skip_label
2035 la $ta, .L35 ! get jump table address
2036 lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry
2037 addi $ta, $r1, $ta
2038 jr5 $ta
2040 ! jump table entry
2041 L35:
2042 .short .L25-.L35
2043 .short .L26-.L35
2044 .short .L27-.L35
2045 .short .L28-.L35
2046 .short .L29-.L35
2047 .short .L30-.L35
2048 .short .L31-.L35
2049 .short .L32-.L35
2050 .short .L33-.L35
2051 .short .L34-.L35 */
2052 const char *
2053 nds32_output_casesi_pc_relative (rtx *operands)
2055 machine_mode mode;
2056 rtx diff_vec;
2058 diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[1])));
2060 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
2062 /* Step C: "t <-- operands[1]". */
2063 output_asm_insn ("la\t$ta, %l1", operands);
2065 /* Get the mode of each element in the difference vector. */
2066 mode = GET_MODE (diff_vec);
2068 /* Step D: "z <-- (mem (plus (operands[0] << m) t))",
2069 where m is 0, 1, or 2 to load address-diff value from table. */
2070 switch (mode)
2072 case E_QImode:
2073 output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands);
2074 break;
2075 case E_HImode:
2076 output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands);
2077 break;
2078 case E_SImode:
2079 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
2080 break;
2081 default:
2082 gcc_unreachable ();
2085 /* Step E: "t <-- z + t".
2086 Add table label_ref with address-diff value to
2087 obtain target case address. */
2088 output_asm_insn ("add\t$ta, %2, $ta", operands);
2090 /* Step F: jump to target with register t. */
2091 if (TARGET_16_BIT)
2092 return "jr5\t$ta";
2093 else
2094 return "jr\t$ta";
2097 /* output a float load instruction */
2098 const char *
2099 nds32_output_float_load (rtx *operands)
2101 char buff[100];
2102 const char *pattern;
2103 rtx addr, addr_op0, addr_op1;
2104 int dp = GET_MODE_SIZE (GET_MODE (operands[0])) == 8;
2105 addr = XEXP (operands[1], 0);
2106 switch (GET_CODE (addr))
2108 case REG:
2109 pattern = "fl%ci\t%%0, %%1";
2110 break;
2112 case PLUS:
2113 addr_op0 = XEXP (addr, 0);
2114 addr_op1 = XEXP (addr, 1);
2116 if (REG_P (addr_op0) && REG_P (addr_op1))
2117 pattern = "fl%c\t%%0, %%1";
2118 else if (REG_P (addr_op0) && CONST_INT_P (addr_op1))
2119 pattern = "fl%ci\t%%0, %%1";
2120 else if (GET_CODE (addr_op0) == MULT && REG_P (addr_op1)
2121 && REG_P (XEXP (addr_op0, 0))
2122 && CONST_INT_P (XEXP (addr_op0, 1)))
2123 pattern = "fl%c\t%%0, %%1";
2124 else
2125 gcc_unreachable ();
2126 break;
2128 case POST_MODIFY:
2129 addr_op0 = XEXP (addr, 0);
2130 addr_op1 = XEXP (addr, 1);
2132 if (REG_P (addr_op0) && GET_CODE (addr_op1) == PLUS
2133 && REG_P (XEXP (addr_op1, 1)))
2134 pattern = "fl%c.bi\t%%0, %%1";
2135 else if (REG_P (addr_op0) && GET_CODE (addr_op1) == PLUS
2136 && CONST_INT_P (XEXP (addr_op1, 1)))
2137 pattern = "fl%ci.bi\t%%0, %%1";
2138 else
2139 gcc_unreachable ();
2140 break;
2142 case POST_INC:
2143 if (REG_P (XEXP (addr, 0)))
2145 if (dp)
2146 pattern = "fl%ci.bi\t%%0, %%1, 8";
2147 else
2148 pattern = "fl%ci.bi\t%%0, %%1, 4";
2150 else
2151 gcc_unreachable ();
2152 break;
2154 case POST_DEC:
2155 if (REG_P (XEXP (addr, 0)))
2157 if (dp)
2158 pattern = "fl%ci.bi\t%%0, %%1, -8";
2159 else
2160 pattern = "fl%ci.bi\t%%0, %%1, -4";
2162 else
2163 gcc_unreachable ();
2164 break;
2166 default:
2167 gcc_unreachable ();
2170 sprintf (buff, pattern, dp ? 'd' : 's');
2171 output_asm_insn (buff, operands);
2172 return "";
2175 /* output a float store instruction */
2176 const char *
2177 nds32_output_float_store (rtx *operands)
2179 char buff[100];
2180 const char *pattern;
2181 rtx addr, addr_op0, addr_op1;
2182 int dp = GET_MODE_SIZE (GET_MODE (operands[0])) == 8;
2183 addr = XEXP (operands[0], 0);
2184 switch (GET_CODE (addr))
2186 case REG:
2187 pattern = "fs%ci\t%%1, %%0";
2188 break;
2190 case PLUS:
2191 addr_op0 = XEXP (addr, 0);
2192 addr_op1 = XEXP (addr, 1);
2194 if (REG_P (addr_op0) && REG_P (addr_op1))
2195 pattern = "fs%c\t%%1, %%0";
2196 else if (REG_P (addr_op0) && CONST_INT_P (addr_op1))
2197 pattern = "fs%ci\t%%1, %%0";
2198 else if (GET_CODE (addr_op0) == MULT && REG_P (addr_op1)
2199 && REG_P (XEXP (addr_op0, 0))
2200 && CONST_INT_P (XEXP (addr_op0, 1)))
2201 pattern = "fs%c\t%%1, %%0";
2202 else
2203 gcc_unreachable ();
2204 break;
2206 case POST_MODIFY:
2207 addr_op0 = XEXP (addr, 0);
2208 addr_op1 = XEXP (addr, 1);
2210 if (REG_P (addr_op0) && GET_CODE (addr_op1) == PLUS
2211 && REG_P (XEXP (addr_op1, 1)))
2212 pattern = "fs%c.bi\t%%1, %%0";
2213 else if (REG_P (addr_op0) && GET_CODE (addr_op1) == PLUS
2214 && CONST_INT_P (XEXP (addr_op1, 1)))
2215 pattern = "fs%ci.bi\t%%1, %%0";
2216 else
2217 gcc_unreachable ();
2218 break;
2220 case POST_INC:
2221 if (REG_P (XEXP (addr, 0)))
2223 if (dp)
2224 pattern = "fs%ci.bi\t%%1, %%0, 8";
2225 else
2226 pattern = "fs%ci.bi\t%%1, %%0, 4";
2228 else
2229 gcc_unreachable ();
2230 break;
2232 case POST_DEC:
2233 if (REG_P (XEXP (addr, 0)))
2235 if (dp)
2236 pattern = "fs%ci.bi\t%%1, %%0, -8";
2237 else
2238 pattern = "fs%ci.bi\t%%1, %%0, -4";
2240 else
2241 gcc_unreachable ();
2242 break;
2244 default:
2245 gcc_unreachable ();
2248 sprintf (buff, pattern, dp ? 'd' : 's');
2249 output_asm_insn (buff, operands);
2250 return "";
2253 /* Function to generate normal jump table. */
2254 const char *
2255 nds32_output_casesi (rtx *operands)
2257 /* Step C: "t <-- operands[1]". */
2258 output_asm_insn ("la\t$ta, %l1", operands);
2260 /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */
2261 output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
2263 /* No need to perform Step E, which is only used for
2264 pc relative jump table. */
2266 /* Step F: jump to target with register z. */
2267 if (TARGET_16_BIT)
2268 return "jr5\t%2";
2269 else
2270 return "jr\t%2";
2273 /* Auxiliary functions for lwm/smw. */
2274 bool
2275 nds32_valid_smw_lwm_base_p (rtx op)
2277 rtx base_addr;
2279 if (!MEM_P (op))
2280 return false;
2282 base_addr = XEXP (op, 0);
2284 if (REG_P (base_addr))
2285 return true;
2286 else
2288 if (GET_CODE (base_addr) == POST_INC
2289 && REG_P (XEXP (base_addr, 0)))
2290 return true;
2293 return false;
2296 /* ------------------------------------------------------------------------ */
2297 const char *
2298 nds32_output_smw_single_word (rtx *operands)
2300 char buff[100];
2301 unsigned regno;
2302 int enable4;
2303 bool update_base_p;
2304 rtx base_addr = operands[0];
2305 rtx base_reg;
2306 rtx otherops[2];
2308 if (REG_P (XEXP (base_addr, 0)))
2310 update_base_p = false;
2311 base_reg = XEXP (base_addr, 0);
2313 else
2315 update_base_p = true;
2316 base_reg = XEXP (XEXP (base_addr, 0), 0);
2319 const char *update_base = update_base_p ? "m" : "";
2321 regno = REGNO (operands[1]);
2323 otherops[0] = base_reg;
2324 otherops[1] = operands[1];
2326 if (regno >= 28)
2328 enable4 = nds32_regno_to_enable4 (regno);
2329 sprintf (buff, "smw.bi%s\t$sp, [%%0], $sp, %x", update_base, enable4);
2331 else
2333 sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1", update_base);
2335 output_asm_insn (buff, otherops);
2336 return "";
2339 const char *
2340 nds32_output_lmw_single_word (rtx *operands)
2342 char buff[100];
2343 unsigned regno;
2344 bool update_base_p;
2345 int enable4;
2346 rtx base_addr = operands[1];
2347 rtx base_reg;
2348 rtx otherops[2];
2350 if (REG_P (XEXP (base_addr, 0)))
2352 update_base_p = false;
2353 base_reg = XEXP (base_addr, 0);
2355 else
2357 update_base_p = true;
2358 base_reg = XEXP (XEXP (base_addr, 0), 0);
2361 const char *update_base = update_base_p ? "m" : "";
2363 regno = REGNO (operands[0]);
2365 otherops[0] = operands[0];
2366 otherops[1] = base_reg;
2368 if (regno >= 28)
2370 enable4 = nds32_regno_to_enable4 (regno);
2371 sprintf (buff, "lmw.bi%s\t$sp, [%%1], $sp, %x", update_base, enable4);
2373 else
2375 sprintf (buff, "lmw.bi%s\t%%0, [%%1], %%0", update_base);
2377 output_asm_insn (buff, otherops);
2378 return "";
2381 void
2382 nds32_expand_unaligned_load (rtx *operands, enum machine_mode mode)
2384 /* Initial memory offset. */
2385 int offset = WORDS_BIG_ENDIAN ? GET_MODE_SIZE (mode) - 1 : 0;
2386 int offset_adj = WORDS_BIG_ENDIAN ? -1 : 1;
2387 /* Initial register shift byte. */
2388 int shift = 0;
2389 /* The first load byte instruction is not the same. */
2390 int width = GET_MODE_SIZE (mode) - 1;
2391 rtx mem[2];
2392 rtx reg[2];
2393 rtx sub_reg;
2394 rtx temp_reg, temp_sub_reg;
2395 int num_reg;
2397 /* Generating a series of load byte instructions.
2398 The first load byte instructions and other
2399 load byte instructions are not the same. like:
2400 First:
2401 lbi reg0, [mem]
2402 zeh reg0, reg0
2403 Second:
2404 lbi temp_reg, [mem + offset]
2405 sll temp_reg, (8 * shift)
2406 ior reg0, temp_reg
2408 lbi temp_reg, [mem + (offset + 1)]
2409 sll temp_reg, (8 * (shift + 1))
2410 ior reg0, temp_reg */
2412 temp_reg = gen_reg_rtx (SImode);
2413 temp_sub_reg = gen_lowpart (QImode, temp_reg);
2415 if (mode == DImode)
2417 /* Load doubleword, we need two registers to access. */
2418 reg[0] = simplify_gen_subreg (SImode, operands[0],
2419 GET_MODE (operands[0]), 0);
2420 reg[1] = simplify_gen_subreg (SImode, operands[0],
2421 GET_MODE (operands[0]), 4);
2422 /* A register only store 4 byte. */
2423 width = GET_MODE_SIZE (SImode) - 1;
2425 else
2427 reg[0] = operands[0];
2430 for (num_reg = (mode == DImode) ? 2 : 1; num_reg > 0; num_reg--)
2432 sub_reg = gen_lowpart (QImode, reg[0]);
2433 mem[0] = gen_rtx_MEM (QImode, plus_constant (Pmode, operands[1], offset));
2435 /* Generating the first part instructions.
2436 lbi reg0, [mem]
2437 zeh reg0, reg0 */
2438 emit_move_insn (sub_reg, mem[0]);
2439 emit_insn (gen_zero_extendqisi2 (reg[0], sub_reg));
2441 while (width > 0)
2443 offset = offset + offset_adj;
2444 shift++;
2445 width--;
2447 mem[1] = gen_rtx_MEM (QImode, plus_constant (Pmode,
2448 operands[1],
2449 offset));
2450 /* Generating the second part instructions.
2451 lbi temp_reg, [mem + offset]
2452 sll temp_reg, (8 * shift)
2453 ior reg0, temp_reg */
2454 emit_move_insn (temp_sub_reg, mem[1]);
2455 emit_insn (gen_ashlsi3 (temp_reg, temp_reg,
2456 GEN_INT (shift * 8)));
2457 emit_insn (gen_iorsi3 (reg[0], reg[0], temp_reg));
2460 if (mode == DImode)
2462 /* Using the second register to load memory information. */
2463 reg[0] = reg[1];
2464 shift = 0;
2465 width = GET_MODE_SIZE (SImode) - 1;
2466 offset = offset + offset_adj;
2471 void
2472 nds32_expand_unaligned_store (rtx *operands, enum machine_mode mode)
2474 /* Initial memory offset. */
2475 int offset = WORDS_BIG_ENDIAN ? GET_MODE_SIZE (mode) - 1 : 0;
2476 int offset_adj = WORDS_BIG_ENDIAN ? -1 : 1;
2477 /* Initial register shift byte. */
2478 int shift = 0;
2479 /* The first load byte instruction is not the same. */
2480 int width = GET_MODE_SIZE (mode) - 1;
2481 rtx mem[2];
2482 rtx reg[2];
2483 rtx sub_reg;
2484 rtx temp_reg, temp_sub_reg;
2485 int num_reg;
2487 /* Generating a series of store byte instructions.
2488 The first store byte instructions and other
2489 load byte instructions are not the same. like:
2490 First:
2491 sbi reg0, [mem + 0]
2492 Second:
2493 srli temp_reg, reg0, (8 * shift)
2494 sbi temp_reg, [mem + offset] */
2496 temp_reg = gen_reg_rtx (SImode);
2497 temp_sub_reg = gen_lowpart (QImode, temp_reg);
2499 if (mode == DImode)
2501 /* Load doubleword, we need two registers to access. */
2502 reg[0] = simplify_gen_subreg (SImode, operands[1],
2503 GET_MODE (operands[1]), 0);
2504 reg[1] = simplify_gen_subreg (SImode, operands[1],
2505 GET_MODE (operands[1]), 4);
2506 /* A register only store 4 byte. */
2507 width = GET_MODE_SIZE (SImode) - 1;
2509 else
2511 reg[0] = operands[1];
2514 for (num_reg = (mode == DImode) ? 2 : 1; num_reg > 0; num_reg--)
2516 sub_reg = gen_lowpart (QImode, reg[0]);
2517 mem[0] = gen_rtx_MEM (QImode, plus_constant (Pmode, operands[0], offset));
2519 /* Generating the first part instructions.
2520 sbi reg0, [mem + 0] */
2521 emit_move_insn (mem[0], sub_reg);
2523 while (width > 0)
2525 offset = offset + offset_adj;
2526 shift++;
2527 width--;
2529 mem[1] = gen_rtx_MEM (QImode, plus_constant (Pmode,
2530 operands[0],
2531 offset));
2532 /* Generating the second part instructions.
2533 srli temp_reg, reg0, (8 * shift)
2534 sbi temp_reg, [mem + offset] */
2535 emit_insn (gen_lshrsi3 (temp_reg, reg[0],
2536 GEN_INT (shift * 8)));
2537 emit_move_insn (mem[1], temp_sub_reg);
2540 if (mode == DImode)
2542 /* Using the second register to load memory information. */
2543 reg[0] = reg[1];
2544 shift = 0;
2545 width = GET_MODE_SIZE (SImode) - 1;
2546 offset = offset + offset_adj;
2551 /* Using multiple load/store instruction to output doubleword instruction. */
2552 const char *
2553 nds32_output_double (rtx *operands, bool load_p)
2555 char pattern[100];
2556 int reg = load_p ? 0 : 1;
2557 int mem = load_p ? 1 : 0;
2558 rtx otherops[3];
2559 rtx addr = XEXP (operands[mem], 0);
2561 otherops[0] = gen_rtx_REG (SImode, REGNO (operands[reg]));
2562 otherops[1] = gen_rtx_REG (SImode, REGNO (operands[reg]) + 1);
2564 if (GET_CODE (addr) == POST_INC)
2566 /* (mem (post_inc (reg))) */
2567 otherops[2] = XEXP (addr, 0);
2568 snprintf (pattern, sizeof (pattern),
2569 "%cmw.bim\t%%0, [%%2], %%1, 0", load_p ? 'l' : 's');
2571 else
2573 /* (mem (reg)) */
2574 otherops[2] = addr;
2575 snprintf (pattern, sizeof (pattern),
2576 "%cmw.bi\t%%0, [%%2], %%1, 0", load_p ? 'l' : 's');
2580 output_asm_insn (pattern, otherops);
2581 return "";
2584 const char *
2585 nds32_output_cbranchsi4_equality_zero (rtx_insn *insn, rtx *operands)
2587 enum rtx_code code;
2588 bool long_jump_p = false;
2590 code = GET_CODE (operands[0]);
2592 /* This zero-comparison conditional branch has two forms:
2593 32-bit instruction => beqz/bnez imm16s << 1
2594 16-bit instruction => beqzs8/bnezs8/beqz38/bnez38 imm8s << 1
2596 For 32-bit case,
2597 we assume it is always reachable. (but check range -65500 ~ 65500)
2599 For 16-bit case,
2600 it must satisfy { 255 >= (label - pc) >= -256 } condition.
2601 However, since the $pc for nds32 is at the beginning of the instruction,
2602 we should leave some length space for current insn.
2603 So we use range -250 ~ 250. */
2605 switch (get_attr_length (insn))
2607 case 8:
2608 long_jump_p = true;
2609 /* fall through */
2610 case 2:
2611 if (which_alternative == 0)
2613 /* constraint: t */
2614 /* b<cond>zs8 .L0
2616 b<inverse_cond>zs8 .LCB0
2617 j .L0
2618 .LCB0:
2620 output_cond_branch_compare_zero (code, "s8", long_jump_p,
2621 operands, true);
2622 return "";
2624 else if (which_alternative == 1)
2626 /* constraint: l */
2627 /* b<cond>z38 $r0, .L0
2629 b<inverse_cond>z38 $r0, .LCB0
2630 j .L0
2631 .LCB0:
2633 output_cond_branch_compare_zero (code, "38", long_jump_p,
2634 operands, false);
2635 return "";
2637 else
2639 /* constraint: r */
2640 /* For which_alternative==2, it should not be here. */
2641 gcc_unreachable ();
2643 case 10:
2644 /* including constraints: t, l, and r */
2645 long_jump_p = true;
2646 /* fall through */
2647 case 4:
2648 /* including constraints: t, l, and r */
2649 output_cond_branch_compare_zero (code, "", long_jump_p, operands, false);
2650 return "";
2652 default:
2653 gcc_unreachable ();
2657 const char *
2658 nds32_output_cbranchsi4_equality_reg (rtx_insn *insn, rtx *operands)
2660 enum rtx_code code;
2661 bool long_jump_p, r5_p;
2662 int insn_length;
2664 insn_length = get_attr_length (insn);
2666 long_jump_p = (insn_length == 10 || insn_length == 8) ? true : false;
2667 r5_p = (insn_length == 2 || insn_length == 8) ? true : false;
2669 code = GET_CODE (operands[0]);
2671 /* This register-comparison conditional branch has one form:
2672 32-bit instruction => beq/bne imm14s << 1
2674 For 32-bit case,
2675 we assume it is always reachable. (but check range -16350 ~ 16350). */
2677 switch (code)
2679 case EQ:
2680 case NE:
2681 output_cond_branch (code, "", r5_p, long_jump_p, operands);
2682 return "";
2684 default:
2685 gcc_unreachable ();
2689 const char *
2690 nds32_output_cbranchsi4_equality_reg_or_const_int (rtx_insn *insn,
2691 rtx *operands)
2693 enum rtx_code code;
2694 bool long_jump_p, r5_p;
2695 int insn_length;
2697 insn_length = get_attr_length (insn);
2699 long_jump_p = (insn_length == 10 || insn_length == 8) ? true : false;
2700 r5_p = (insn_length == 2 || insn_length == 8) ? true : false;
2702 code = GET_CODE (operands[0]);
2704 /* This register-comparison conditional branch has one form:
2705 32-bit instruction => beq/bne imm14s << 1
2706 32-bit instruction => beqc/bnec imm8s << 1
2708 For 32-bit case, we assume it is always reachable.
2709 (but check range -16350 ~ 16350 and -250 ~ 250). */
2711 switch (code)
2713 case EQ:
2714 case NE:
2715 if (which_alternative == 2)
2717 /* r, Is11 */
2718 /* b<cond>c */
2719 output_cond_branch (code, "c", r5_p, long_jump_p, operands);
2721 else
2723 /* r, r */
2724 /* v, r */
2725 output_cond_branch (code, "", r5_p, long_jump_p, operands);
2727 return "";
2728 default:
2729 gcc_unreachable ();
2733 const char *
2734 nds32_output_cbranchsi4_greater_less_zero (rtx_insn *insn, rtx *operands)
2736 enum rtx_code code;
2737 bool long_jump_p;
2738 int insn_length;
2740 insn_length = get_attr_length (insn);
2742 gcc_assert (insn_length == 4 || insn_length == 10);
2744 long_jump_p = (insn_length == 10) ? true : false;
2746 code = GET_CODE (operands[0]);
2748 /* This zero-greater-less-comparison conditional branch has one form:
2749 32-bit instruction => bgtz/bgez/bltz/blez imm16s << 1
2751 For 32-bit case, we assume it is always reachable.
2752 (but check range -65500 ~ 65500). */
2754 switch (code)
2756 case GT:
2757 case GE:
2758 case LT:
2759 case LE:
2760 output_cond_branch_compare_zero (code, "", long_jump_p, operands, false);
2761 break;
2762 default:
2763 gcc_unreachable ();
2765 return "";
2768 /* Return true if SYMBOL_REF X binds locally. */
2770 static bool
2771 nds32_symbol_binds_local_p (const_rtx x)
2773 return (SYMBOL_REF_DECL (x)
2774 ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
2775 : SYMBOL_REF_LOCAL_P (x));
2778 const char *
2779 nds32_output_call (rtx insn, rtx *operands, rtx symbol, const char *long_call,
2780 const char *call, bool align_p)
2782 char pattern[100];
2783 bool noreturn_p;
2785 if (GET_CODE (symbol) == CONST)
2787 symbol= XEXP (symbol, 0);
2789 if (GET_CODE (symbol) == PLUS)
2790 symbol = XEXP (symbol, 0);
2793 gcc_assert (GET_CODE (symbol) == SYMBOL_REF
2794 || REG_P (symbol));
2796 if (nds32_long_call_p (symbol))
2797 strcpy (pattern, long_call);
2798 else
2799 strcpy (pattern, call);
2801 if (align_p)
2802 strcat (pattern, "\n\t.align 2");
2804 noreturn_p = find_reg_note (insn, REG_NORETURN, NULL_RTX) != NULL_RTX;
2806 if (noreturn_p)
2808 if (TARGET_16_BIT)
2809 strcat (pattern, "\n\tnop16");
2810 else
2811 strcat (pattern, "\n\tnop");
2814 output_asm_insn (pattern, operands);
2815 return "";
2818 /* Spilt a doubleword instrucion to two single word instructions. */
2819 void
2820 nds32_spilt_doubleword (rtx *operands, bool load_p)
2822 int reg = load_p ? 0 : 1;
2823 int mem = load_p ? 1 : 0;
2824 rtx reg_rtx = load_p ? operands[0] : operands[1];
2825 rtx mem_rtx = load_p ? operands[1] : operands[0];
2826 rtx low_part[2], high_part[2];
2827 rtx sub_mem = XEXP (mem_rtx, 0);
2829 /* Generate low_part and high_part register pattern.
2830 i.e. register pattern like:
2831 (reg:DI) -> (subreg:SI (reg:DI))
2832 (subreg:SI (reg:DI)) */
2833 low_part[reg] = simplify_gen_subreg (SImode, reg_rtx, GET_MODE (reg_rtx), 0);
2834 high_part[reg] = simplify_gen_subreg (SImode, reg_rtx, GET_MODE (reg_rtx), 4);
2836 /* Generate low_part and high_part memory pattern.
2837 Memory format is (post_dec) will generate:
2838 low_part: lwi.bi reg, [mem], 4
2839 high_part: lwi.bi reg, [mem], -12 */
2840 if (GET_CODE (sub_mem) == POST_DEC)
2842 /* memory format is (post_dec (reg)),
2843 so that extract (reg) from the (post_dec (reg)) pattern. */
2844 sub_mem = XEXP (sub_mem, 0);
2846 /* generate low_part and high_part memory format:
2847 low_part: (post_modify ((reg) (plus (reg) (const 4)))
2848 high_part: (post_modify ((reg) (plus (reg) (const -12))) */
2849 low_part[mem] = gen_frame_mem (SImode,
2850 gen_rtx_POST_MODIFY (Pmode, sub_mem,
2851 gen_rtx_PLUS (Pmode,
2852 sub_mem,
2853 GEN_INT (4))));
2854 high_part[mem] = gen_frame_mem (SImode,
2855 gen_rtx_POST_MODIFY (Pmode, sub_mem,
2856 gen_rtx_PLUS (Pmode,
2857 sub_mem,
2858 GEN_INT (-12))));
2860 else if (GET_CODE (sub_mem) == POST_MODIFY)
2862 /* Memory format is (post_modify (reg) (plus (reg) (const))),
2863 so that extract (reg) from the post_modify pattern. */
2864 rtx post_mem = XEXP (sub_mem, 0);
2866 /* Extract (const) from the (post_modify (reg) (plus (reg) (const)))
2867 pattern. */
2869 rtx plus_op = XEXP (sub_mem, 1);
2870 rtx post_val = XEXP (plus_op, 1);
2872 /* Generate low_part and high_part memory format:
2873 low_part: (post_modify ((reg) (plus (reg) (const)))
2874 high_part: ((plus (reg) (const 4))) */
2875 low_part[mem] = gen_frame_mem (SImode,
2876 gen_rtx_POST_MODIFY (Pmode, post_mem,
2877 gen_rtx_PLUS (Pmode,
2878 post_mem,
2879 post_val)));
2880 high_part[mem] = gen_frame_mem (SImode, plus_constant (Pmode,
2881 post_mem,
2882 4));
2884 else
2886 /* memory format: (symbol_ref), (const), (reg + const_int). */
2887 low_part[mem] = adjust_address (mem_rtx, SImode, 0);
2888 high_part[mem] = adjust_address (mem_rtx, SImode, 4);
2891 /* After reload completed, we have dependent issue by low part register and
2892 higt part memory. i.e. we cannot split a sequence
2893 like:
2894 load $r0, [%r1]
2895 spilt to
2896 lw $r0, [%r0]
2897 lwi $r1, [%r0 + 4]
2898 swap position
2899 lwi $r1, [%r0 + 4]
2900 lw $r0, [%r0]
2901 For store instruction we don't have a problem.
2903 When memory format is [post_modify], we need to emit high part instruction,
2904 before low part instruction.
2905 expamle:
2906 load $r0, [%r2], post_val
2907 spilt to
2908 load $r1, [%r2 + 4]
2909 load $r0, [$r2], post_val. */
2910 if ((load_p && reg_overlap_mentioned_p (low_part[0], high_part[1]))
2911 || GET_CODE (sub_mem) == POST_MODIFY)
2913 operands[2] = high_part[0];
2914 operands[3] = high_part[1];
2915 operands[4] = low_part[0];
2916 operands[5] = low_part[1];
2918 else
2920 operands[2] = low_part[0];
2921 operands[3] = low_part[1];
2922 operands[4] = high_part[0];
2923 operands[5] = high_part[1];
2927 /* Return true X is need use long call. */
2928 bool
2929 nds32_long_call_p (rtx symbol)
2931 return TARGET_CMODEL_LARGE;
2934 void
2935 nds32_expand_constant (machine_mode mode, HOST_WIDE_INT val,
2936 rtx target, rtx source)
2938 rtx temp = gen_reg_rtx (mode);
2939 int clear_sign_bit_copies = 0;
2940 int clear_zero_bit_copies = 0;
2941 unsigned HOST_WIDE_INT remainder = val & 0xffffffffUL;
2943 /* Count number of leading zeros. */
2944 clear_sign_bit_copies = __builtin_clz (remainder);
2945 /* Count number of trailing zeros. */
2946 clear_zero_bit_copies = __builtin_ctz (remainder);
2948 HOST_WIDE_INT sign_shift_mask = ((0xffffffffUL
2949 << (32 - clear_sign_bit_copies))
2950 & 0xffffffffUL);
2951 HOST_WIDE_INT zero_shift_mask = (1 << clear_zero_bit_copies) - 1;
2953 if (clear_sign_bit_copies > 0 && clear_sign_bit_copies < 17
2954 && (remainder | sign_shift_mask) == 0xffffffffUL)
2956 /* Transfer AND to two shifts, example:
2957 a = b & 0x7fffffff => (b << 1) >> 1 */
2958 rtx shift = GEN_INT (clear_sign_bit_copies);
2960 emit_insn (gen_ashlsi3 (temp, source, shift));
2961 emit_insn (gen_lshrsi3 (target, temp, shift));
2963 else if (clear_zero_bit_copies > 0 && clear_sign_bit_copies < 17
2964 && (remainder | zero_shift_mask) == 0xffffffffUL)
2966 /* Transfer AND to two shifts, example:
2967 a = b & 0xfff00000 => (b >> 20) << 20 */
2968 rtx shift = GEN_INT (clear_zero_bit_copies);
2970 emit_insn (gen_lshrsi3 (temp, source, shift));
2971 emit_insn (gen_ashlsi3 (target, temp, shift));
2973 else
2975 emit_move_insn (temp, GEN_INT (val));
2976 emit_move_insn (target, gen_rtx_fmt_ee (AND, mode, source, temp));