1 /* Subroutines for assembler code output on the DSP1610.
2    Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc.
3    Contributed by Michael Collison (collison@isisinc.net).
4 
5 This file is part of GNU CC.
6 
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11 
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21 
22 /* Some output-actions in dsp1600.md need these.  */
23 #include "config.h"
24 #include "system.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "output.h"
32 #include "insn-attr.h"
33 #include "tree.h"
34 #include "expr.h"
35 #include "function.h"
36 #include "flags.h"
37 #include "ggc.h"
38 #include "toplev.h"
39 #include "recog.h"
40 #include "tm_p.h"
41 #include "target.h"
42 #include "target-def.h"
43 
44 const char *text_seg_name;
45 const char *rsect_text;
46 const char *data_seg_name;
47 const char *rsect_data;
48 const char *bss_seg_name;
49 const char *rsect_bss;
50 const char *const_seg_name;
51 const char *rsect_const;
52 
53 const char *chip_name;
54 const char *save_chip_name;
55 
56 /* Save the operands of a compare. The 16xx has not lt or gt, so
57    in these cases we swap the operands and reverse the condition.  */
58 
59 rtx dsp16xx_compare_op0;
60 rtx dsp16xx_compare_op1;
61 rtx (*dsp16xx_compare_gen) PARAMS (());
62 
63 static const char *fp;
64 static const char *sp;
65 static const char *rr;
66 static const char *a1h;
67 
68 struct dsp16xx_frame_info current_frame_info;
69 struct dsp16xx_frame_info zero_frame_info;
70 
71 rtx dsp16xx_addhf3_libcall = (rtx) 0;
72 rtx dsp16xx_subhf3_libcall = (rtx) 0;
73 rtx dsp16xx_mulhf3_libcall = (rtx) 0;
74 rtx dsp16xx_divhf3_libcall = (rtx) 0;
75 rtx dsp16xx_cmphf3_libcall = (rtx) 0;
76 rtx dsp16xx_fixhfhi2_libcall = (rtx) 0;
77 rtx dsp16xx_floathihf2_libcall = (rtx) 0;
78 rtx dsp16xx_neghf2_libcall = (rtx) 0;
79 
80 rtx dsp16xx_mulhi3_libcall = (rtx) 0;
81 rtx dsp16xx_udivqi3_libcall = (rtx) 0;
82 rtx dsp16xx_udivhi3_libcall = (rtx) 0;
83 rtx dsp16xx_divqi3_libcall = (rtx) 0;
84 rtx dsp16xx_divhi3_libcall = (rtx) 0;
85 rtx dsp16xx_modqi3_libcall = (rtx) 0;
86 rtx dsp16xx_modhi3_libcall = (rtx) 0;
87 rtx dsp16xx_umodqi3_libcall = (rtx) 0;
88 rtx dsp16xx_umodhi3_libcall = (rtx) 0;
89 rtx dsp16xx_ashrhi3_libcall = (rtx) 0;
90 rtx dsp16xx_ashlhi3_libcall = (rtx) 0;
91 rtx dsp16xx_ucmphi2_libcall = (rtx) 0;
92 rtx dsp16xx_lshrhi3_libcall = (rtx) 0;
93 
94 static const char *const himode_reg_name[] = HIMODE_REGISTER_NAMES;
95 
96 #define SHIFT_INDEX_1   0
97 #define SHIFT_INDEX_4   1
98 #define SHIFT_INDEX_8   2
99 #define SHIFT_INDEX_16  3
100 
101 static const char *const ashift_right_asm[] =
102 {
103   "%0=%0>>1",
104   "%0=%0>>4",
105   "%0=%0>>8",
106   "%0=%0>>16"
107 };
108 
109 static const char *const ashift_right_asm_first[] =
110 {
111   "%0=%1>>1",
112   "%0=%1>>4",
113   "%0=%1>>8",
114   "%0=%1>>16"
115 };
116 
117 static const char *const ashift_left_asm[] =
118 {
119   "%0=%0<<1",
120   "%0=%0<<4",
121   "%0=%0<<8",
122   "%0=%0<<16"
123 };
124 
125 static const char *const ashift_left_asm_first[] =
126 {
127   "%0=%1<<1",
128   "%0=%1<<4",
129   "%0=%1<<8",
130   "%0=%1<<16"
131 };
132 
133 static const char *const lshift_right_asm[] =
134 {
135   "%0=%0>>1\n\t%0=%b0&0x7fff",
136   "%0=%0>>4\n\t%0=%b0&0x0fff",
137   "%0=%0>>8\n\t%0=%b0&0x00ff",
138   "%0=%0>>16\n\t%0=%b0&0x0000"
139 };
140 
141 static const char *const lshift_right_asm_first[] =
142 {
143   "%0=%1>>1\n\t%0=%b0&0x7fff",
144   "%0=%1>>4\n\t%0=%b0&0x0fff",
145   "%0=%1>>8\n\t%0=%b0&0x00ff",
146   "%0=%1>>16\n\t%0=%b0&0x0000"
147 };
148 
149 static int reg_save_size PARAMS ((void));
150 static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
151 static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
152 
153 /* Initialize the GCC target structure.  */
154 #undef TARGET_ASM_BYTE_OP
155 #define TARGET_ASM_BYTE_OP "\tint\t"
156 #undef TARGET_ASM_ALIGNED_HI_OP
157 #define TARGET_ASM_ALIGNED_HI_OP NULL
158 #undef TARGET_ASM_ALIGNED_SI_OP
159 #define TARGET_ASM_ALIGNED_SI_OP NULL
160 
161 #undef TARGET_ASM_FUNCTION_PROLOGUE
162 #define TARGET_ASM_FUNCTION_PROLOGUE dsp16xx_output_function_prologue
163 #undef TARGET_ASM_FUNCTION_EPILOGUE
164 #define TARGET_ASM_FUNCTION_EPILOGUE dsp16xx_output_function_epilogue
165 
166 struct gcc_target targetm = TARGET_INITIALIZER;
167 
168 int
hard_regno_mode_ok(regno,mode)169 hard_regno_mode_ok (regno, mode)
170      int regno;
171      enum machine_mode mode;
172 {
173   switch ((int) mode)
174     {
175     case VOIDmode:
176       return 1;
177 
178       /* We can't use the c0-c2 for QImode, since they are only
179 	 8 bits in length.  */
180 
181     case QImode:
182       if (regno != REG_C0 && regno != REG_C1 && regno != REG_C2)
183 	return 1;
184       else
185 	return 0;
186 
187       /* We only allow a0, a1, y, and p to be allocated for 32-bit modes.
188          Additionally we allow the virtual ybase registers to be used for 32-bit
189 	 modes.  */
190 
191     case HFmode:
192     case SFmode:
193     case DFmode:
194     case XFmode:
195     case HImode:
196     case SImode:
197     case DImode:
198       if (regno == REG_A0 || regno == REG_A1 || regno == REG_Y || regno == REG_PROD
199 	  || (IS_YBASE_REGISTER_WINDOW(regno) && ((regno & 1) == 0)))
200 	return 1;
201       else
202 	return 0;
203 
204     default:
205       return 0;
206     }
207 }
208 
209 enum reg_class
dsp16xx_reg_class_from_letter(c)210 dsp16xx_reg_class_from_letter (c)
211      int c;
212 {
213   switch (c)
214     {
215     case 'A':
216       return ACCUM_REGS;
217 
218     case 'l':
219       return A0_REG;
220 
221     case 'C':
222       return A1_REG;
223 
224     case 'h':
225       return ACCUM_HIGH_REGS;
226 
227     case 'j':
228       return A0H_REG;
229 
230     case 'k':
231       return A0L_REG;
232 
233     case 'q':
234       return A1H_REG;
235 
236     case 'u':
237       return A1L_REG;
238 
239     case 'x':
240       return X_REG;
241 
242     case 'y':
243       return YH_REG;
244 
245     case 'z':
246       return YL_REG;
247 
248     case 't':
249       return P_REG;
250 
251     case 'Z':
252       return Y_OR_P_REGS;
253 
254     case 'd':
255       return ACCUM_Y_OR_P_REGS;
256 
257     case 'a':
258       return Y_ADDR_REGS;
259 
260     case 'B':
261       return (TARGET_BMU ? BMU_REGS : NO_REGS);
262 
263     case 'Y':
264       return YBASE_VIRT_REGS;
265 
266     case 'v':
267       return PH_REG;
268 
269     case 'w':
270       return PL_REG;
271 
272     case 'W':
273       return J_REG;
274 
275     case 'e':
276       return YBASE_ELIGIBLE_REGS;
277 
278     case 'b':
279       return ACCUM_LOW_REGS;
280 
281     case 'c':
282       return NON_YBASE_REGS;
283 
284     case 'f':
285       return Y_REG;
286 
287     case 'D':
288       return SLOW_MEM_LOAD_REGS;
289 
290     default:
291       return NO_REGS;
292     }
293 }
294 
295 /* Return the class number of the smallest class containing
296    reg number REGNO.  */
297 
298 int
regno_reg_class(regno)299 regno_reg_class(regno)
300      int regno;
301 {
302   switch (regno)
303     {
304     case REG_A0L:
305       return (int) A0L_REG;
306     case REG_A1L:
307       return (int) A1L_REG;
308 
309     case REG_A0:
310       return (int) A0H_REG;
311     case REG_A1:
312       return (int) A1H_REG;
313 
314     case REG_X:
315       return (int) X_REG;
316 
317     case REG_Y:
318       return (int) YH_REG;
319     case REG_YL:
320       return (int) YL_REG;
321 
322     case REG_PROD:
323       return (int) PH_REG;
324     case REG_PRODL:
325       return (int) PL_REG;
326 
327     case REG_R0: case REG_R1: case REG_R2: case REG_R3:
328       return (int) Y_ADDR_REGS;
329 
330     case REG_J:
331       return (int) J_REG;
332     case REG_K:
333       return (int) GENERAL_REGS;
334 
335     case REG_YBASE:
336       return (int) GENERAL_REGS;
337 
338     case REG_PT:
339       return (int) GENERAL_REGS;
340 
341     case REG_AR0: case REG_AR1: case REG_AR2: case REG_AR3:
342       return (int) BMU_REGS;
343 
344     case REG_C0: case REG_C1: case REG_C2:
345       return (int) GENERAL_REGS;
346 
347     case REG_PR:
348       return (int) GENERAL_REGS;
349 
350     case REG_RB:
351       return (int) GENERAL_REGS;
352 
353     case REG_YBASE0: case REG_YBASE1: case REG_YBASE2: case REG_YBASE3:
354     case REG_YBASE4: case REG_YBASE5: case REG_YBASE6: case REG_YBASE7:
355     case REG_YBASE8: case REG_YBASE9: case REG_YBASE10: case REG_YBASE11:
356     case REG_YBASE12: case REG_YBASE13: case REG_YBASE14: case REG_YBASE15:
357     case REG_YBASE16: case REG_YBASE17: case REG_YBASE18: case REG_YBASE19:
358     case REG_YBASE20: case REG_YBASE21: case REG_YBASE22: case REG_YBASE23:
359     case REG_YBASE24: case REG_YBASE25: case REG_YBASE26: case REG_YBASE27:
360     case REG_YBASE28: case REG_YBASE29: case REG_YBASE30: case REG_YBASE31:
361       return (int) YBASE_VIRT_REGS;
362 
363     default:
364       return (int) NO_REGS;
365     }
366 }
367 
368 /* A C expression for the maximum number of consecutive registers of class CLASS
369    needed to hold a value of mode MODE.  */
370 
371 int
class_max_nregs(class,mode)372 class_max_nregs(class, mode)
373      enum reg_class class ATTRIBUTE_UNUSED;
374      enum machine_mode mode;
375 {
376     return (GET_MODE_SIZE(mode));
377 }
378 
379 enum reg_class
limit_reload_class(mode,class)380 limit_reload_class (mode, class)
381      enum machine_mode mode ATTRIBUTE_UNUSED;
382      enum reg_class class;
383 {
384   return class;
385 }
386 
387 int
dsp16xx_register_move_cost(from,to)388 dsp16xx_register_move_cost (from, to)
389      enum reg_class from, to;
390 {
391   if (from == A0H_REG || from == A0L_REG || from == A0_REG ||
392       from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG ||
393       from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS)
394     {
395       if (to == Y_REG || to == P_REG)
396 	return 4;
397       else
398 	return 2;
399     }
400 
401   if (to == A0H_REG || to == A0L_REG || to == A0_REG ||
402       to == A1H_REG || to == ACCUM_HIGH_REGS || to == A1L_REG ||
403       to == ACCUM_LOW_REGS || to == A1_REG || to == ACCUM_REGS)
404     {
405       return 2;
406     }
407 
408   if (from == YBASE_VIRT_REGS)
409     {
410       if (to == YBASE_VIRT_REGS)
411 	return 16;
412 
413       if (to == X_REG || to == YH_REG || to == YL_REG ||
414 	  to == Y_REG || to == PL_REG || to == PH_REG ||
415 	  to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS ||
416 	  to == Y_OR_P_REGS)
417 	{
418 	  return 8;
419 	}
420       else
421 	return 10;
422     }
423 
424   if (to == YBASE_VIRT_REGS)
425     {
426       if (from == X_REG || from == YH_REG || from == YL_REG ||
427 	  from == Y_REG || from == PL_REG || from == PH_REG ||
428 	  from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS ||
429 	  from == Y_OR_P_REGS)
430 	{
431 	  return 8;
432 	}
433       else
434 	return 10;
435     }
436 
437   return 8;
438 }
439 
440 /* Given an rtx X being reloaded into a reg required to be
441    in class CLASS, return the class of reg to actually use.
442    In general this is just CLASS; but on some machines
443    in some cases it is preferable to use a more restrictive class.
444    Also, we must ensure that a PLUS is reloaded either
445    into an accumulator or an address register.  */
446 
447 enum reg_class
preferred_reload_class(x,class)448 preferred_reload_class (x, class)
449      rtx x;
450      enum reg_class class;
451 {
452   /* The ybase registers cannot have constants copied directly
453      to them.  */
454 
455   if (CONSTANT_P (x))
456     {
457       switch ((int) class)
458 	{
459 	case YBASE_VIRT_REGS:
460 	  return (!reload_in_progress ? NO_REGS : class);
461 
462 	case ACCUM_LOW_OR_YBASE_REGS:
463 	  return ACCUM_LOW_REGS;
464 
465 	case ACCUM_OR_YBASE_REGS:
466 	  return ACCUM_REGS;
467 
468 	case X_OR_YBASE_REGS:
469 	  return X_REG;
470 
471 	case Y_OR_YBASE_REGS:
472 	  return Y_REG;
473 
474 	case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
475 	  return YL_OR_PL_OR_ACCUM_LOW_REGS;
476 
477 	case P_OR_YBASE_REGS:
478 	  return P_REG;
479 
480 	case ACCUM_Y_P_OR_YBASE_REGS:
481 	  return ACCUM_Y_OR_P_REGS;
482 
483 	case Y_ADDR_OR_YBASE_REGS:
484 	  return Y_ADDR_REGS;
485 
486 	case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
487 	  return NON_HIGH_YBASE_ELIGIBLE_REGS;;
488 
489 	case YBASE_OR_YBASE_ELIGIBLE_REGS:
490 	  return YBASE_ELIGIBLE_REGS;
491 
492 	case NO_HIGH_ALL_REGS:
493 	  return NOHIGH_NON_YBASE_REGS;
494 
495 	case ALL_REGS:
496 	  return NON_YBASE_REGS;
497 
498 	default:
499 	  return class;
500 	}
501     }
502 
503   /* If x is not an accumulator or a ybase register, restrict the class of registers
504      we can copy the register into.  */
505 
506   if (REG_P (x) && !IS_ACCUM_REG (REGNO (x)) && !IS_YBASE_REGISTER_WINDOW (REGNO (x)))
507     {
508       switch ((int) class)
509 	{
510 	case NO_REGS:
511 	case A0H_REG: case A0L_REG: case A0_REG: case A1H_REG:
512 	case ACCUM_HIGH_REGS: case A1L_REG: case ACCUM_LOW_REGS:
513 	case A1_REG: case ACCUM_REGS:
514 	  return class;
515 
516 	case X_REG:
517 	  return (!reload_in_progress ? NO_REGS : class);
518 
519 	case X_OR_ACCUM_LOW_REGS:
520 	  return ACCUM_LOW_REGS;
521 
522 	case X_OR_ACCUM_REGS:
523 	  return ACCUM_REGS;
524 
525 	case YH_REG:
526 	  return (!reload_in_progress ? NO_REGS : class);
527 
528 	case YH_OR_ACCUM_HIGH_REGS:
529 	  return ACCUM_HIGH_REGS;
530 
531 	case X_OR_YH_REGS:
532 	case YL_REG:
533 	  return (!reload_in_progress ? NO_REGS : class);
534 
535 	case YL_OR_ACCUM_LOW_REGS:
536 	  return ACCUM_LOW_REGS;
537 
538 	case X_OR_YL_REGS:
539 	case X_OR_Y_REGS: case Y_REG:
540 	  return (!reload_in_progress ? NO_REGS : class);
541 
542 	case ACCUM_OR_Y_REGS:
543 	  return ACCUM_REGS;
544 
545 	case PH_REG:
546 	case X_OR_PH_REGS: case PL_REG:
547 	  return (!reload_in_progress ? NO_REGS : class);
548 
549 	case PL_OR_ACCUM_LOW_REGS:
550  	  return ACCUM_LOW_REGS;
551 
552 	case X_OR_PL_REGS:
553 	  return (!reload_in_progress ? NO_REGS : class);
554 
555 	case YL_OR_PL_OR_ACCUM_LOW_REGS:
556  	  return ACCUM_LOW_REGS;
557 
558 	case P_REG:
559 	  return (!reload_in_progress ? NO_REGS : class);
560 
561 	case ACCUM_OR_P_REGS:
562 	  return ACCUM_REGS;
563 
564 	case YL_OR_P_REGS:
565 	  return (!reload_in_progress ? NO_REGS : class);
566 
567 	case ACCUM_LOW_OR_YL_OR_P_REGS:
568  	  return ACCUM_LOW_REGS;
569 
570 	case Y_OR_P_REGS:
571 	  return (!reload_in_progress ? NO_REGS : class);
572 
573 	case ACCUM_Y_OR_P_REGS:
574 	  return ACCUM_REGS;
575 
576 	case NO_FRAME_Y_ADDR_REGS:
577 	case Y_ADDR_REGS:
578 	  return (!reload_in_progress ? NO_REGS : class);
579 
580 	case ACCUM_LOW_OR_Y_ADDR_REGS:
581  	  return ACCUM_LOW_REGS;
582 
583 	case ACCUM_OR_Y_ADDR_REGS:
584 	  return ACCUM_REGS;
585 
586 	case X_OR_Y_ADDR_REGS:
587 	case Y_OR_Y_ADDR_REGS:
588 	case P_OR_Y_ADDR_REGS:
589 	  return (!reload_in_progress ? NO_REGS : class);
590 
591 	case NON_HIGH_YBASE_ELIGIBLE_REGS:
592  	  return ACCUM_LOW_REGS;
593 
594 	case YBASE_ELIGIBLE_REGS:
595 	  return ACCUM_REGS;
596 
597 	case J_REG:
598 	case J_OR_DAU_16_BIT_REGS:
599 	case BMU_REGS:
600 	  return (!reload_in_progress ? NO_REGS : class);
601 
602 	case YBASE_VIRT_REGS:
603 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
604 	    return class;
605 	  else
606 	    return (!reload_in_progress ? NO_REGS : class);
607 
608 	case ACCUM_LOW_OR_YBASE_REGS:
609 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
610 	    return class;
611 	  else
612 	    return ACCUM_LOW_REGS;
613 
614 	case ACCUM_OR_YBASE_REGS:
615 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
616 	    return class;
617 	  else
618 	    return ACCUM_REGS;
619 
620 	case X_OR_YBASE_REGS:
621 	case Y_OR_YBASE_REGS:
622 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
623 	    return YBASE_VIRT_REGS;
624 	  else
625 	    return (!reload_in_progress ? NO_REGS : class);
626 
627 	case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
628 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
629 	    return ACCUM_LOW_OR_YBASE_REGS;
630 	  else
631 	    return ACCUM_LOW_REGS;
632 
633 	case P_OR_YBASE_REGS:
634 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
635 	    return YBASE_VIRT_REGS;
636 	  else
637 	    return (!reload_in_progress ? NO_REGS : class);
638 
639 	case ACCUM_Y_P_OR_YBASE_REGS:
640 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
641 	    return ACCUM_OR_YBASE_REGS;
642 	  else
643 	    return ACCUM_REGS;
644 
645 	case Y_ADDR_OR_YBASE_REGS:
646 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
647 	    return YBASE_VIRT_REGS;
648 	  else
649 	    return (!reload_in_progress ? NO_REGS : class);
650 
651 	case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
652 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
653 	    return ACCUM_LOW_OR_YBASE_REGS;
654 	  else
655 	    return ACCUM_LOW_REGS;
656 
657 	case YBASE_OR_YBASE_ELIGIBLE_REGS:
658 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
659 	    return ACCUM_OR_YBASE_REGS;
660 	  else
661 	    return ACCUM_REGS;
662 
663 	case NO_HIGH_ALL_REGS:
664 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
665 	    return ACCUM_LOW_OR_YBASE_REGS;
666 	  else
667 	    return ACCUM_LOW_REGS;
668 
669 	case ALL_REGS:
670 	  if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
671 	    return ACCUM_OR_YBASE_REGS;
672 	  else
673 	    return ACCUM_REGS;
674 
675 	case NOHIGH_NON_ADDR_REGS:
676 	    return ACCUM_LOW_REGS;
677 
678 	case NON_ADDR_REGS:
679 	case SLOW_MEM_LOAD_REGS:
680 	    return ACCUM_REGS;
681 
682 	case NOHIGH_NON_YBASE_REGS:
683 	    return ACCUM_LOW_REGS;
684 
685 	case NO_ACCUM_NON_YBASE_REGS:
686 	  return (!reload_in_progress ? NO_REGS : class);
687 
688 	case NON_YBASE_REGS:
689 	    return ACCUM_REGS;
690 
691 	default:
692 	  return class;
693 	}
694     }
695 
696   /* If x (the input) is a ybase register, restrict the class of registers
697      we can copy the register into.  */
698 
699   if (REG_P (x) && !TARGET_RESERVE_YBASE
700       && IS_YBASE_REGISTER_WINDOW (REGNO(x)))
701     {
702       switch ((int) class)
703 	{
704 	case NO_REGS:
705 	case A0H_REG: case A0L_REG: case A0_REG: case A1H_REG:
706 	case ACCUM_HIGH_REGS: case A1L_REG: case ACCUM_LOW_REGS:
707 	case A1_REG: case ACCUM_REGS: case X_REG:
708 	case X_OR_ACCUM_LOW_REGS: case X_OR_ACCUM_REGS:
709 	case YH_REG: case YH_OR_ACCUM_HIGH_REGS:
710 	case X_OR_YH_REGS: case YL_REG:
711 	case YL_OR_ACCUM_LOW_REGS: case X_OR_YL_REGS:
712 	case X_OR_Y_REGS: case Y_REG:
713 	case ACCUM_OR_Y_REGS: case PH_REG:
714 	case X_OR_PH_REGS: case PL_REG:
715 	case PL_OR_ACCUM_LOW_REGS: case X_OR_PL_REGS:
716 	case YL_OR_PL_OR_ACCUM_LOW_REGS: case P_REG:
717 	case ACCUM_OR_P_REGS: case YL_OR_P_REGS:
718 	case ACCUM_LOW_OR_YL_OR_P_REGS: case Y_OR_P_REGS:
719 	case ACCUM_Y_OR_P_REGS: case NO_FRAME_Y_ADDR_REGS:
720 	case Y_ADDR_REGS: case ACCUM_LOW_OR_Y_ADDR_REGS:
721 	case ACCUM_OR_Y_ADDR_REGS: case X_OR_Y_ADDR_REGS:
722 	case Y_OR_Y_ADDR_REGS: case P_OR_Y_ADDR_REGS:
723 	case NON_HIGH_YBASE_ELIGIBLE_REGS: case YBASE_ELIGIBLE_REGS:
724 	default:
725 	  return class;
726 
727 	case J_REG:
728 	  return (!reload_in_progress ? NO_REGS : class);
729 
730 	case J_OR_DAU_16_BIT_REGS:
731 	  return ACCUM_HIGH_REGS;
732 
733 	case BMU_REGS:
734 	case YBASE_VIRT_REGS:
735 	  return (!reload_in_progress ? NO_REGS : class);
736 
737 	case ACCUM_LOW_OR_YBASE_REGS:
738 	  return ACCUM_LOW_REGS;
739 
740 	case ACCUM_OR_YBASE_REGS:
741 	  return ACCUM_REGS;
742 
743 	case X_OR_YBASE_REGS:
744 	  return X_REG;
745 
746 	case Y_OR_YBASE_REGS:
747 	  return Y_REG;
748 
749 	case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
750 	  return YL_OR_PL_OR_ACCUM_LOW_REGS;
751 
752 	case P_OR_YBASE_REGS:
753 	  return P_REG;
754 
755 	case ACCUM_Y_P_OR_YBASE_REGS:
756 	  return ACCUM_Y_OR_P_REGS;
757 
758 	case Y_ADDR_OR_YBASE_REGS:
759 	  return Y_ADDR_REGS;
760 
761 	case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
762 	  return NON_HIGH_YBASE_ELIGIBLE_REGS;
763 
764 	case YBASE_OR_YBASE_ELIGIBLE_REGS:
765 	  return YBASE_ELIGIBLE_REGS;
766 
767 	case NO_HIGH_ALL_REGS:
768 	  return NON_HIGH_YBASE_ELIGIBLE_REGS;
769 
770 	case ALL_REGS:
771 	  return YBASE_ELIGIBLE_REGS;
772 
773 	case NOHIGH_NON_ADDR_REGS:
774 	  return ACCUM_LOW_OR_YL_OR_P_REGS;
775 
776 	case NON_ADDR_REGS:
777 	  return ACCUM_Y_OR_P_REGS;
778 
779 	case SLOW_MEM_LOAD_REGS:
780 	  return ACCUM_OR_Y_ADDR_REGS;
781 
782 	case NOHIGH_NON_YBASE_REGS:
783     	  return NON_HIGH_YBASE_ELIGIBLE_REGS;
784 
785     	case NO_ACCUM_NON_YBASE_REGS:
786 	  return Y_ADDR_REGS;
787 
788     	case NON_YBASE_REGS:
789 	  return YBASE_ELIGIBLE_REGS;
790 	}
791     }
792 
793   if (GET_CODE (x) == PLUS)
794     {
795       if (GET_MODE (x) == QImode
796 	  && REG_P (XEXP (x,0))
797 	  && (XEXP (x,0) == frame_pointer_rtx
798 	      || XEXP (x,0) == stack_pointer_rtx)
799 	  && (GET_CODE (XEXP (x,1)) == CONST_INT))
800 	{
801 	  if (class == ACCUM_HIGH_REGS)
802 	    return class;
803 
804 	  /* If the accumulators are not part of the class
805 	     being reloaded into, return NO_REGS.  */
806 #if 0
807 	  if (!reg_class_subset_p (ACCUM_REGS, class))
808 	    return (!reload_in_progress ? NO_REGS : class);
809 #endif
810 	  if (reg_class_subset_p (ACCUM_HIGH_REGS, class))
811 	    return ACCUM_HIGH_REGS;
812 
813 	  /* We will use accumulator 'a1l' for reloading a
814 	     PLUS.  We can only use one accumulator because
815 	     'reload_inqi' only allows one alternative to be
816 	     used.  */
817 
818 	  else if (class == ACCUM_LOW_REGS)
819 	    return A1L_REG;
820 	  else if (class == A0L_REG)
821 	    return NO_REGS;
822 	  else
823 	    return class;
824 	}
825 
826       if (class == NON_YBASE_REGS || class == YBASE_ELIGIBLE_REGS)
827 	return Y_ADDR_REGS;
828       else
829 	return class;
830     }
831   else if (GET_CODE (x) == MEM)
832     {
833       /* We can't copy from a memory location into a
834 	 ybase register.  */
835       if (reg_class_subset_p(YBASE_VIRT_REGS, class))
836 	{
837 	  switch ((int) class)
838 	    {
839 	    case YBASE_VIRT_REGS:
840 	      return (!reload_in_progress ? NO_REGS : class);
841 
842 	    case ACCUM_LOW_OR_YBASE_REGS:
843 	      return ACCUM_LOW_REGS;
844 
845 	    case ACCUM_OR_YBASE_REGS:
846 	      return ACCUM_REGS;
847 
848 	    case X_OR_YBASE_REGS:
849 	      return X_REG;
850 
851 	    case Y_OR_YBASE_REGS:
852 	      return Y_REG;
853 
854 	    case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
855 	      return YL_OR_PL_OR_ACCUM_LOW_REGS;
856 
857 	    case P_OR_YBASE_REGS:
858 	      return P_REG;
859 
860 	    case ACCUM_Y_P_OR_YBASE_REGS:
861 	      return ACCUM_Y_OR_P_REGS;
862 
863 	    case Y_ADDR_OR_YBASE_REGS:
864 	      return Y_ADDR_REGS;
865 
866 	    case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
867 	      return NON_HIGH_YBASE_ELIGIBLE_REGS;
868 
869 	    case YBASE_OR_YBASE_ELIGIBLE_REGS:
870 	      return YBASE_ELIGIBLE_REGS;
871 
872 	    case NO_HIGH_ALL_REGS:
873 	      return NOHIGH_NON_YBASE_REGS;
874 
875 	    case ALL_REGS:
876 	      return NON_YBASE_REGS;
877 
878 	    default:
879 	      return class;
880 	    }
881 	}
882       else
883 	return class;
884     }
885   else
886     return class;
887 }
888 
889 /* Return the register class of a scratch register needed to copy IN into
890    or out of a register in CLASS in MODE.  If it can be done directly,
891    NO_REGS is returned.  */
892 
893 enum reg_class
secondary_reload_class(class,mode,in)894 secondary_reload_class (class, mode, in)
895      enum reg_class class;
896      enum machine_mode mode;
897      rtx in;
898 {
899   int regno = -1;
900 
901   if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
902     regno = true_regnum (in);
903 
904   /* If we are reloading a plus into a high accumulator register,
905      we need a scratch low accumulator, because the low half gets
906      clobbered.  */
907 
908   if (class == ACCUM_HIGH_REGS
909       || class == A1H_REG
910       || class == A0H_REG)
911     {
912       if (GET_CODE (in) == PLUS && mode == QImode)
913 	return ACCUM_LOW_REGS;
914     }
915 
916   if (class == ACCUM_HIGH_REGS
917       || class == ACCUM_LOW_REGS
918       || class == A1L_REG
919       || class == A0L_REG
920       || class == A1H_REG
921       || class == A0H_REG)
922     {
923       if (GET_CODE (in) == PLUS && mode == QImode)
924 	{
925 	  rtx addr0 = XEXP (in, 0);
926 	  rtx addr1 = XEXP (in, 1);
927 
928 	  /* If we are reloading a plus (reg:QI) (reg:QI)
929 	     we need an additional register.  */
930 	  if (REG_P (addr0) && REG_P (addr1))
931 	    return NO_REGS;
932 	}
933     }
934 
935   /* We can place anything into ACCUM_REGS and can put ACCUM_REGS
936      into anything.  */
937 
938   if ((class == ACCUM_REGS || class == ACCUM_HIGH_REGS ||
939        class == ACCUM_LOW_REGS || class == A0H_REG || class == A0L_REG ||
940        class == A1H_REG || class == A1_REG) ||
941       (regno >= REG_A0 && regno < REG_A1L + 1))
942     return NO_REGS;
943 
944   if (class == ACCUM_OR_YBASE_REGS && REG_P(in)
945       && IS_YBASE_ELIGIBLE_REG(regno))
946     {
947       return NO_REGS;
948     }
949 
950   /* We can copy the ybase registers into:
951      r0-r3, a0-a1, y, p, & x or the union of
952      any of these.  */
953 
954   if (!TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW(regno))
955     {
956       switch ((int) class)
957 	{
958 	case (int) X_REG:
959 	case (int) X_OR_ACCUM_LOW_REGS:
960 	case (int) X_OR_ACCUM_REGS:
961 	case (int) YH_REG:
962 	case (int) YH_OR_ACCUM_HIGH_REGS:
963 	case (int) X_OR_YH_REGS:
964 	case (int) YL_REG:
965 	case (int) YL_OR_ACCUM_LOW_REGS:
966 	case (int) X_OR_Y_REGS:
967 	case (int) X_OR_YL_REGS:
968 	case (int) Y_REG:
969 	case (int) ACCUM_OR_Y_REGS:
970 	case (int) PH_REG:
971 	case (int) X_OR_PH_REGS:
972 	case (int) PL_REG:
973 	case (int) PL_OR_ACCUM_LOW_REGS:
974 	case (int) X_OR_PL_REGS:
975 	case (int) YL_OR_PL_OR_ACCUM_LOW_REGS:
976 	case (int) P_REG:
977 	case (int) ACCUM_OR_P_REGS:
978 	case (int) YL_OR_P_REGS:
979 	case (int) ACCUM_LOW_OR_YL_OR_P_REGS:
980 	case (int) Y_OR_P_REGS:
981 	case (int) ACCUM_Y_OR_P_REGS:
982 	case (int) Y_ADDR_REGS:
983 	case (int) ACCUM_LOW_OR_Y_ADDR_REGS:
984 	case (int) ACCUM_OR_Y_ADDR_REGS:
985 	case (int) X_OR_Y_ADDR_REGS:
986 	case (int) Y_OR_Y_ADDR_REGS:
987 	case (int) P_OR_Y_ADDR_REGS:
988 	case (int) YBASE_ELIGIBLE_REGS:
989 	  return NO_REGS;
990 
991 	default:
992 	  return ACCUM_HIGH_REGS;
993 	}
994     }
995 
996   /* We can copy r0-r3, a0-a1, y, & p
997      directly to the ybase registers. In addition
998      we can use any of the ybase virtual registers
999      as the secondary reload registers when copying
1000      between any of these registers.  */
1001 
1002   if (!TARGET_RESERVE_YBASE && regno != -1)
1003     {
1004       switch (regno)
1005 	{
1006 	case REG_A0:
1007 	case REG_A0L:
1008 	case REG_A1:
1009 	case REG_A1L:
1010 	case REG_X:
1011 	case REG_Y:
1012 	case REG_YL:
1013 	case REG_PROD:
1014 	case REG_PRODL:
1015 	case REG_R0:
1016 	case REG_R1:
1017 	case REG_R2:
1018 	case REG_R3:
1019 	  if (class == YBASE_VIRT_REGS)
1020 	    return NO_REGS;
1021 	  else
1022 	    {
1023 	      switch ((int) class)
1024 		{
1025 		case (int) X_REG:
1026 		case (int) X_OR_ACCUM_LOW_REGS:
1027 		case (int) X_OR_ACCUM_REGS:
1028 		case (int) YH_REG:
1029 		case (int) YH_OR_ACCUM_HIGH_REGS:
1030 		case (int) X_OR_YH_REGS:
1031 		case (int) YL_REG:
1032 		case (int) YL_OR_ACCUM_LOW_REGS:
1033 		case (int) X_OR_Y_REGS:
1034 		case (int) X_OR_YL_REGS:
1035 		case (int) Y_REG:
1036 		case (int) ACCUM_OR_Y_REGS:
1037 		case (int) PH_REG:
1038 		case (int) X_OR_PH_REGS:
1039 		case (int) PL_REG:
1040 		case (int) PL_OR_ACCUM_LOW_REGS:
1041 		case (int) X_OR_PL_REGS:
1042 		case (int) YL_OR_PL_OR_ACCUM_LOW_REGS:
1043 		case (int) P_REG:
1044 		case (int) ACCUM_OR_P_REGS:
1045 		case (int) YL_OR_P_REGS:
1046 		case (int) ACCUM_LOW_OR_YL_OR_P_REGS:
1047 		case (int) Y_OR_P_REGS:
1048 		case (int) ACCUM_Y_OR_P_REGS:
1049 		case (int) Y_ADDR_REGS:
1050 		case (int) ACCUM_LOW_OR_Y_ADDR_REGS:
1051 		case (int) ACCUM_OR_Y_ADDR_REGS:
1052 		case (int) X_OR_Y_ADDR_REGS:
1053 		case (int) Y_OR_Y_ADDR_REGS:
1054 		case (int) P_OR_Y_ADDR_REGS:
1055 		case (int) YBASE_ELIGIBLE_REGS:
1056 		  return YBASE_VIRT_REGS;
1057 
1058 		default:
1059 		  break;
1060 		}
1061 	    }
1062 	}
1063     }
1064 
1065   /* Memory or constants can be moved from or to any register
1066      except the ybase virtual registers.  */
1067   if (regno == -1 && GET_CODE(in) != PLUS)
1068     {
1069       if (class == YBASE_VIRT_REGS)
1070 	return NON_YBASE_REGS;
1071       else
1072         return NO_REGS;
1073     }
1074 
1075   if (GET_CODE (in) == PLUS && mode == QImode)
1076     {
1077       rtx addr0 = XEXP (in, 0);
1078       rtx addr1 = XEXP (in, 1);
1079 
1080       /* If we are reloading a plus (reg:QI) (reg:QI)
1081 	 we need a low accumulator, not a high one.  */
1082       if (REG_P (addr0) && REG_P (addr1))
1083 	return ACCUM_LOW_REGS;
1084     }
1085 
1086 #if 0
1087   if (REG_P(in))
1088     return ACCUM_REGS;
1089 #endif
1090 
1091   /* Otherwise, we need a high accumulator(s).  */
1092   return ACCUM_HIGH_REGS;
1093 }
1094 
1095 int
symbolic_address_operand(op,mode)1096 symbolic_address_operand (op, mode)
1097      rtx op;
1098      enum machine_mode mode ATTRIBUTE_UNUSED;
1099 {
1100   return (symbolic_address_p (op));
1101 }
1102 
1103 int
symbolic_address_p(op)1104 symbolic_address_p (op)
1105      rtx op;
1106 {
1107   switch (GET_CODE (op))
1108     {
1109     case SYMBOL_REF:
1110     case LABEL_REF:
1111       return 1;
1112 
1113     case CONST:
1114       op = XEXP (op, 0);
1115       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1116 	       || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1117 	      && GET_CODE (XEXP (op, 1)) == CONST_INT
1118               && INTVAL (XEXP (op,1)) < 0x20);
1119 
1120     default:
1121       return 0;
1122     }
1123 }
1124 
1125 /* For a Y address space operand we allow only *rn, *rn++, *rn--.
1126    This routine only recognizes *rn, the '<>' constraints recognize
1127    (*rn++), and (*rn--).  */
1128 
1129 int
Y_address_operand(op,mode)1130 Y_address_operand (op, mode)
1131      rtx op;
1132      enum machine_mode mode;
1133 {
1134   return (memory_address_p (mode, op) && !symbolic_address_p (op));
1135 }
1136 
1137 int
sp_operand(op,mode)1138 sp_operand (op, mode)
1139      rtx op;
1140      enum machine_mode mode ATTRIBUTE_UNUSED;
1141 {
1142     return (GET_CODE (op) == PLUS
1143 	    && (XEXP (op, 0) == stack_pointer_rtx
1144 		|| XEXP (op, 0) == frame_pointer_rtx)
1145 	    && GET_CODE (XEXP (op,1)) == CONST_INT);
1146 }
1147 
1148 int
sp_operand2(op,mode)1149 sp_operand2 (op, mode)
1150      rtx op;
1151      enum machine_mode mode ATTRIBUTE_UNUSED;
1152 {
1153   if ((GET_CODE (op) == PLUS
1154        && (XEXP (op, 0) == stack_pointer_rtx
1155 	   || XEXP (op, 0) == frame_pointer_rtx)
1156        && (REG_P (XEXP (op,1))
1157 	   && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1))))))
1158     return 1;
1159   else if ((GET_CODE (op) == PLUS
1160        && (XEXP (op, 1) == stack_pointer_rtx
1161 	   || XEXP (op, 1) == frame_pointer_rtx)
1162        && (REG_P (XEXP (op,0))
1163 	   && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1))))))
1164     return 1;
1165   else
1166     return 0;
1167 }
1168 
1169 int
nonmemory_arith_operand(op,mode)1170 nonmemory_arith_operand (op, mode)
1171      rtx op;
1172      enum machine_mode mode;
1173 {
1174   return (immediate_operand (op, mode) || arith_reg_operand (op, mode));
1175 }
1176 
1177 int
arith_reg_operand(op,mode)1178 arith_reg_operand (op, mode)
1179      rtx op;
1180      enum machine_mode mode;
1181 {
1182   return (register_operand (op, mode)
1183 	  && (GET_CODE (op) != REG
1184 	      || REGNO (op) >= FIRST_PSEUDO_REGISTER
1185 	      || (!(IS_YBASE_REGISTER_WINDOW (REGNO (op)))
1186 		  && REGNO (op) != FRAME_POINTER_REGNUM)));
1187 }
1188 
1189 int
call_address_operand(op,mode)1190 call_address_operand (op, mode)
1191      rtx op;
1192      enum machine_mode mode ATTRIBUTE_UNUSED;
1193 {
1194     if (symbolic_address_p (op) || REG_P(op))
1195     {
1196 	return 1;
1197     }
1198 
1199     return 0;
1200 }
1201 
1202 int
dsp16xx_comparison_operator(op,mode)1203 dsp16xx_comparison_operator (op, mode)
1204     register rtx op;
1205     enum machine_mode mode;
1206 {
1207   return ((mode == VOIDmode || GET_MODE (op) == mode)
1208 	  && GET_RTX_CLASS (GET_CODE (op)) == '<'
1209 	  && (GET_CODE(op) != GE && GET_CODE (op) != LT &&
1210 	      GET_CODE (op) != GEU && GET_CODE (op) != LTU));
1211 }
1212 
1213 void
notice_update_cc(exp)1214 notice_update_cc(exp)
1215      rtx exp;
1216 {
1217     if (GET_CODE (exp) == SET)
1218     {
1219 	/* Jumps do not alter the cc's.  */
1220 
1221 	if (SET_DEST (exp) == pc_rtx)
1222 	    return;
1223 
1224 	/* Moving register or memory into a register:
1225 	   it doesn't alter the cc's, but it might invalidate
1226 	   the RTX's which we remember the cc's came from.
1227 	   (Note that moving a constant 0 or 1 MAY set the cc's).  */
1228 	if (REG_P (SET_DEST (exp))
1229 	    && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
1230 	{
1231 	    if (cc_status.value1
1232 		&& reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1233 		cc_status.value1 = 0;
1234 	    if (cc_status.value2
1235 		&& reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1236 		cc_status.value2 = 0;
1237 	    return;
1238 	}
1239 	/* Moving register into memory doesn't alter the cc's.
1240 	   It may invalidate the RTX's which we remember the cc's came from.  */
1241 	if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
1242 	{
1243 	    if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
1244 		cc_status.value1 = 0;
1245 	    if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
1246 		cc_status.value2 = 0;
1247 	    return;
1248 	}
1249 	/* Function calls clobber the cc's.  */
1250 	else if (GET_CODE (SET_SRC (exp)) == CALL)
1251 	{
1252 	    CC_STATUS_INIT;
1253 	    return;
1254 	}
1255 	/* Tests and compares set the cc's in predictable ways.  */
1256 	else if (SET_DEST (exp) == cc0_rtx)
1257 	{
1258 	    CC_STATUS_INIT;
1259 	    cc_status.value1 = SET_SRC (exp);
1260 	    return;
1261 	}
1262 	/* Certain instructions effect the condition codes.  */
1263 	else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT)
1264 	    switch (GET_CODE (SET_SRC (exp)))
1265 	    {
1266 	    case PLUS:
1267 	    case MINUS:
1268 	      if (REG_P (SET_DEST (exp)))
1269 		{
1270 		  /* Address registers don't set the condition codes.  */
1271 		  if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp))))
1272 		    {
1273 		      CC_STATUS_INIT;
1274 		      break;
1275 		    }
1276 		}
1277 	    case ASHIFTRT:
1278 	    case LSHIFTRT:
1279 	    case ASHIFT:
1280 	    case AND:
1281 	    case IOR:
1282 	    case XOR:
1283 	    case MULT:
1284 	    case NEG:
1285 	    case NOT:
1286 	      cc_status.value1 = SET_SRC (exp);
1287 	      cc_status.value2 = SET_DEST (exp);
1288 	      break;
1289 
1290 	    default:
1291 	      CC_STATUS_INIT;
1292 	    }
1293 	else
1294 	{
1295 	    CC_STATUS_INIT;
1296 	}
1297     }
1298     else if (GET_CODE (exp) == PARALLEL
1299 	     && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1300     {
1301 	if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
1302 	    return;
1303 
1304 	if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
1305 	{
1306 	    CC_STATUS_INIT;
1307 	    cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
1308 	    return;
1309 	}
1310 
1311 	CC_STATUS_INIT;
1312     }
1313     else
1314     {
1315 	CC_STATUS_INIT;
1316     }
1317 }
1318 
1319 int
dsp16xx_makes_calls()1320 dsp16xx_makes_calls ()
1321 {
1322   rtx insn;
1323 
1324   for (insn = get_insns (); insn; insn = next_insn (insn))
1325     if (GET_CODE (insn) == CALL_INSN)
1326       return (1);
1327 
1328   return 0;
1329 }
1330 
1331 long
compute_frame_size(size)1332 compute_frame_size (size)
1333      int size;
1334 {
1335   long total_size;
1336   long var_size;
1337   long args_size;
1338   long extra_size;
1339   long reg_size;
1340 
1341   /* This value is needed to compute reg_size.  */
1342   current_frame_info.function_makes_calls = !leaf_function_p ();
1343 
1344   reg_size = 0;
1345   extra_size = 0;
1346   var_size = size;
1347   args_size = current_function_outgoing_args_size;
1348   reg_size = reg_save_size ();
1349 
1350   total_size = var_size + args_size + extra_size + reg_size;
1351 
1352 
1353   /* Save other computed information.  */
1354   current_frame_info.total_size  = total_size;
1355   current_frame_info.var_size    = var_size;
1356   current_frame_info.args_size   = args_size;
1357   current_frame_info.extra_size  = extra_size;
1358   current_frame_info.reg_size    = reg_size;
1359   current_frame_info.initialized = reload_completed;
1360   current_frame_info.reg_size	 = reg_size / UNITS_PER_WORD;
1361 
1362   if (reg_size)
1363     {
1364       unsigned long offset = args_size + var_size + reg_size;
1365       current_frame_info.sp_save_offset = offset;
1366       current_frame_info.fp_save_offset = offset - total_size;
1367     }
1368 
1369   return total_size;
1370 }
1371 
1372 int
dsp16xx_call_saved_register(regno)1373 dsp16xx_call_saved_register (regno)
1374      int regno;
1375 {
1376 #if 0
1377   if (regno == REG_PR && current_frame_info.function_makes_calls)
1378     return 1;
1379 #endif
1380   return (regs_ever_live[regno] && !call_used_regs[regno] &&
1381 	  !IS_YBASE_REGISTER_WINDOW(regno));
1382 }
1383 
1384 int
ybase_regs_ever_used()1385 ybase_regs_ever_used ()
1386 {
1387   int regno;
1388   int live = 0;
1389 
1390   for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++)
1391     if (regs_ever_live[regno])
1392       {
1393 	live = 1;
1394 	break;
1395       }
1396 
1397   return live;
1398 }
1399 
1400 static void
dsp16xx_output_function_prologue(file,size)1401 dsp16xx_output_function_prologue (file, size)
1402      FILE *file;
1403      HOST_WIDE_INT size;
1404 {
1405   int regno;
1406   long total_size;
1407   fp = reg_names[FRAME_POINTER_REGNUM];
1408   sp = reg_names[STACK_POINTER_REGNUM];
1409   rr = reg_names[RETURN_ADDRESS_REGNUM];   /* return address register */
1410   a1h = reg_names[REG_A1];
1411 
1412   total_size = compute_frame_size (size);
1413 
1414   fprintf (file, "\t/* FUNCTION PROLOGUE: */\n");
1415   fprintf (file, "\t/* total=%ld, vars= %ld, regs= %d, args=%d, extra= %ld */\n",
1416 	   current_frame_info.total_size,
1417 	   current_frame_info.var_size,
1418 	   current_frame_info.reg_size,
1419 	   current_function_outgoing_args_size,
1420 	   current_frame_info.extra_size);
1421 
1422   fprintf (file, "\t/* fp save offset= %ld, sp save_offset= %ld */\n\n",
1423 	   current_frame_info.fp_save_offset,
1424 	   current_frame_info.sp_save_offset);
1425   /* Set up the 'ybase' register window.  */
1426 
1427   if (ybase_regs_ever_used())
1428     {
1429       fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]);
1430       if (TARGET_YBASE_HIGH)
1431 	fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
1432       else
1433 	fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h);
1434       fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
1435     }
1436 
1437   if (current_frame_info.var_size)
1438     {
1439       if (current_frame_info.var_size == 1)
1440 	fprintf (file, "\t*%s++\n", sp);
1441       else
1442         {
1443 	  if (SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0))
1444 	    fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.var_size, sp, reg_names[REG_J]);
1445 	  else
1446 	    fatal_error ("stack size > 32k");
1447 	}
1448     }
1449 
1450   /* Save any registers this function uses, unless they are
1451      used in a call, in which case we don't need to.  */
1452 
1453   for(regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno)
1454     if (dsp16xx_call_saved_register (regno))
1455       {
1456 	fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[regno]);
1457       }
1458 
1459   /* For debugging purposes, we want the return address to be at a predictable
1460      location.  */
1461   if (current_frame_info.function_makes_calls)
1462     fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[RETURN_ADDRESS_REGNUM]);
1463 
1464   if (current_frame_info.args_size)
1465     {
1466       if (current_frame_info.args_size == 1)
1467 	fprintf (file, "\t*%s++\n", sp);
1468       else
1469 	error ("stack size > 32k");
1470     }
1471 
1472   if (frame_pointer_needed)
1473     {
1474       fprintf (file, "\t%s=%s\n", a1h, sp);
1475       fprintf (file, "\t%s=%s\n", fp, a1h);  /* Establish new base frame */
1476       fprintf (file, "\t%s=%ld\n", reg_names[REG_J], -total_size);
1477       fprintf (file, "\t*%s++%s\n", fp, reg_names[REG_J]);
1478     }
1479 
1480   fprintf (file, "\t/* END FUNCTION PROLOGUE: */\n\n");
1481 }
1482 
1483 void
init_emulation_routines()1484 init_emulation_routines ()
1485 {
1486  dsp16xx_addhf3_libcall = (rtx) 0;
1487  dsp16xx_subhf3_libcall = (rtx) 0;
1488  dsp16xx_mulhf3_libcall = (rtx) 0;
1489  dsp16xx_divhf3_libcall = (rtx) 0;
1490  dsp16xx_cmphf3_libcall = (rtx) 0;
1491  dsp16xx_fixhfhi2_libcall = (rtx) 0;
1492  dsp16xx_floathihf2_libcall = (rtx) 0;
1493  dsp16xx_neghf2_libcall = (rtx) 0;
1494 
1495  dsp16xx_mulhi3_libcall = (rtx) 0;
1496  dsp16xx_udivqi3_libcall = (rtx) 0;
1497  dsp16xx_udivhi3_libcall = (rtx) 0;
1498  dsp16xx_divqi3_libcall = (rtx) 0;
1499  dsp16xx_divhi3_libcall = (rtx) 0;
1500  dsp16xx_modqi3_libcall = (rtx) 0;
1501  dsp16xx_modhi3_libcall = (rtx) 0;
1502  dsp16xx_umodqi3_libcall = (rtx) 0;
1503  dsp16xx_umodhi3_libcall = (rtx) 0;
1504  dsp16xx_ashrhi3_libcall = (rtx) 0;
1505  dsp16xx_ashlhi3_libcall = (rtx) 0;
1506  dsp16xx_ucmphi2_libcall = (rtx) 0;
1507  dsp16xx_lshrhi3_libcall = (rtx) 0;
1508 
1509 }
1510 static void
dsp16xx_output_function_epilogue(file,size)1511 dsp16xx_output_function_epilogue (file, size)
1512      FILE *file;
1513      HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1514 {
1515   int regno;
1516 
1517   fp = reg_names[FRAME_POINTER_REGNUM];
1518   sp = reg_names[STACK_POINTER_REGNUM];
1519   rr = reg_names[RETURN_ADDRESS_REGNUM];   /* return address register */
1520   a1h = reg_names[REG_A1];
1521 
1522   fprintf (file, "\n\t/* FUNCTION EPILOGUE: */\n");
1523 
1524   if (current_frame_info.args_size)
1525     {
1526       if (current_frame_info.args_size == 1)
1527 	fprintf (file, "\t*%s--\n", sp);
1528       else
1529 	{
1530 	  fprintf (file, "\t%s=%ld\n\t*%s++%s\n",
1531 		   reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]);
1532 	}
1533     }
1534 
1535   if (ybase_regs_ever_used())
1536     {
1537       fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]);
1538       if (TARGET_YBASE_HIGH)
1539 	fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h);
1540       else
1541 	fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
1542       fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
1543     }
1544 
1545   if (current_frame_info.function_makes_calls)
1546     fprintf (file, "\t%s=pop(*%s)\n", reg_names[RETURN_ADDRESS_REGNUM], sp);
1547 
1548   for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1549     if (dsp16xx_call_saved_register(regno))
1550       {
1551 	fprintf (file, "\t%s=pop(*%s)\n", reg_names[regno], sp);
1552       }
1553 
1554   if (current_frame_info.var_size)
1555     {
1556       if (current_frame_info.var_size == 1)
1557 	fprintf (file, "\t*%s--\n", sp);
1558       else
1559 	{
1560 	  fprintf (file, "\t%s=%ld\n\t*%s++%s\n",
1561 		   reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]);
1562 	}
1563     }
1564 
1565   fprintf (file, "\treturn\n");
1566   /* Reset the frame info for the next function.  */
1567   current_frame_info = zero_frame_info;
1568   init_emulation_routines ();
1569 }
1570 
1571 /* Emit insns to move operands[1] into operands[0].
1572 
1573    Return 1 if we have written out everything that needs to be done to
1574    do the move.  Otherwise, return 0 and the caller will emit the move
1575    normally.  */
1576 
1577 int
emit_move_sequence(operands,mode)1578 emit_move_sequence (operands, mode)
1579      rtx *operands;
1580      enum machine_mode mode;
1581 {
1582   register rtx operand0 = operands[0];
1583   register rtx operand1 = operands[1];
1584 
1585   /* We can only store registers to memory.  */
1586 
1587   if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG)
1588     operands[1] = force_reg (mode, operand1);
1589 
1590   return 0;
1591 }
1592 
1593 void
double_reg_from_memory(operands)1594 double_reg_from_memory (operands)
1595      rtx operands[];
1596 {
1597     rtx xoperands[4];
1598 
1599     if (GET_CODE(XEXP(operands[1],0)) == POST_INC)
1600     {
1601 	output_asm_insn ("%u0=%1", operands);
1602 	output_asm_insn ("%w0=%1", operands);
1603     }
1604     else if (GET_CODE(XEXP(operands[1],0)) == POST_DEC)
1605     {
1606 	xoperands[1] = XEXP (XEXP (operands[1], 0), 0);
1607 	xoperands[0] = operands[0];
1608 
1609 	/* We can't use j anymore since the compiler can allocate it.  */
1610 /*	output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */
1611 	output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands);
1612     }
1613     else if (GET_CODE(XEXP(operands[1],0)) == PLUS)
1614     {
1615       rtx addr;
1616       int offset = 0;
1617 
1618       output_asm_insn ("%u0=%1", operands);
1619 
1620 
1621       /* In order to print out the least significant word we must
1622 	 use 'offset + 1'.  */
1623       addr = XEXP (operands[1], 0);
1624       if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1625 	offset = INTVAL(XEXP(addr,0)) + 1;
1626       else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1627 	offset = INTVAL(XEXP(addr,1)) + 1;
1628 
1629       fprintf (asm_out_file, "\t%s=*(%d)\n", reg_names[REGNO(operands[0]) + 1], offset + 31);
1630     }
1631     else
1632     {
1633 	xoperands[1] = XEXP(operands[1],0);
1634 	xoperands[0] = operands[0];
1635 
1636 	output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands);
1637     }
1638 }
1639 
1640 
1641 void
double_reg_to_memory(operands)1642 double_reg_to_memory (operands)
1643      rtx operands[];
1644 {
1645     rtx xoperands[4];
1646 
1647     if (GET_CODE(XEXP(operands[0],0)) == POST_INC)
1648     {
1649 	output_asm_insn ("%0=%u1", operands);
1650 	output_asm_insn ("%0=%w1", operands);
1651     }
1652     else if (GET_CODE(XEXP(operands[0],0)) == POST_DEC)
1653     {
1654 	xoperands[0] = XEXP (XEXP (operands[0], 0), 0);
1655 	xoperands[1] = operands[1];
1656 
1657 	/* We can't use j anymore since the compiler can allocate it.  */
1658 
1659 /*	output_asm_insn ("j=-3\n\t*%0++=%u1\n\t*%0++j=%w1", xoperands); */
1660 	output_asm_insn ("*%0++=%u1\n\t*%0--=%w1\n\t*%0--\n\t*%0--", xoperands);
1661 
1662     }
1663     else if (GET_CODE(XEXP(operands[0],0)) == PLUS)
1664     {
1665       rtx addr;
1666       int offset = 0;
1667 
1668       output_asm_insn ("%0=%u1", operands);
1669 
1670       /* In order to print out the least significant word we must
1671 	 use 'offset + 1'.  */
1672       addr = XEXP (operands[0], 0);
1673       if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1674 	offset = INTVAL(XEXP(addr,0)) + 1;
1675       else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1676 	offset = INTVAL(XEXP(addr,1)) + 1;
1677       else
1678 	fatal_error ("invalid addressing mode");
1679 
1680       fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]);
1681     }
1682     else
1683     {
1684 	xoperands[0] = XEXP(operands[0],0);
1685 	xoperands[1] = operands[1];
1686 
1687 	output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands);
1688     }
1689 }
1690 
1691 void
override_options()1692 override_options ()
1693 {
1694   if (chip_name == (char *) 0)
1695     chip_name = DEFAULT_CHIP_NAME;
1696 
1697   if (text_seg_name == (char *) 0)
1698     text_seg_name = DEFAULT_TEXT_SEG_NAME;
1699 
1700   if (data_seg_name == (char *) 0)
1701     data_seg_name = DEFAULT_DATA_SEG_NAME;
1702 
1703   if (bss_seg_name == (char *) 0)
1704     bss_seg_name = DEFAULT_BSS_SEG_NAME;
1705 
1706   if (const_seg_name == (char *) 0)
1707     const_seg_name = DEFAULT_CONST_SEG_NAME;
1708 
1709   save_chip_name = xstrdup (chip_name);
1710 
1711   rsect_text = concat (".rsect \"", text_seg_name, "\"", NULL);
1712   rsect_data = concat (".rsect \"", data_seg_name, "\"", NULL);
1713   rsect_bss = concat (".rsect \"", bss_seg_name, "\"", NULL);
1714   rsect_const = concat (".rsect \"", const_seg_name, "\"", NULL);
1715 }
1716 
1717 int
next_cc_user_unsigned(insn)1718 next_cc_user_unsigned (insn)
1719      rtx insn;
1720 {
1721   switch (next_cc_user_code (insn))
1722     {
1723     case GTU:
1724     case GEU:
1725     case LTU:
1726     case LEU:
1727       return 1;
1728     default:
1729       return 0;
1730     }
1731 }
1732 
1733 enum rtx_code
next_cc_user_code(insn)1734 next_cc_user_code (insn)
1735      rtx insn;
1736 {
1737   /* If no insn could be found we assume that the jump has been
1738      deleted and the compare will be deleted later.  */
1739 
1740   if (!(insn = next_cc0_user (insn)))
1741     return (enum rtx_code) 0;
1742   else if (GET_CODE (insn) == JUMP_INSN
1743 	   && GET_CODE (PATTERN (insn)) == SET
1744 	   && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
1745     return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0));
1746   else if (GET_CODE (insn) == INSN
1747 	   && GET_CODE (PATTERN (insn)) == SET
1748 	   && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode))
1749     return GET_CODE (SET_SRC (PATTERN (insn)));
1750   else
1751     abort ();
1752 }
1753 
1754 void
print_operand(file,op,letter)1755 print_operand(file, op, letter)
1756      FILE *file;
1757      rtx op;
1758      int letter;
1759 {
1760     enum rtx_code code;
1761 
1762     code = GET_CODE(op);
1763 
1764     switch (letter)
1765     {
1766        case 'I':
1767 	  code = reverse_condition (code);
1768 	  /* Fallthrough */
1769 
1770        case 'C':
1771           if (code == EQ)
1772           {
1773 	      fputs ("eq", file);
1774 	      return;
1775 	  }
1776           else if (code == NE)
1777 	  {
1778 	      fputs ("ne", file);
1779 	      return;
1780 	  }
1781           else if (code == GT || code == GTU)
1782 	  {
1783 	      fputs ("gt", file);
1784 	      return;
1785 	  }
1786           else if (code == LT || code == LTU)
1787 	  {
1788 	      fputs ("mi", file);
1789 	      return;
1790 	  }
1791           else if (code == GE || code == GEU)
1792 	  {
1793 	      fputs ("pl", file);
1794 	      return;
1795 	  }
1796           else if (code == LE || code == LEU)
1797 	  {
1798 	      fputs ("le", file);
1799 	      return;
1800 	  }
1801           else
1802 	      abort ();
1803 	  break;
1804 
1805        default:
1806           break;
1807     }
1808 
1809     if (code == REG)
1810     {
1811 	/* Print the low half of a 32-bit register pair.  */
1812         if (letter == 'w')
1813            fprintf (file, "%s", reg_names[REGNO (op) + 1]);
1814         else if (letter == 'u' || !letter)
1815            fprintf (file, "%s", reg_names[REGNO (op)]);
1816 	else if (letter == 'b')
1817 	    fprintf (file, "%sh", reg_names[REGNO (op)]);
1818 	else if (letter == 'm')
1819 	  fprintf (file, "%s", himode_reg_name[REGNO (op)]);
1820         else
1821 	  output_operand_lossage ("bad register extension code");
1822     }
1823     else if (code == MEM)
1824       output_address (XEXP(op,0));
1825     else if (code == CONST_INT)
1826       {
1827 	HOST_WIDE_INT val = INTVAL (op);
1828 
1829         if (letter == 'H')
1830 	  fprintf (file, HOST_WIDE_INT_PRINT_HEX, val & 0xffff);
1831 	else if (letter == 'h')
1832 	  fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1833         else if (letter == 'U')
1834 	  fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
1835         else
1836            output_addr_const(file, op);
1837       }
1838     else if (code == CONST_DOUBLE && GET_MODE(op) != DImode)
1839       {
1840 	long l;
1841 	REAL_VALUE_TYPE r;
1842 	REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1843 	REAL_VALUE_TO_TARGET_SINGLE (r, l);
1844 	fprintf (file, "0x%lx", l);
1845       }
1846     else if (code == CONST)
1847       {
1848 	rtx addr = XEXP (op, 0);
1849 
1850 	if (GET_CODE (addr) != PLUS)
1851 	  {
1852 	    output_addr_const(file, op);
1853 	    return;
1854 	  }
1855 
1856 	if ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
1857 	     || GET_CODE (XEXP (addr, 0)) == LABEL_REF)
1858 	    && (GET_CODE (XEXP (addr, 1)) == CONST_INT))
1859 	  {
1860 	    int n = INTVAL (XEXP(addr, 1));
1861 	    output_addr_const (file, XEXP (addr, 0));
1862 
1863 	    if (n >= 0)
1864 	      fprintf (file, "+");
1865 
1866 	    n = (int) (short) n;
1867 	    fprintf (file, "%d", n);
1868 	  }
1869 	else if ((GET_CODE (XEXP (addr, 1)) == SYMBOL_REF
1870 		  || GET_CODE (XEXP (addr, 1)) == LABEL_REF)
1871 		 && (GET_CODE (XEXP (addr, 0)) == CONST_INT))
1872 	  {
1873 	    int n = INTVAL (XEXP(addr, 0));
1874 	    output_addr_const (file, XEXP (addr, 1));
1875 
1876 	    if (n >= 0)
1877 	      fprintf (file, "+");
1878 
1879 	    n = (int) (short) n;
1880 	    fprintf (file, "%d", n);
1881 	  }
1882 	else
1883 	  output_addr_const(file, op);
1884       }
1885     else
1886       output_addr_const (file, op);
1887 }
1888 
1889 
1890 void
print_operand_address(file,addr)1891 print_operand_address(file, addr)
1892      FILE *file;
1893      rtx addr;
1894 {
1895   rtx base;
1896   int offset = 0;;
1897 
1898   switch (GET_CODE (addr))
1899     {
1900     case REG:
1901       fprintf (file, "*%s", reg_names[REGNO (addr)]);
1902       break;
1903     case POST_DEC:
1904       fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]);
1905       break;
1906     case POST_INC:
1907       fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]);
1908       break;
1909     case PLUS:
1910       if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1911 	offset = INTVAL(XEXP(addr,0)), base = XEXP(addr,1);
1912       else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1913 	offset = INTVAL(XEXP(addr,1)), base = XEXP(addr,0);
1914       else
1915 	abort();
1916       if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM)
1917 	{
1918 	  if (offset >= -31 && offset <= 0)
1919 	    offset = 31 + offset;
1920 	  else
1921 	    fatal_error ("invalid offset in ybase addressing");
1922 	}
1923       else
1924 	fatal_error ("invalid register in ybase addressing");
1925 
1926       fprintf (file, "*(%d)", offset);
1927       break;
1928 
1929     default:
1930       if (FITS_5_BITS (addr))
1931 	fprintf (file, "*(0x%x)", (INTVAL (addr) & 0x20));
1932       else
1933 	output_addr_const (file, addr);
1934     }
1935 }
1936 
1937 void
output_dsp16xx_float_const(operands)1938 output_dsp16xx_float_const (operands)
1939      rtx *operands;
1940 {
1941   rtx src = operands[1];
1942 
1943   REAL_VALUE_TYPE d;
1944   long value;
1945 
1946   REAL_VALUE_FROM_CONST_DOUBLE (d, src);
1947   REAL_VALUE_TO_TARGET_SINGLE (d, value);
1948 
1949   operands[1] = GEN_INT (value);
1950   output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands);
1951 }
1952 
1953 static int
reg_save_size()1954 reg_save_size ()
1955 {
1956   int reg_save_size = 0;
1957   int regno;
1958 
1959   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1960     if (dsp16xx_call_saved_register (regno))
1961       {
1962 	reg_save_size += UNITS_PER_WORD;
1963       }
1964 
1965   /* If the function makes calls we will save need to save the 'pr' register.  */
1966   if (current_frame_info.function_makes_calls)
1967     reg_save_size += 1;
1968 
1969   return (reg_save_size);
1970 }
1971 
1972 #if 0
1973 int
1974 dsp16xx_starting_frame_offset()
1975 {
1976   int reg_save_size = 0;
1977  int regno;
1978 
1979   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1980     if (dsp16xx_call_saved_register (regno))
1981       {
1982 	reg_save_size += UNITS_PER_WORD;
1983       }
1984 
1985   return (reg_save_size);
1986 }
1987 #endif
1988 
1989 int
initial_frame_pointer_offset()1990 initial_frame_pointer_offset()
1991 {
1992   int offset = 0;
1993 
1994   offset = compute_frame_size (get_frame_size());
1995 
1996 #ifdef STACK_GROWS_DOWNWARD
1997   return (offset);
1998 #else
1999   return (-offset);
2000 #endif
2001 }
2002 
2003 /* Generate the minimum number of 1600 core shift instructions
2004    to shift by 'shift_amount'.  */
2005 
2006 #if 0
2007 void
2008 emit_1600_core_shift (shift_op, operands, shift_amount, mode)
2009      enum rtx_code shift_op;
2010      rtx *operands;
2011      int shift_amount;
2012      enum machine_mode mode;
2013 {
2014   int quotient;
2015   int i;
2016   int first_shift_emitted = 0;
2017 
2018   while (shift_amount != 0)
2019     {
2020       if (shift_amount/16)
2021 	{
2022 	  quotient = shift_amount/16;
2023 	  shift_amount = shift_amount - (quotient * 16);
2024 	  for (i = 0; i < quotient; i++)
2025 	    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2026 				    gen_rtx (shift_op, mode,
2027 					     first_shift_emitted
2028 					     ? operands[0] : operands[1],
2029 					     GEN_INT (16))));
2030 	  first_shift_emitted = 1;
2031 	}
2032       else if (shift_amount/8)
2033 	{
2034 	  quotient = shift_amount/8;
2035 	  shift_amount = shift_amount - (quotient * 8);
2036 	  for (i = 0; i < quotient; i++)
2037 	    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2038 				    gen_rtx (shift_op, mode,
2039 					     first_shift_emitted
2040 					     ? operands[0] : operands[1],
2041 					     GEN_INT (8))));
2042 	  first_shift_emitted = 1;
2043 	}
2044       else if (shift_amount/4)
2045 	{
2046 	  quotient = shift_amount/4;
2047 	  shift_amount = shift_amount - (quotient * 4);
2048 	  for (i = 0; i < quotient; i++)
2049 	    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2050 				    gen_rtx (shift_op, mode,
2051 					     first_shift_emitted
2052 					     ? operands[0] : operands[1],
2053 					     GEN_INT (4))));
2054 	  first_shift_emitted = 1;
2055 	}
2056       else if (shift_amount/1)
2057 	{
2058 	  quotient = shift_amount/1;
2059 	  shift_amount = shift_amount - (quotient * 1);
2060 	  for (i = 0; i < quotient; i++)
2061 	    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2062 				    gen_rtx (shift_op, mode,
2063 					     first_shift_emitted
2064 					     ? operands[0] : operands[1],
2065 					     GEN_INT (1))));
2066 	  first_shift_emitted = 1;
2067 	}
2068     }
2069 }
2070 #else
2071 void
emit_1600_core_shift(shift_op,operands,shift_amount)2072 emit_1600_core_shift (shift_op, operands, shift_amount)
2073      enum rtx_code shift_op;
2074      rtx *operands;
2075      int shift_amount;
2076 {
2077   int quotient;
2078   int i;
2079   int first_shift_emitted = 0;
2080   const char * const *shift_asm_ptr;
2081   const char * const *shift_asm_ptr_first;
2082 
2083   if (shift_op == ASHIFT)
2084     {
2085       shift_asm_ptr = ashift_left_asm;
2086       shift_asm_ptr_first = ashift_left_asm_first;
2087     }
2088   else if (shift_op == ASHIFTRT)
2089     {
2090       shift_asm_ptr = ashift_right_asm;
2091       shift_asm_ptr_first = ashift_right_asm_first;
2092     }
2093   else if (shift_op == LSHIFTRT)
2094     {
2095       shift_asm_ptr = lshift_right_asm;
2096       shift_asm_ptr_first = lshift_right_asm_first;
2097     }
2098   else
2099     fatal_error ("invalid shift operator in emit_1600_core_shift");
2100 
2101   while (shift_amount != 0)
2102     {
2103       if (shift_amount/16)
2104 	{
2105 	  quotient = shift_amount/16;
2106 	  shift_amount = shift_amount - (quotient * 16);
2107 	  for (i = 0; i < quotient; i++)
2108 	    output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_16]
2109 			      : shift_asm_ptr_first[SHIFT_INDEX_16]), operands);
2110 	  first_shift_emitted = 1;
2111 	}
2112       else if (shift_amount/8)
2113 	{
2114 	  quotient = shift_amount/8;
2115 	  shift_amount = shift_amount - (quotient * 8);
2116 	  for (i = 0; i < quotient; i++)
2117 	    output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_8]
2118 			      : shift_asm_ptr_first[SHIFT_INDEX_8]), operands);
2119 	  first_shift_emitted = 1;
2120 	}
2121       else if (shift_amount/4)
2122 	{
2123 	  quotient = shift_amount/4;
2124 	  shift_amount = shift_amount - (quotient * 4);
2125 	  for (i = 0; i < quotient; i++)
2126 	    output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_4]
2127 			      : shift_asm_ptr_first[SHIFT_INDEX_4]), operands);
2128 	  first_shift_emitted = 1;
2129 	}
2130       else if (shift_amount/1)
2131 	{
2132 	  quotient = shift_amount/1;
2133 	  shift_amount = shift_amount - (quotient * 1);
2134 	  for (i = 0; i < quotient; i++)
2135 	    output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_1]
2136 			      : shift_asm_ptr_first[SHIFT_INDEX_1]), operands);
2137 	  first_shift_emitted = 1;
2138 	}
2139     }
2140 }
2141 #endif
2142 
2143 int
num_1600_core_shifts(shift_amount)2144 num_1600_core_shifts (shift_amount)
2145 int shift_amount;
2146 {
2147   int quotient;
2148   int i;
2149   int first_shift_emitted = 0;
2150   int num_shifts = 0;
2151 
2152   while (shift_amount != 0)
2153     {
2154       if (shift_amount/16)
2155 	{
2156 	  quotient = shift_amount/16;
2157 	  shift_amount = shift_amount - (quotient * 16);
2158 	  for (i = 0; i < quotient; i++)
2159 	    num_shifts++;
2160 	  first_shift_emitted = 1;
2161 	}
2162       else if (shift_amount/8)
2163 	{
2164 	  quotient = shift_amount/8;
2165 	  shift_amount = shift_amount - (quotient * 8);
2166 	  for (i = 0; i < quotient; i++)
2167 	    num_shifts++;
2168 
2169 	  first_shift_emitted = 1;
2170 	}
2171       else if (shift_amount/4)
2172 	{
2173 	  quotient = shift_amount/4;
2174 	  shift_amount = shift_amount - (quotient * 4);
2175 	  for (i = 0; i < quotient; i++)
2176 	    num_shifts++;
2177 
2178 	  first_shift_emitted = 1;
2179 	}
2180       else if (shift_amount/1)
2181 	{
2182 	  quotient = shift_amount/1;
2183 	  shift_amount = shift_amount - (quotient * 1);
2184 	  for (i = 0; i < quotient; i++)
2185 	    num_shifts++;
2186 
2187 	  first_shift_emitted = 1;
2188 	}
2189     }
2190   return num_shifts;
2191 }
2192 
2193 void
asm_output_common(file,name,size,rounded)2194 asm_output_common(file, name, size, rounded)
2195      FILE *file;
2196      const char *name;
2197      int size ATTRIBUTE_UNUSED;
2198      int rounded;
2199 {
2200     bss_section ();
2201     (*targetm.asm_out.globalize_label) (file, name);
2202     assemble_name (file, name);
2203     fputs (":", file);
2204     if (rounded > 1)
2205 	fprintf (file, "%d * int\n", rounded);
2206     else
2207 	fprintf (file, "int\n");
2208 }
2209 
2210 void
asm_output_local(file,name,size,rounded)2211 asm_output_local(file, name, size, rounded)
2212      FILE *file;
2213      const char *name;
2214      int size ATTRIBUTE_UNUSED;
2215      int rounded;
2216 {
2217     bss_section ();
2218     assemble_name (file, name);
2219     fputs (":", file);
2220     if (rounded > 1)
2221 	fprintf (file, "%d * int\n", rounded);
2222     else
2223 	fprintf (file, "int\n");
2224 }
2225 
2226 int
dsp16xx_address_cost(addr)2227 dsp16xx_address_cost (addr)
2228      rtx addr;
2229 {
2230     switch (GET_CODE (addr))
2231     {
2232 	  default:
2233 	     break;
2234 
2235 	  case REG:
2236 	     return 1;
2237 
2238 	  case CONST:
2239 	     {
2240 	        rtx offset = const0_rtx;
2241 	        addr = eliminate_constant_term (addr, &offset);
2242 
2243 	        if (GET_CODE (addr) == LABEL_REF)
2244 	            return 2;
2245 
2246 	        if (GET_CODE (addr) != SYMBOL_REF)
2247 	            return 4;
2248 
2249 	        if (INTVAL (offset) == 0)
2250 	            return 2;
2251              }
2252 	     /* fall through */
2253 
2254 	  case POST_INC: case POST_DEC:
2255 	     return (GET_MODE (addr) == QImode ? 1 : 2);
2256 
2257 	  case SYMBOL_REF: case LABEL_REF:
2258 	     return 2;
2259 
2260 	  case PLUS:
2261 	  {
2262 	     register rtx plus0 = XEXP (addr, 0);
2263 	     register rtx plus1 = XEXP (addr, 1);
2264 
2265 	     if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
2266 	     {
2267 		 plus0 = XEXP (addr, 1);
2268 		 plus1 = XEXP (addr, 0);
2269 	     }
2270 
2271 	     if (GET_CODE (plus0) != REG)
2272 		 break;
2273 
2274 	     switch (GET_CODE (plus1))
2275 	     {
2276 		   default:
2277 		      break;
2278 
2279 		   case CONST_INT:
2280 		      return 4;
2281 
2282 		   case CONST:
2283 		   case SYMBOL_REF:
2284 		   case LABEL_REF:
2285 		      return dsp16xx_address_cost (plus1) + 1;
2286 	     }
2287 	  }
2288      }
2289 
2290      return 4;
2291 }
2292 
2293 
2294 /* Determine whether a function argument is passed in a register, and
2295    which register.
2296 
2297    The arguments are CUM, which summarizes all the previous
2298    arguments; MODE, the machine mode of the argument; TYPE,
2299    the data type of the argument as a tree node or 0 if that is not known
2300    (which happens for C support library functions); and NAMED,
2301    which is 1 for an ordinary argument and 0 for nameless arguments that
2302    correspond to `...' in the called function's prototype.
2303 
2304    The value of the expression should either be a `reg' RTX for the
2305    hard register in which to pass the argument, or zero to pass the
2306    argument on the stack.
2307 
2308    On the dsp1610 the first four words of args are normally in registers
2309    and the rest are pushed. If we a long or on float mode, the argument
2310    must begin on an even register boundary
2311 
2312    Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2313    For structures that are passed in memory, but could have been
2314    passed in registers, we first load the structure into the
2315    register, and then when the last argument is passed, we store
2316    the registers into the stack locations.  This fixes some bugs
2317    where GCC did not expect to have register arguments, followed.  */
2318 
2319 struct rtx_def *
dsp16xx_function_arg(args_so_far,mode,type,named)2320 dsp16xx_function_arg (args_so_far, mode, type, named)
2321      CUMULATIVE_ARGS args_so_far;
2322      enum machine_mode mode;
2323      tree type;
2324      int named;
2325 {
2326   if (TARGET_REGPARM)
2327     {
2328       if ((args_so_far & 1) != 0
2329 	  && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
2330 	args_so_far++;
2331 
2332       if (type == void_type_node)
2333 	return (struct rtx_def *) 0;
2334 
2335       if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type))
2336 	return gen_rtx_REG (mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG);
2337       else
2338 	return (struct rtx_def *) 0;
2339     }
2340   else
2341     return (struct rtx_def *) 0;
2342 }
2343 
2344 /* Advance the argument to the next argument position.  */
2345 
2346 void
dsp16xx_function_arg_advance(cum,mode,type,named)2347 dsp16xx_function_arg_advance (cum, mode, type, named)
2348      CUMULATIVE_ARGS *cum;	/* current arg information */
2349      enum machine_mode mode;	/* current arg mode */
2350      tree type;			/* type of the argument or 0 if lib support */
2351      int named ATTRIBUTE_UNUSED;/* whether or not the argument was named */
2352 {
2353   if (TARGET_REGPARM)
2354     {
2355       if ((*cum & 1) != 0
2356 	  && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
2357 	*cum += 1;
2358 
2359       if (mode != BLKmode)
2360 	*cum += GET_MODE_SIZE (mode);
2361       else
2362 	*cum += int_size_in_bytes (type);
2363     }
2364 }
2365 
2366 void
coff_dsp16xx_file_start(file)2367 coff_dsp16xx_file_start (file)
2368      FILE *file;
2369 {
2370   fprintf (file, "#include <%s.h>\n", save_chip_name);
2371 }
2372 
2373 void
luxworks_dsp16xx_file_start(file)2374 luxworks_dsp16xx_file_start (file)
2375      FILE *file;
2376 {
2377   char *temp_filename;
2378   int len, err_code;
2379 
2380 
2381   fprintf (file, "\t.debug ");
2382   err_code = (TARGET_DEBUG) ? fprintf (file, "yes, ") : fprintf (file, "no, ");
2383   err_code = (TARGET_SAVE_TEMPS) ? fprintf (file, "asm, ") : fprintf (file, "temp, ");
2384   len = strlen (main_input_filename);
2385   temp_filename = (char *) xmalloc (len + 2);
2386   strcpy (temp_filename, main_input_filename);
2387 #ifdef __CYGWIN32__
2388     p = temp_filename;
2389     while (*p != '\0') {
2390     if (*p == '\\')
2391         *p = '/';
2392          p++;
2393          }
2394 #endif
2395     fprintf (file, "\"%s\"\n", temp_filename);
2396 
2397   fprintf (file, "#include <%s.h>\n", save_chip_name);
2398 
2399    /*
2400     * Add dummy sections, so that they always exist in the
2401     * object code. These have been created so that the number and
2402     * type of sections remain consistent with and without -g option. Note
2403     * that the .data, .text, .const and .bss are always created when -g
2404     * is provided as an option.  */
2405    fprintf (file, "\t.rsect \".text\" , nodelete\n");
2406    fprintf (file, "\t.rsect \".data\" , nodelete\n");
2407    fprintf (file, "\t.rsect \".const\" , nodelete\n");
2408    fprintf (file, "\t.rsect \".bss\" , nodelete\n");
2409 }
2410 
2411 rtx
gen_tst_reg(x)2412 gen_tst_reg (x)
2413      rtx x;
2414 {
2415   enum machine_mode mode;
2416 
2417   mode = GET_MODE (x);
2418 
2419   if (mode == QImode)
2420     emit_insn (gen_rtx_PARALLEL
2421 	       (VOIDmode,
2422 		gen_rtvec (2, gen_rtx_SET (VOIDmode, cc0_rtx, x),
2423 			   gen_rtx_CLOBBER (VOIDmode,
2424 					    gen_rtx_SCRATCH (QImode)))));
2425   else if (mode == HImode)
2426     emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x));
2427   else
2428     fatal_error ("invalid mode for gen_tst_reg");
2429 
2430   return cc0_rtx;
2431 }
2432 
2433 rtx
gen_compare_reg(code,x,y)2434 gen_compare_reg (code, x, y)
2435      enum rtx_code code;
2436      rtx x, y;
2437 {
2438   enum machine_mode mode;
2439 
2440   mode = GET_MODE (x);
2441   /* For floating point compare insns, a call is generated so don't
2442      do anything here.  */
2443 
2444   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
2445     return cc0_rtx;
2446 
2447   if (mode == QImode)
2448     {
2449       if (code == GTU || code == GEU
2450 	  || code == LTU || code == LEU)
2451 	{
2452 	  emit_insn (gen_rtx_PARALLEL
2453 		     (VOIDmode,
2454 		      gen_rtvec (3,
2455 				 gen_rtx_SET (VOIDmode, cc0_rtx,
2456 					      gen_rtx_COMPARE (mode, x, y)),
2457 				 gen_rtx_CLOBBER (VOIDmode,
2458 						  gen_rtx_SCRATCH (QImode)),
2459 				 gen_rtx_CLOBBER (VOIDmode,
2460 						  gen_rtx_SCRATCH (QImode)))));
2461 	}
2462       else
2463 	{
2464 	  emit_insn (gen_rtx_PARALLEL
2465 		     (VOIDmode,
2466 		      gen_rtvec (3, gen_rtx_SET (VOIDmode, cc0_rtx,
2467 						 gen_rtx_COMPARE (mode, x, y)),
2468 				 gen_rtx_CLOBBER (VOIDmode,
2469 						  gen_rtx_SCRATCH (QImode)),
2470 				 gen_rtx_CLOBBER (VOIDmode,
2471 						  gen_rtx_SCRATCH (QImode)))));
2472 	}
2473     }
2474   else if (mode == HImode)
2475     {
2476       if (code == GTU || code == GEU
2477 	  || code == LTU || code == LEU)
2478 	{
2479 	  emit_insn (gen_rtx_PARALLEL
2480 		     (VOIDmode,
2481 		      gen_rtvec (5,
2482 				 gen_rtx_SET (VOIDmode, cc0_rtx,
2483 					      gen_rtx_COMPARE (VOIDmode, x, y)),
2484 				 gen_rtx_CLOBBER (VOIDmode,
2485 						  gen_rtx_SCRATCH (QImode)),
2486 				 gen_rtx_CLOBBER (VOIDmode,
2487 						  gen_rtx_SCRATCH (QImode)),
2488 				 gen_rtx_CLOBBER (VOIDmode,
2489 						  gen_rtx_SCRATCH (QImode)),
2490 				 gen_rtx_CLOBBER (VOIDmode,
2491 						  gen_rtx_SCRATCH (QImode)))));
2492 	}
2493       else
2494 	emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
2495 				gen_rtx_COMPARE (VOIDmode,
2496 						 force_reg (HImode, x),
2497 						 force_reg (HImode,y))));
2498     }
2499   else
2500     fatal_error ("invalid mode for integer comparison in gen_compare_reg");
2501 
2502   return cc0_rtx;
2503 }
2504 
2505 const char *
output_block_move(operands)2506 output_block_move (operands)
2507      rtx operands[];
2508 {
2509   int loop_count = INTVAL(operands[2]);
2510   rtx xoperands[4];
2511 
2512   fprintf (asm_out_file, "\tdo %d {\n", loop_count);
2513   xoperands[0] = operands[4];
2514   xoperands[1] = operands[1];
2515   output_asm_insn ("%0=*%1++", xoperands);
2516 
2517   xoperands[0] = operands[0];
2518   xoperands[1] = operands[4];
2519   output_asm_insn ("*%0++=%1", xoperands);
2520 
2521   fprintf (asm_out_file, "\t}\n");
2522   return "";
2523 }
2524 
2525 int
uns_comparison_operator(op,mode)2526 uns_comparison_operator (op, mode)
2527      rtx op;
2528      enum machine_mode mode;
2529 {
2530   if (mode == VOIDmode || GET_MODE (op) == mode)
2531     {
2532       enum rtx_code code;
2533 
2534       code = GET_CODE(op);
2535 
2536       if (code == LEU || code == LTU || code == GEU
2537 	  || code == GTU)
2538 	{
2539 	  return 1;
2540 	}
2541       else
2542 	return 0;
2543     }
2544 
2545   return 0;
2546 }
2547 
2548 int
signed_comparison_operator(op,mode)2549 signed_comparison_operator (op, mode)
2550      rtx op;
2551      enum machine_mode mode;
2552 {
2553   if (mode == VOIDmode || GET_MODE (op) == mode)
2554     {
2555       enum rtx_code code;
2556 
2557       code = GET_CODE(op);
2558 
2559       if (!(code == LEU || code == LTU || code == GEU
2560 	  || code == GTU))
2561 	{
2562 	  return 1;
2563 	}
2564       else
2565 	return 0;
2566     }
2567 
2568   return 0;
2569 }
2570