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