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.
5 
6    This file is part of GCC.
7 
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.
12 
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.
17 
18    You should have received a copy of the GNU General Public License
19    along with GCC; see the file COPYING3.  If not see
20    <http://www.gnu.org/licenses/>.  */
21 
22 /* ------------------------------------------------------------------------ */
23 
24 #define IN_TARGET_CODE 1
25 
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"
42 
43 /* ------------------------------------------------------------------------ */
44 
45 static int
nds32_regno_to_enable4(unsigned regno)46 nds32_regno_to_enable4 (unsigned regno)
47 {
48   switch (regno)
49     {
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 ();
60     }
61 }
62 
63 /* A helper function to return character based on byte size.  */
64 static char
nds32_byte_to_size(int byte)65 nds32_byte_to_size (int byte)
66 {
67   switch (byte)
68     {
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 ();
78     }
79 }
80 
81 static int
nds32_inverse_cond_code(int code)82 nds32_inverse_cond_code (int code)
83 {
84   switch (code)
85     {
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 ();
100     }
101 }
102 
103 static const char *
nds32_cond_code_str(int code)104 nds32_cond_code_str (int code)
105 {
106   switch (code)
107     {
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 ();
122     }
123 }
124 
125 static void
output_cond_branch(int code,const char * suffix,bool r5_p,bool long_jump_p,rtx * operands)126 output_cond_branch (int code, const char *suffix, bool r5_p,
127 		    bool long_jump_p, rtx *operands)
128 {
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" : "";
133 
134   if (r5_p && REGNO (operands[2]) == 5 && TARGET_16_BIT)
135     {
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)
140 	{
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");
148 	}
149       else
150 	/* Don't output anything since $r5 != $r5 never taken! */
151 	pattern[0] = '\0';
152     }
153   else if (long_jump_p)
154     {
155       int inverse_code = nds32_inverse_cond_code (code);
156       cond_code = nds32_cond_code_str (inverse_code);
157 
158       /*      b<cond><suffix>  $r0, $r1, .L0
159 	    =>
160 	      b<inverse_cond><suffix>  $r0, $r1, .LCB0
161 	      j  .L0
162 	    .LCB0:
163 
164 	    or
165 
166 	      b<cond><suffix>  $r0, $r1, .L0
167 	    =>
168 	      b<inverse_cond><suffix>  $r0, $r1, .LCB0
169 	      j  .L0
170 	    .LCB0:
171       */
172       if (r5_p && TARGET_16_BIT)
173 	{
174 	  snprintf (pattern, sizeof (pattern),
175 		    "b%ss38\t %%2, .LCB%%=\n\tj\t%%3\n%s.LCB%%=:",
176 		    cond_code, align);
177 	}
178       else
179 	{
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);
183 	}
184     }
185   else
186     {
187       cond_code = nds32_cond_code_str (code);
188       if (r5_p && TARGET_16_BIT)
189 	{
190 	  /* b<cond>s38  $r1, .L0   */
191 	  snprintf (pattern, sizeof (pattern),
192 		    "b%ss38\t %%2, %%3", cond_code);
193 	}
194       else
195 	{
196 	  /* b<cond><suffix>  $r0, $r1, .L0   */
197 	  snprintf (pattern, sizeof (pattern),
198 		    "b%s%s\t%%1, %%2, %%3", cond_code, suffix);
199 	}
200     }
201 
202   output_asm_insn (pattern, operands);
203 }
204 
205 static void
output_cond_branch_compare_zero(int code,const char * suffix,bool long_jump_p,rtx * operands,bool ta_implied_p)206 output_cond_branch_compare_zero (int code, const char *suffix,
207 				 bool long_jump_p, rtx *operands,
208 				 bool ta_implied_p)
209 {
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)
215     {
216       int inverse_code = nds32_inverse_cond_code (code);
217       cond_code = nds32_cond_code_str (inverse_code);
218 
219       if (ta_implied_p && TARGET_16_BIT)
220 	{
221 	  /*    b<cond>z<suffix>  .L0
222 	      =>
223 		b<inverse_cond>z<suffix>  .LCB0
224 		j  .L0
225 	      .LCB0:
226 	   */
227 	  snprintf (pattern, sizeof (pattern),
228 		    "b%sz%s\t.LCB%%=\n\tj\t%%2\n%s.LCB%%=:",
229 		    cond_code, suffix, align);
230 	}
231       else
232 	{
233 	  /*      b<cond>z<suffix>  $r0, .L0
234 		=>
235 		  b<inverse_cond>z<suffix>  $r0, .LCB0
236 		  j  .L0
237 		.LCB0:
238 	   */
239 	  snprintf (pattern, sizeof (pattern),
240 		    "b%sz%s\t%%1, .LCB%%=\n\tj\t%%2\n%s.LCB%%=:",
241 		    cond_code, suffix, align);
242 	}
243     }
244   else
245     {
246       cond_code = nds32_cond_code_str (code);
247       if (ta_implied_p && TARGET_16_BIT)
248 	{
249 	  /* b<cond>z<suffix>  .L0  */
250 	  snprintf (pattern, sizeof (pattern),
251 		    "b%sz%s\t%%2", cond_code, suffix);
252 	}
253       else
254 	{
255 	  /* b<cond>z<suffix>  $r0, .L0  */
256 	  snprintf (pattern, sizeof (pattern),
257 		    "b%sz%s\t%%1, %%2", cond_code, suffix);
258 	}
259     }
260 
261   output_asm_insn (pattern, operands);
262 }
263 
264 /* ------------------------------------------------------------------------ */
265 
266 /* Auxiliary function for expand RTL pattern.  */
267 
268 enum nds32_expand_result_type
nds32_expand_cbranch(rtx * operands)269 nds32_expand_cbranch (rtx *operands)
270 {
271   rtx tmp_reg;
272   enum rtx_code code;
273 
274   code = GET_CODE (operands[0]);
275 
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;
286 
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)
291     {
292     case GT:
293     case GTU:
294       if (GET_CODE (operands[2]) == CONST_INT)
295 	{
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);
301 
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.
308 
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.
314 
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;
318 
319 	  rtx plus1 = gen_int_mode (INTVAL (operands[2]) + 1, SImode);
320 	  if (satisfies_constraint_Is15 (plus1))
321 	    {
322 	      operands[2] = plus1;
323 	      cmp_code = EQ;
324 	      if (code == GT)
325 		{
326 		  /* GT, use slts instruction */
327 		  emit_insn (
328 		    gen_slts_compare (tmp_reg, operands[1], operands[2]));
329 		}
330 	      else
331 		{
332 		  /* GTU, use slt instruction */
333 		  emit_insn (
334 		    gen_slt_compare  (tmp_reg, operands[1], operands[2]));
335 		}
336 	    }
337 	  else
338 	    {
339 	      cmp_code = NE;
340 	      if (code == GT)
341 		{
342 		  /* GT, use slts instruction */
343 		  emit_insn (
344 		    gen_slts_compare (tmp_reg, operands[2], operands[1]));
345 		}
346 	      else
347 		{
348 		  /* GTU, use slt instruction */
349 		  emit_insn (
350 		    gen_slt_compare  (tmp_reg, operands[2], operands[1]));
351 		}
352 	    }
353 
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]));
359 
360 	  return EXPAND_DONE;
361 	}
362       else
363 	{
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);
369 
370 	  if (code == GT)
371 	    {
372 	      /* GT, use slts instruction */
373 	      emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1]));
374 	    }
375 	  else
376 	    {
377 	      /* GTU, use slt instruction */
378 	      emit_insn (gen_slt_compare  (tmp_reg, operands[2], operands[1]));
379 	    }
380 
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]));
386 
387 	  return EXPAND_DONE;
388 	}
389 
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);
398 
399       if (code == GE)
400 	{
401 	  /* GE, use slts instruction */
402 	  emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2]));
403 	}
404       else
405 	{
406 	  /* GEU, use slt instruction */
407 	  emit_insn (gen_slt_compare  (tmp_reg, operands[1], operands[2]));
408 	}
409 
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]));
415 
416       return EXPAND_DONE;
417 
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);
426 
427       if (code == LT)
428 	{
429 	  /* LT, use slts instruction */
430 	  emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2]));
431 	}
432       else
433 	{
434 	  /* LTU, use slt instruction */
435 	  emit_insn (gen_slt_compare  (tmp_reg, operands[1], operands[2]));
436 	}
437 
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]));
443 
444       return EXPAND_DONE;
445 
446     case LE:
447     case LEU:
448       if (GET_CODE (operands[2]) == CONST_INT)
449 	{
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);
455 
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))
462 	    {
463 	      operands[2] = plus1;
464 	      cmp_code = NE;
465 	      if (code == LE)
466 		{
467 		  /* LE, use slts instruction */
468 		  emit_insn (
469 		    gen_slts_compare (tmp_reg, operands[1], operands[2]));
470 		}
471 	      else
472 		{
473 		  /* LEU, use slt instruction */
474 		  emit_insn (
475 		    gen_slt_compare  (tmp_reg, operands[1], operands[2]));
476 		}
477 	    }
478 	  else
479 	    {
480 	      cmp_code = EQ;
481 	      if (code == LE)
482 		{
483 		  /* LE, use slts instruction */
484 		  emit_insn (
485 		    gen_slts_compare (tmp_reg, operands[2], operands[1]));
486 		}
487 	      else
488 		{
489 		  /* LEU, use slt instruction */
490 		  emit_insn (
491 		    gen_slt_compare  (tmp_reg, operands[2], operands[1]));
492 		}
493 	    }
494 
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]));
500 
501 	  return EXPAND_DONE;
502 	}
503       else
504 	{
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);
510 
511 	  if (code == LE)
512 	    {
513 	      /* LE, use slts instruction */
514 	      emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1]));
515 	    }
516 	  else
517 	    {
518 	      /* LEU, use slt instruction */
519 	      emit_insn (gen_slt_compare  (tmp_reg, operands[2], operands[1]));
520 	    }
521 
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]));
527 
528 	  return EXPAND_DONE;
529 	}
530 
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.  */
536 
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]);
543 
544       return EXPAND_CREATE_TEMPLATE;
545 
546     default:
547       return EXPAND_FAIL;
548     }
549 }
550 
551 enum nds32_expand_result_type
nds32_expand_cstore(rtx * operands)552 nds32_expand_cstore (rtx *operands)
553 {
554   rtx tmp_reg;
555   enum rtx_code code;
556 
557   code = GET_CODE (operands[1]);
558 
559   switch (code)
560     {
561     case EQ:
562     case NE:
563       if (GET_CODE (operands[3]) == CONST_INT)
564 	{
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);
572 
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
580 	    {
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]));
586 	    }
587 
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));
592 
593 	  return EXPAND_DONE;
594 	}
595       else
596 	{
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));
609 
610 	  return EXPAND_DONE;
611 	}
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)
617 	{
618 	  /* GT, use slts instruction */
619 	  emit_insn (gen_slts_compare (operands[0], operands[3], operands[2]));
620 	}
621       else
622 	{
623 	  /* GTU, use slt instruction */
624 	  emit_insn (gen_slt_compare  (operands[0], operands[3], operands[2]));
625 	}
626 
627       return EXPAND_DONE;
628 
629     case GE:
630     case GEU:
631       if (GET_CODE (operands[3]) == CONST_INT)
632 	{
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);
637 
638 	  emit_insn (gen_movsi (tmp_reg,
639 				gen_int_mode (INTVAL (operands[3]) - 1,
640 					      SImode)));
641 	  if (code == GE)
642 	    {
643 	      /* GE, use slts instruction */
644 	      emit_insn (gen_slts_compare (operands[0], tmp_reg, operands[2]));
645 	    }
646 	  else
647 	    {
648 	      /* GEU, use slt instruction */
649 	      emit_insn (gen_slt_compare  (operands[0], tmp_reg, operands[2]));
650 	    }
651 
652 	  return EXPAND_DONE;
653 	}
654       else
655 	{
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)
660 	    {
661 	      /* GE, use slts instruction */
662 	      emit_insn (gen_slts_compare (operands[0],
663 					   operands[2], operands[3]));
664 	    }
665 	  else
666 	    {
667 	      /* GEU, use slt instruction */
668 	      emit_insn (gen_slt_compare  (operands[0],
669 					   operands[2], operands[3]));
670 	    }
671 
672 	  /* perform 'not' behavior */
673 	  emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
674 
675 	  return EXPAND_DONE;
676 	}
677 
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)
683 	{
684 	  /* LT, use slts instruction */
685 	  emit_insn (gen_slts_compare (operands[0], operands[2], operands[3]));
686 	}
687       else
688 	{
689 	  /* LTU, use slt instruction */
690 	  emit_insn (gen_slt_compare  (operands[0], operands[2], operands[3]));
691 	}
692 
693       return EXPAND_DONE;
694 
695     case LE:
696     case LEU:
697       if (GET_CODE (operands[3]) == CONST_INT)
698 	{
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);
703 
704 	  emit_insn (gen_movsi (tmp_reg,
705 				gen_int_mode (INTVAL (operands[3]) + 1,
706 						      SImode)));
707 	  if (code == LE)
708 	    {
709 	      /* LE, use slts instruction */
710 	      emit_insn (gen_slts_compare (operands[0], operands[2], tmp_reg));
711 	    }
712 	  else
713 	    {
714 	      /* LEU, use slt instruction */
715 	      emit_insn (gen_slt_compare  (operands[0], operands[2], tmp_reg));
716 	    }
717 
718 	  return EXPAND_DONE;
719 	}
720       else
721 	{
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)
725 	    {
726 	      /* LE, use slts instruction */
727 	      emit_insn (gen_slts_compare (operands[0],
728 					   operands[3], operands[2]));
729 	    }
730 	  else
731 	    {
732 	      /* LEU, use slt instruction */
733 	      emit_insn (gen_slt_compare  (operands[0],
734 					   operands[3], operands[2]));
735 	    }
736 
737 	  /* perform 'not' behavior */
738 	  emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
739 
740 	  return EXPAND_DONE;
741 	}
742 
743 
744     default:
745       gcc_unreachable ();
746     }
747 }
748 
749 void
nds32_expand_float_cbranch(rtx * operands)750 nds32_expand_float_cbranch (rtx *operands)
751 {
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;
758 
759   int reverse = 0;
760 
761   /* Main Goal: Use compare instruction + branch instruction.
762 
763      For example:
764      GT, GE: swap condition and swap operands and generate
765      compare instruction(LT, LE) + branch not equal instruction.
766 
767      UNORDERED, LT, LE, EQ: no need to change and generate
768      compare instruction(UNORDERED, LT, LE, EQ) + branch not equal instruction.
769 
770      ORDERED, NE: reverse condition and generate
771      compare instruction(EQ) + branch equal instruction. */
772 
773   switch (code)
774     {
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;
808     }
809 
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)));
814 
815   PUT_CODE (operands[0], reverse ? EQ : NE);
816   emit_insn (gen_cbranchsi4 (operands[0], tmp_reg,
817 			     const0_rtx, operands[3]));
818 }
819 
820 void
nds32_expand_float_cstore(rtx * operands)821 nds32_expand_float_cstore (rtx *operands)
822 {
823   enum rtx_code code = GET_CODE (operands[1]);
824   enum rtx_code new_code = code;
825   machine_mode mode = GET_MODE (operands[2]);
826 
827   rtx cmp_op0 = operands[2];
828   rtx cmp_op1 = operands[3];
829   rtx tmp;
830 
831   /* Main Goal: Use compare instruction to store value.
832 
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
837 
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
842 
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
846 
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)
851     {
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));
869 
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));
877 
878       emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
879       return;
880     default:
881       return;
882     }
883 
884   emit_insn (gen_rtx_SET (operands[0],
885 			  gen_rtx_fmt_ee (new_code, SImode,
886 					  cmp_op0, cmp_op1)));
887 }
888 
889 enum nds32_expand_result_type
nds32_expand_movcc(rtx * operands)890 nds32_expand_movcc (rtx *operands)
891 {
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;
898 
899   if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE)
900       && XEXP (operands[1], 1) == const0_rtx)
901     {
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;
905     }
906   else if ((TARGET_FPU_SINGLE && cmp0_mode == SFmode)
907 	   || (TARGET_FPU_DOUBLE && cmp0_mode == DFmode))
908     {
909       nds32_expand_float_movcc (operands);
910     }
911   else
912     {
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;
921 
922       /* Main Goal: Use 'LT + EQ' or 'LT + NE' to target "then" part
923 	 Strategy : Reverse condition and swap comparison operands
924 
925 	 For example:
926 
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')
930 
931 	     a >= b ? P : Q   (GE or GEU)
932 	 --> a <  b ? Q : P   (reverse condition to achieve 'LT/LTU')
933 
934 	     a <  b ? P : Q   (LT or LTU)
935 	 --> (NO NEED TO CHANGE, it is already 'LT/LTU')
936 
937 	     a >  b ? P : Q   (GT or GTU)
938 	 --> b <  a ? P : Q   (swap comparison operands to achieve 'LT/LTU') */
939       switch (code)
940 	{
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;
951 	}
952 
953       /* For '>' comparison operator, we swap operands
954 	 so that we can have 'LT/LTU' operator.  */
955       if (new_code == GT || new_code == GTU)
956 	{
957 	  tmp     = cmp_op0;
958 	  cmp_op0 = cmp_op1;
959 	  cmp_op1 = tmp;
960 
961 	  new_code = swap_condition (new_code);
962 	}
963 
964       /* Use a temporary register to store slt/slts result.  */
965       tmp = gen_reg_rtx (SImode);
966 
967       if (new_code == EQ || new_code == NE)
968 	{
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);
972 	}
973       else
974 	{
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 ();
983 
984 	  /* Change comparison semantic into (eq X 0) or (ne X 0) behavior
985 	     so that cmovz or cmovn will be matched later.
986 
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
991 
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);
996 	}
997     }
998   return EXPAND_CREATE_TEMPLATE;
999 }
1000 
1001 void
nds32_expand_float_movcc(rtx * operands)1002 nds32_expand_float_movcc (rtx *operands)
1003 {
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)
1007     {
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;
1011     }
1012   else
1013     {
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;
1021 
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;
1025 
1026       /* Main Goal: Use cmpare instruction + conditional move instruction.
1027 	 Strategy : swap condition and swap comparison operands.
1028 
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')
1033 
1034 	     a >= b ? P : Q  (GE)
1035 	 --> a <= b ? Q : P  (swap condition)
1036 	 --> b <= a ? Q : P  (swap comparison operands to achieve 'GE')
1037 
1038 	     a <  b ? P : Q  (LT)
1039 	 --> (NO NEED TO CHANGE, it is already 'LT')
1040 
1041 	     a >= b ? P : Q  (LE)
1042 	 --> (NO NEED TO CHANGE, it is already 'LE')
1043 
1044 	     a == b ? P : Q  (EQ)
1045 	 --> (NO NEED TO CHANGE, it is already 'EQ') */
1046 
1047       switch (code)
1048 	{
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;
1082 	}
1083 
1084       /* Use a temporary register to store fcmpxxs result.  */
1085       tmp = gen_reg_rtx (SImode);
1086 
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))
1091 	{
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)));
1096 	}
1097       else
1098 	{
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));
1104 	}
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);
1109     }
1110 }
1111 
1112 void
nds32_emit_push_fpr_callee_saved(int base_offset)1113 nds32_emit_push_fpr_callee_saved (int base_offset)
1114 {
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;
1119 
1120   while (regno <= last_fpr)
1121     {
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;
1131     }
1132 }
1133 
1134 void
nds32_emit_pop_fpr_callee_saved(int gpr_padding_size)1135 nds32_emit_pop_fpr_callee_saved (int gpr_padding_size)
1136 {
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;
1143 
1144   while (regno <= last_fpr)
1145     {
1146       /* Handling two registers, using fldi.bi instruction.  */
1147       if ((regno + 1) >= last_fpr)
1148 	padding = gpr_padding_size;
1149 
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);
1157 
1158       adjust_sp_rtx =
1159 	gen_rtx_SET (stack_pointer_rtx,
1160 		     plus_constant (Pmode, stack_pointer_rtx,
1161 				    8 + padding));
1162 
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;
1169     }
1170 }
1171 
1172 void
nds32_emit_v3pop_fpr_callee_saved(int base)1173 nds32_emit_v3pop_fpr_callee_saved (int base)
1174 {
1175   int fpu_base_addr = base;
1176   int regno;
1177   rtx fpu_insn;
1178   rtx reg, mem;
1179   rtx dwarf;
1180 
1181   regno = cfun->machine->callee_saved_first_fpr_regno;
1182   while (regno <= cfun->machine->callee_saved_last_fpr_regno)
1183     {
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;
1195     }
1196 }
1197 
1198 /* ------------------------------------------------------------------------ */
1199 
1200 /* Function to return memory format.  */
1201 enum nds32_16bit_address_type
nds32_mem_format(rtx op)1202 nds32_mem_format (rtx op)
1203 {
1204   machine_mode mode_test;
1205   int val;
1206   int regno;
1207 
1208   if (!TARGET_16_BIT)
1209     return ADDRESS_NOT_16BIT_FORMAT;
1210 
1211   mode_test = GET_MODE (op);
1212 
1213   op = XEXP (op, 0);
1214 
1215   /* 45 format.  */
1216   if (GET_CODE (op) == REG
1217       && ((mode_test == SImode) || (mode_test == SFmode)))
1218     return ADDRESS_REG;
1219 
1220   /* 333 format for QI/HImode.  */
1221   if (GET_CODE (op) == REG && (REGNO (op) < R8_REGNUM))
1222     return ADDRESS_LO_REG_IMM3U;
1223 
1224   /* post_inc 333 format.  */
1225   if ((GET_CODE (op) == POST_INC)
1226       && ((mode_test == SImode) || (mode_test == SFmode)))
1227     {
1228       regno = REGNO(XEXP (op, 0));
1229 
1230       if (regno < 8)
1231 	return ADDRESS_POST_INC_LO_REG_IMM3U;
1232     }
1233 
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))))
1239     {
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;
1244     }
1245 
1246   if ((GET_CODE (op) == PLUS)
1247       && (GET_CODE (XEXP (op, 0)) == REG)
1248       && (GET_CODE (XEXP (op, 1)) == CONST_INT))
1249     {
1250       val = INTVAL (XEXP (op, 1));
1251 
1252       regno = REGNO(XEXP (op, 0));
1253 
1254       if (regno > 8
1255 	  && regno != SP_REGNUM
1256 	  && regno != FP_REGNUM)
1257 	return ADDRESS_NOT_16BIT_FORMAT;
1258 
1259       switch (mode_test)
1260 	{
1261 	case E_QImode:
1262 	  /* 333 format.  */
1263 	  if (val >= 0 && val < 8 && regno < 8)
1264 	    return ADDRESS_LO_REG_IMM3U;
1265 	  break;
1266 
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;
1272 
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;
1292 
1293 	default:
1294 	  break;
1295 	}
1296     }
1297 
1298   return ADDRESS_NOT_16BIT_FORMAT;
1299 }
1300 
1301 /* Output 16-bit store.  */
1302 const char *
nds32_output_16bit_store(rtx * operands,int byte)1303 nds32_output_16bit_store (rtx *operands, int byte)
1304 {
1305   char pattern[100];
1306   char size;
1307   rtx code = XEXP (operands[0], 0);
1308 
1309   size = nds32_byte_to_size (byte);
1310 
1311   switch (nds32_mem_format (operands[0]))
1312     {
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;
1339     }
1340 
1341   return "";
1342 }
1343 
1344 /* Output 16-bit load.  */
1345 const char *
nds32_output_16bit_load(rtx * operands,int byte)1346 nds32_output_16bit_load (rtx *operands, int byte)
1347 {
1348   char pattern[100];
1349   unsigned char size;
1350   rtx code = XEXP (operands[1], 0);
1351 
1352   size = nds32_byte_to_size (byte);
1353 
1354   switch (nds32_mem_format (operands[1]))
1355     {
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;
1385     }
1386 
1387   return "";
1388 }
1389 
1390 /* Output 32-bit store.  */
1391 const char *
nds32_output_32bit_store(rtx * operands,int byte)1392 nds32_output_32bit_store (rtx *operands, int byte)
1393 {
1394   char pattern[100];
1395   unsigned char size;
1396   rtx code = XEXP (operands[0], 0);
1397 
1398   size = nds32_byte_to_size (byte);
1399 
1400   switch (GET_CODE (code))
1401     {
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;
1408 
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;
1418 
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;
1426 
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;
1434 
1435     case POST_MODIFY:
1436       switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
1437 	{
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 ();
1455 	}
1456       break;
1457 
1458     case PLUS:
1459       switch (GET_CODE (XEXP (code, 1)))
1460 	{
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 ();
1476 	}
1477       break;
1478 
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;
1485 
1486     default:
1487       abort ();
1488     }
1489 
1490   output_asm_insn (pattern, operands);
1491   return "";
1492 }
1493 
1494 /* Output 32-bit load.  */
1495 const char *
nds32_output_32bit_load(rtx * operands,int byte)1496 nds32_output_32bit_load (rtx *operands, int byte)
1497 {
1498   char pattern[100];
1499   unsigned char size;
1500   rtx code;
1501 
1502   code = XEXP (operands[1], 0);
1503 
1504   size = nds32_byte_to_size (byte);
1505 
1506   switch (GET_CODE (code))
1507     {
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;
1514 
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;
1524 
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;
1532 
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;
1540 
1541     case POST_MODIFY:
1542       switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
1543 	{
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 ();
1561 	}
1562       break;
1563 
1564     case PLUS:
1565       switch (GET_CODE (XEXP (code, 1)))
1566 	{
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 ();
1581 	}
1582       break;
1583 
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;
1590 
1591     default:
1592       abort ();
1593     }
1594 
1595   output_asm_insn (pattern, operands);
1596   return "";
1597 }
1598 
1599 /* Output 32-bit load with signed extension.  */
1600 const char *
nds32_output_32bit_load_s(rtx * operands,int byte)1601 nds32_output_32bit_load_s (rtx *operands, int byte)
1602 {
1603   char pattern[100];
1604   unsigned char size;
1605   rtx code;
1606 
1607   code = XEXP (operands[1], 0);
1608 
1609   size = nds32_byte_to_size (byte);
1610 
1611   switch (GET_CODE (code))
1612     {
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;
1619 
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;
1629 
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;
1637 
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;
1645 
1646     case POST_MODIFY:
1647       switch (GET_CODE (XEXP (XEXP (code, 1), 1)))
1648 	{
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 ();
1666 	}
1667       break;
1668 
1669     case PLUS:
1670       switch (GET_CODE (XEXP (code, 1)))
1671 	{
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 ();
1686 	}
1687       break;
1688 
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;
1695 
1696     default:
1697       abort ();
1698     }
1699 
1700   output_asm_insn (pattern, operands);
1701   return "";
1702 }
1703 
1704 /* Function to output stack push operation.
1705    We need to deal with normal stack push multiple or stack v3push.  */
1706 const char *
nds32_output_stack_push(rtx par_rtx)1707 nds32_output_stack_push (rtx par_rtx)
1708 {
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;
1726 
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))
1731     {
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 "";
1740     }
1741 
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))
1747     {
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 "";
1756     }
1757 
1758   /* If we step here, we are going to do v3push or multiple push operation.  */
1759 
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))
1765     {
1766       /* For stack v3push:
1767 	   operands[0]: Re
1768 	   operands[1]: imm8u */
1769 
1770       /* This variable is to check if 'push25 Re,imm8u' is available.  */
1771       int sp_adjust;
1772 
1773       /* Set operands[0].  */
1774       operands[0] = gen_rtx_REG (SImode, re_callee_saved);
1775 
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
1786 	{
1787 	  /* Allocate callee saved fpr space.  */
1788 	  if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
1789 	    {
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);
1793 	    }
1794 	  else
1795 	    {
1796 	      operands[1] = GEN_INT (0);
1797 	    }
1798 	}
1799 
1800       /* Create assembly code pattern.  */
1801       snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1");
1802     }
1803   else
1804     {
1805       /* For normal stack push multiple:
1806 	 operands[0]: Rb
1807 	 operands[1]: Re
1808 	 operands[2]: En4 */
1809 
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;
1813 
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);
1817 
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)
1824 	{
1825 	  /* No need to generate instruction.  */
1826 	  return "";
1827 	}
1828       else
1829 	{
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;
1834 
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" : "");
1843 	}
1844     }
1845 
1846   /* We use output_asm_insn() to output assembly code by ourself.  */
1847   output_asm_insn (pattern, operands);
1848   return "";
1849 }
1850 
1851 /* Function to output stack pop operation.
1852    We need to deal with normal stack pop multiple or stack v3pop.  */
1853 const char *
nds32_output_stack_pop(rtx par_rtx ATTRIBUTE_UNUSED)1854 nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED)
1855 {
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;
1867 
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))
1871     {
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 "";
1880     }
1881 
1882   /* If we step here, we are going to do v3pop or multiple pop operation.  */
1883 
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))
1889     {
1890       /* For stack v3pop:
1891 	   operands[0]: Re
1892 	   operands[1]: imm8u */
1893 
1894       /* This variable is to check if 'pop25 Re,imm8u' is available.  */
1895       int sp_adjust;
1896 
1897       /* Set operands[0].  */
1898       operands[0] = gen_rtx_REG (SImode, re_callee_saved);
1899 
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
1916 	{
1917 	  if (cfun->machine->callee_saved_first_fpr_regno != SP_REGNUM)
1918 	    {
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);
1925 	    }
1926 	  else
1927 	    {
1928 	      operands[1] = GEN_INT (0);
1929 	    }
1930 	}
1931 
1932       /* Create assembly code pattern.  */
1933       snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1");
1934     }
1935   else
1936     {
1937       /* For normal stack pop multiple:
1938 	 operands[0]: Rb
1939 	 operands[1]: Re
1940 	 operands[2]: En4 */
1941 
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;
1945 
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);
1949 
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)
1956 	{
1957 	  /* No need to generate instruction.  */
1958 	  return "";
1959 	}
1960       else
1961 	{
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;
1966 
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" : "");
1975 	}
1976     }
1977 
1978   /* We use output_asm_insn() to output assembly code by ourself.  */
1979   output_asm_insn (pattern, operands);
1980   return "";
1981 }
1982 
1983 /* Function to output return operation.  */
1984 const char *
nds32_output_return(void)1985 nds32_output_return (void)
1986 {
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;
1996 
1997   /* Set operands[0].  */
1998   operands[0] = gen_rtx_REG (SImode, re_callee_saved);
1999 
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);
2017 
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 "";
2023 }
2024 
2025 /* Function to generate PC relative jump table.
2026    Refer to nds32.md for more details.
2027 
2028    The following is the sample for the case that diff value
2029    can be presented in '.short' size.
2030 
2031      addi    $r1, $r1, -(case_lower_bound)
2032      slti    $ta, $r1, (case_number)
2033      beqz    $ta, .L_skip_label
2034 
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
2039 
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 *
nds32_output_casesi_pc_relative(rtx * operands)2053 nds32_output_casesi_pc_relative (rtx *operands)
2054 {
2055   machine_mode mode;
2056   rtx diff_vec;
2057 
2058   diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[1])));
2059 
2060   gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC);
2061 
2062   /* Step C: "t <-- operands[1]".  */
2063   output_asm_insn ("la\t$ta, %l1", operands);
2064 
2065   /* Get the mode of each element in the difference vector.  */
2066   mode = GET_MODE (diff_vec);
2067 
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)
2071     {
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 ();
2083     }
2084 
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);
2089 
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";
2095 }
2096 
2097 /* output a float load instruction */
2098 const char *
nds32_output_float_load(rtx * operands)2099 nds32_output_float_load (rtx *operands)
2100 {
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))
2107     {
2108     case REG:
2109       pattern = "fl%ci\t%%0, %%1";
2110       break;
2111 
2112     case PLUS:
2113       addr_op0 = XEXP (addr, 0);
2114       addr_op1 = XEXP (addr, 1);
2115 
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;
2127 
2128     case POST_MODIFY:
2129       addr_op0 = XEXP (addr, 0);
2130       addr_op1 = XEXP (addr, 1);
2131 
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;
2141 
2142     case POST_INC:
2143       if (REG_P (XEXP (addr, 0)))
2144 	{
2145 	  if (dp)
2146 	    pattern = "fl%ci.bi\t%%0, %%1, 8";
2147 	  else
2148 	    pattern = "fl%ci.bi\t%%0, %%1, 4";
2149 	}
2150       else
2151 	gcc_unreachable ();
2152       break;
2153 
2154     case POST_DEC:
2155       if (REG_P (XEXP (addr, 0)))
2156 	{
2157 	  if (dp)
2158 	    pattern = "fl%ci.bi\t%%0, %%1, -8";
2159 	  else
2160 	    pattern = "fl%ci.bi\t%%0, %%1, -4";
2161 	}
2162       else
2163 	gcc_unreachable ();
2164       break;
2165 
2166     default:
2167       gcc_unreachable ();
2168     }
2169 
2170   sprintf (buff, pattern, dp ? 'd' : 's');
2171   output_asm_insn (buff, operands);
2172   return "";
2173 }
2174 
2175 /* output a float store instruction */
2176 const char *
nds32_output_float_store(rtx * operands)2177 nds32_output_float_store (rtx *operands)
2178 {
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))
2185     {
2186     case REG:
2187       pattern = "fs%ci\t%%1, %%0";
2188       break;
2189 
2190     case PLUS:
2191       addr_op0 = XEXP (addr, 0);
2192       addr_op1 = XEXP (addr, 1);
2193 
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;
2205 
2206     case POST_MODIFY:
2207       addr_op0 = XEXP (addr, 0);
2208       addr_op1 = XEXP (addr, 1);
2209 
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;
2219 
2220     case POST_INC:
2221       if (REG_P (XEXP (addr, 0)))
2222 	{
2223 	  if (dp)
2224 	    pattern = "fs%ci.bi\t%%1, %%0, 8";
2225 	  else
2226 	    pattern = "fs%ci.bi\t%%1, %%0, 4";
2227 	}
2228       else
2229 	gcc_unreachable ();
2230       break;
2231 
2232     case POST_DEC:
2233       if (REG_P (XEXP (addr, 0)))
2234 	{
2235 	  if (dp)
2236 	    pattern = "fs%ci.bi\t%%1, %%0, -8";
2237 	  else
2238 	    pattern = "fs%ci.bi\t%%1, %%0, -4";
2239 	}
2240       else
2241 	gcc_unreachable ();
2242       break;
2243 
2244     default:
2245       gcc_unreachable ();
2246     }
2247 
2248   sprintf (buff, pattern, dp ? 'd' : 's');
2249   output_asm_insn (buff, operands);
2250   return "";
2251 }
2252 
2253 /* Function to generate normal jump table.  */
2254 const char *
nds32_output_casesi(rtx * operands)2255 nds32_output_casesi (rtx *operands)
2256 {
2257   /* Step C: "t <-- operands[1]".  */
2258   output_asm_insn ("la\t$ta, %l1", operands);
2259 
2260   /* Step D: "z <-- (mem (plus (operands[0] << 2) t))".  */
2261   output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands);
2262 
2263   /* No need to perform Step E, which is only used for
2264      pc relative jump table.  */
2265 
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";
2271 }
2272 
2273 /* Auxiliary functions for lwm/smw.  */
2274 bool
nds32_valid_smw_lwm_base_p(rtx op)2275 nds32_valid_smw_lwm_base_p (rtx op)
2276 {
2277   rtx base_addr;
2278 
2279   if (!MEM_P (op))
2280     return false;
2281 
2282   base_addr = XEXP (op, 0);
2283 
2284   if (REG_P (base_addr))
2285     return true;
2286   else
2287     {
2288       if (GET_CODE (base_addr) == POST_INC
2289 	  && REG_P (XEXP (base_addr, 0)))
2290         return true;
2291     }
2292 
2293   return false;
2294 }
2295 
2296 /* ------------------------------------------------------------------------ */
2297 const char *
nds32_output_smw_single_word(rtx * operands)2298 nds32_output_smw_single_word (rtx *operands)
2299 {
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];
2307 
2308   if (REG_P (XEXP (base_addr, 0)))
2309     {
2310       update_base_p = false;
2311       base_reg = XEXP (base_addr, 0);
2312     }
2313   else
2314     {
2315       update_base_p = true;
2316       base_reg = XEXP (XEXP (base_addr, 0), 0);
2317     }
2318 
2319   const char *update_base = update_base_p ? "m" : "";
2320 
2321   regno = REGNO (operands[1]);
2322 
2323   otherops[0] = base_reg;
2324   otherops[1] = operands[1];
2325 
2326   if (regno >= 28)
2327     {
2328       enable4 = nds32_regno_to_enable4 (regno);
2329       sprintf (buff, "smw.bi%s\t$sp, [%%0], $sp, %x", update_base, enable4);
2330     }
2331   else
2332     {
2333       sprintf (buff, "smw.bi%s\t%%1, [%%0], %%1", update_base);
2334     }
2335   output_asm_insn (buff, otherops);
2336   return "";
2337 }
2338 
2339 const char *
nds32_output_lmw_single_word(rtx * operands)2340 nds32_output_lmw_single_word (rtx *operands)
2341 {
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];
2349 
2350   if (REG_P (XEXP (base_addr, 0)))
2351     {
2352       update_base_p = false;
2353       base_reg = XEXP (base_addr, 0);
2354     }
2355   else
2356     {
2357       update_base_p = true;
2358       base_reg = XEXP (XEXP (base_addr, 0), 0);
2359     }
2360 
2361   const char *update_base = update_base_p ? "m" : "";
2362 
2363   regno = REGNO (operands[0]);
2364 
2365   otherops[0] = operands[0];
2366   otherops[1] = base_reg;
2367 
2368   if (regno >= 28)
2369     {
2370       enable4 = nds32_regno_to_enable4 (regno);
2371       sprintf (buff, "lmw.bi%s\t$sp, [%%1], $sp, %x", update_base, enable4);
2372     }
2373   else
2374     {
2375       sprintf (buff, "lmw.bi%s\t%%0, [%%1], %%0", update_base);
2376     }
2377   output_asm_insn (buff, otherops);
2378   return "";
2379 }
2380 
2381 void
nds32_expand_unaligned_load(rtx * operands,enum machine_mode mode)2382 nds32_expand_unaligned_load (rtx *operands, enum machine_mode mode)
2383 {
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;
2396 
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
2407 
2408        lbi temp_reg, [mem + (offset + 1)]
2409        sll temp_reg, (8 * (shift + 1))
2410        ior reg0, temp_reg  */
2411 
2412   temp_reg = gen_reg_rtx (SImode);
2413   temp_sub_reg = gen_lowpart (QImode, temp_reg);
2414 
2415   if (mode == DImode)
2416     {
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;
2424     }
2425   else
2426     {
2427       reg[0] = operands[0];
2428     }
2429 
2430   for (num_reg = (mode == DImode) ? 2 : 1; num_reg > 0; num_reg--)
2431     {
2432       sub_reg = gen_lowpart (QImode, reg[0]);
2433       mem[0] = gen_rtx_MEM (QImode, plus_constant (Pmode, operands[1], offset));
2434 
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));
2440 
2441       while (width > 0)
2442 	{
2443 	  offset = offset + offset_adj;
2444 	  shift++;
2445 	  width--;
2446 
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));
2458 	}
2459 
2460       if (mode == DImode)
2461 	{
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;
2467 	}
2468     }
2469 }
2470 
2471 void
nds32_expand_unaligned_store(rtx * operands,enum machine_mode mode)2472 nds32_expand_unaligned_store (rtx *operands, enum machine_mode mode)
2473 {
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;
2486 
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]  */
2495 
2496   temp_reg = gen_reg_rtx (SImode);
2497   temp_sub_reg = gen_lowpart (QImode, temp_reg);
2498 
2499   if (mode == DImode)
2500     {
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;
2508     }
2509   else
2510     {
2511       reg[0] = operands[1];
2512     }
2513 
2514   for (num_reg = (mode == DImode) ? 2 : 1; num_reg > 0; num_reg--)
2515     {
2516       sub_reg = gen_lowpart (QImode, reg[0]);
2517       mem[0] = gen_rtx_MEM (QImode, plus_constant (Pmode, operands[0], offset));
2518 
2519       /* Generating the first part instructions.
2520 	   sbi reg0, [mem + 0] */
2521       emit_move_insn (mem[0], sub_reg);
2522 
2523       while (width > 0)
2524 	{
2525 	  offset = offset + offset_adj;
2526 	  shift++;
2527 	  width--;
2528 
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);
2538 	}
2539 
2540       if (mode == DImode)
2541 	{
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;
2547 	}
2548     }
2549 }
2550 
2551 /* Using multiple load/store instruction to output doubleword instruction.  */
2552 const char *
nds32_output_double(rtx * operands,bool load_p)2553 nds32_output_double (rtx *operands, bool load_p)
2554 {
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);
2560 
2561   otherops[0] = gen_rtx_REG (SImode, REGNO (operands[reg]));
2562   otherops[1] = gen_rtx_REG (SImode, REGNO (operands[reg]) + 1);
2563 
2564   if (GET_CODE (addr)  == POST_INC)
2565     {
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');
2570     }
2571   else
2572     {
2573       /* (mem (reg)) */
2574       otherops[2] = addr;
2575       snprintf (pattern, sizeof (pattern),
2576 		"%cmw.bi\t%%0, [%%2], %%1, 0", load_p ? 'l' : 's');
2577 
2578     }
2579 
2580   output_asm_insn (pattern, otherops);
2581   return "";
2582 }
2583 
2584 const char *
nds32_output_cbranchsi4_equality_zero(rtx_insn * insn,rtx * operands)2585 nds32_output_cbranchsi4_equality_zero (rtx_insn *insn, rtx *operands)
2586 {
2587   enum rtx_code code;
2588   bool long_jump_p = false;
2589 
2590   code = GET_CODE (operands[0]);
2591 
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
2595 
2596      For 32-bit case,
2597      we assume it is always reachable. (but check range -65500 ~ 65500)
2598 
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.  */
2604 
2605   switch (get_attr_length (insn))
2606     {
2607     case 8:
2608       long_jump_p = true;
2609       /* fall through  */
2610     case 2:
2611       if (which_alternative == 0)
2612 	{
2613 	  /* constraint: t */
2614 	  /*    b<cond>zs8  .L0
2615 	      or
2616 		b<inverse_cond>zs8  .LCB0
2617 		j  .L0
2618 	      .LCB0:
2619 	   */
2620 	  output_cond_branch_compare_zero (code, "s8", long_jump_p,
2621 					   operands, true);
2622 	  return "";
2623 	}
2624       else if (which_alternative == 1)
2625 	{
2626 	  /* constraint: l */
2627 	  /*    b<cond>z38  $r0, .L0
2628 	      or
2629 		b<inverse_cond>z38  $r0, .LCB0
2630 		j  .L0
2631 	      .LCB0:
2632 	   */
2633 	  output_cond_branch_compare_zero (code, "38", long_jump_p,
2634 					   operands, false);
2635 	  return "";
2636 	}
2637       else
2638 	{
2639 	  /* constraint: r */
2640 	  /* For which_alternative==2, it should not be here.  */
2641 	  gcc_unreachable ();
2642 	}
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 "";
2651 
2652     default:
2653       gcc_unreachable ();
2654     }
2655 }
2656 
2657 const char *
nds32_output_cbranchsi4_equality_reg(rtx_insn * insn,rtx * operands)2658 nds32_output_cbranchsi4_equality_reg (rtx_insn *insn, rtx *operands)
2659 {
2660   enum rtx_code code;
2661   bool long_jump_p, r5_p;
2662   int insn_length;
2663 
2664   insn_length = get_attr_length (insn);
2665 
2666   long_jump_p = (insn_length == 10 || insn_length == 8) ? true : false;
2667   r5_p = (insn_length == 2 || insn_length == 8) ? true : false;
2668 
2669   code = GET_CODE (operands[0]);
2670 
2671   /* This register-comparison conditional branch has one form:
2672        32-bit instruction =>          beq/bne           imm14s << 1
2673 
2674      For 32-bit case,
2675      we assume it is always reachable. (but check range -16350 ~ 16350).  */
2676 
2677   switch (code)
2678     {
2679     case EQ:
2680     case NE:
2681       output_cond_branch (code, "", r5_p, long_jump_p, operands);
2682       return "";
2683 
2684     default:
2685       gcc_unreachable ();
2686     }
2687 }
2688 
2689 const char *
nds32_output_cbranchsi4_equality_reg_or_const_int(rtx_insn * insn,rtx * operands)2690 nds32_output_cbranchsi4_equality_reg_or_const_int (rtx_insn *insn,
2691 						   rtx *operands)
2692 {
2693   enum rtx_code code;
2694   bool long_jump_p, r5_p;
2695   int insn_length;
2696 
2697   insn_length = get_attr_length (insn);
2698 
2699   long_jump_p = (insn_length == 10 || insn_length == 8) ? true : false;
2700   r5_p = (insn_length == 2 || insn_length == 8) ? true : false;
2701 
2702   code = GET_CODE (operands[0]);
2703 
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
2707 
2708      For 32-bit case, we assume it is always reachable.
2709      (but check range -16350 ~ 16350 and -250 ~ 250).  */
2710 
2711   switch (code)
2712     {
2713     case EQ:
2714     case NE:
2715       if (which_alternative == 2)
2716 	{
2717 	  /* r, Is11 */
2718 	  /* b<cond>c */
2719 	  output_cond_branch (code, "c", r5_p, long_jump_p, operands);
2720 	}
2721       else
2722 	{
2723 	  /* r, r */
2724 	  /* v, r */
2725 	  output_cond_branch (code, "", r5_p, long_jump_p, operands);
2726 	}
2727       return "";
2728     default:
2729       gcc_unreachable ();
2730     }
2731 }
2732 
2733 const char *
nds32_output_cbranchsi4_greater_less_zero(rtx_insn * insn,rtx * operands)2734 nds32_output_cbranchsi4_greater_less_zero (rtx_insn *insn, rtx *operands)
2735 {
2736   enum rtx_code code;
2737   bool long_jump_p;
2738   int insn_length;
2739 
2740   insn_length = get_attr_length (insn);
2741 
2742   gcc_assert (insn_length == 4 || insn_length == 10);
2743 
2744   long_jump_p = (insn_length == 10) ? true : false;
2745 
2746   code = GET_CODE (operands[0]);
2747 
2748   /* This zero-greater-less-comparison conditional branch has one form:
2749        32-bit instruction =>      bgtz/bgez/bltz/blez     imm16s << 1
2750 
2751      For 32-bit case, we assume it is always reachable.
2752      (but check range -65500 ~ 65500).  */
2753 
2754   switch (code)
2755     {
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 ();
2764     }
2765   return "";
2766 }
2767 
2768 /* Return true if SYMBOL_REF X binds locally.  */
2769 
2770 static bool
nds32_symbol_binds_local_p(const_rtx x)2771 nds32_symbol_binds_local_p (const_rtx x)
2772 {
2773   return (SYMBOL_REF_DECL (x)
2774 	  ? targetm.binds_local_p (SYMBOL_REF_DECL (x))
2775 	  : SYMBOL_REF_LOCAL_P (x));
2776 }
2777 
2778 const char *
nds32_output_call(rtx insn,rtx * operands,rtx symbol,const char * long_call,const char * call,bool align_p)2779 nds32_output_call (rtx insn, rtx *operands, rtx symbol, const char *long_call,
2780 		   const char *call, bool align_p)
2781 {
2782   char pattern[100];
2783   bool noreturn_p;
2784 
2785   if (GET_CODE (symbol) == CONST)
2786     {
2787       symbol= XEXP (symbol, 0);
2788 
2789       if (GET_CODE (symbol) == PLUS)
2790         symbol = XEXP (symbol, 0);
2791     }
2792 
2793   gcc_assert (GET_CODE (symbol) == SYMBOL_REF
2794 	      || REG_P (symbol));
2795 
2796   if (nds32_long_call_p (symbol))
2797     strcpy (pattern, long_call);
2798   else
2799     strcpy (pattern, call);
2800 
2801   if (align_p)
2802     strcat (pattern, "\n\t.align 2");
2803 
2804   noreturn_p = find_reg_note (insn, REG_NORETURN, NULL_RTX) != NULL_RTX;
2805 
2806   if (noreturn_p)
2807     {
2808       if (TARGET_16_BIT)
2809 	strcat (pattern, "\n\tnop16");
2810       else
2811 	strcat (pattern, "\n\tnop");
2812     }
2813 
2814   output_asm_insn (pattern, operands);
2815   return "";
2816 }
2817 
2818 /* Spilt a doubleword instrucion to two single word instructions.  */
2819 void
nds32_spilt_doubleword(rtx * operands,bool load_p)2820 nds32_spilt_doubleword (rtx *operands, bool load_p)
2821 {
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);
2828 
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);
2835 
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)
2841     {
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);
2845 
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))));
2859     }
2860   else if (GET_CODE (sub_mem) == POST_MODIFY)
2861     {
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);
2865 
2866       /* Extract (const) from the (post_modify (reg) (plus (reg) (const)))
2867 	 pattern.  */
2868 
2869       rtx plus_op = XEXP (sub_mem, 1);
2870       rtx post_val = XEXP (plus_op, 1);
2871 
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));
2883     }
2884   else
2885     {
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);
2889     }
2890 
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.
2902 
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)
2912     {
2913       operands[2] = high_part[0];
2914       operands[3] = high_part[1];
2915       operands[4] = low_part[0];
2916       operands[5] = low_part[1];
2917     }
2918   else
2919     {
2920       operands[2] = low_part[0];
2921       operands[3] = low_part[1];
2922       operands[4] = high_part[0];
2923       operands[5] = high_part[1];
2924     }
2925 }
2926 
2927 /* Return true X is need use long call.  */
2928 bool
nds32_long_call_p(rtx symbol)2929 nds32_long_call_p (rtx symbol)
2930 {
2931   return TARGET_CMODEL_LARGE;
2932 }
2933 
2934 void
nds32_expand_constant(machine_mode mode,HOST_WIDE_INT val,rtx target,rtx source)2935 nds32_expand_constant (machine_mode mode, HOST_WIDE_INT val,
2936 		       rtx target, rtx source)
2937 {
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;
2942 
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);
2947 
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;
2952 
2953   if (clear_sign_bit_copies > 0 && clear_sign_bit_copies < 17
2954       && (remainder | sign_shift_mask) == 0xffffffffUL)
2955     {
2956       /* Transfer AND to two shifts, example:
2957 	 a = b & 0x7fffffff => (b << 1) >> 1 */
2958       rtx shift = GEN_INT (clear_sign_bit_copies);
2959 
2960       emit_insn (gen_ashlsi3 (temp, source, shift));
2961       emit_insn (gen_lshrsi3 (target, temp, shift));
2962     }
2963   else if (clear_zero_bit_copies > 0 && clear_sign_bit_copies < 17
2964 	   && (remainder | zero_shift_mask) == 0xffffffffUL)
2965     {
2966       /* Transfer AND to two shifts, example:
2967 	 a = b & 0xfff00000 => (b >> 20) << 20 */
2968       rtx shift = GEN_INT (clear_zero_bit_copies);
2969 
2970       emit_insn (gen_lshrsi3 (temp, source, shift));
2971       emit_insn (gen_ashlsi3 (target, temp, shift));
2972     }
2973   else
2974     {
2975       emit_move_insn (temp, GEN_INT (val));
2976       emit_move_insn (target, gen_rtx_fmt_ee (AND, mode, source, temp));
2977     }
2978 }
2979