OSDN Git Service

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