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