Makefile.in (TARGET_H, [...]): New.
[gcc.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 }