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