OSDN Git Service

* i386.h (MIN_UNITS_PER_WORD): Define to 8 for x86-64 libgcc.
[pf3gnuchains/gcc-fork.git] / gcc / config / dsp16xx / dsp16xx.c
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 
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
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 
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 \f
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 *
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
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
2367 coff_dsp16xx_file_start (file)
2368      FILE *file;
2369 {
2370   fprintf (file, "#include <%s.h>\n", save_chip_name);
2371 }
2372
2373 void
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
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
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 *
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
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
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 }