]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/dsp16xx/dsp16xx.c
alpha.c (TARGET_ASM_GLOBALIZE_LABEL): Define for unicosmk.
[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"
c83c42d9
RK
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"
c83c42d9
RK
31#include "output.h"
32#include "insn-attr.h"
33#include "tree.h"
34#include "expr.h"
bf6bb899 35#include "function.h"
c83c42d9 36#include "flags.h"
b979ef45 37#include "ggc.h"
69985118
KG
38#include "toplev.h"
39#include "recog.h"
55710451 40#include "tm_p.h"
672a6f42
NB
41#include "target.h"
42#include "target-def.h"
69985118
KG
43
44const char *text_seg_name;
45const char *rsect_text;
46const char *data_seg_name;
47const char *rsect_data;
48const char *bss_seg_name;
49const char *rsect_bss;
50const char *const_seg_name;
51const char *rsect_const;
52
53const char *chip_name;
54const char *save_chip_name;
c83c42d9
RK
55
56/* Save the operands of a compare. The 16xx has not lt or gt, so
6b0880cb 57 in these cases we swap the operands and reverse the condition. */
c83c42d9
RK
58
59rtx dsp16xx_compare_op0;
60rtx dsp16xx_compare_op1;
6b0880cb 61rtx (*dsp16xx_compare_gen) PARAMS (());
c83c42d9 62
69985118
KG
63static const char *fp;
64static const char *sp;
65static const char *rr;
66static const char *a1h;
c83c42d9
RK
67
68struct dsp16xx_frame_info current_frame_info;
69struct dsp16xx_frame_info zero_frame_info;
70
71rtx dsp16xx_addhf3_libcall = (rtx) 0;
72rtx dsp16xx_subhf3_libcall = (rtx) 0;
73rtx dsp16xx_mulhf3_libcall = (rtx) 0;
74rtx dsp16xx_divhf3_libcall = (rtx) 0;
75rtx dsp16xx_cmphf3_libcall = (rtx) 0;
76rtx dsp16xx_fixhfhi2_libcall = (rtx) 0;
77rtx dsp16xx_floathihf2_libcall = (rtx) 0;
78rtx dsp16xx_neghf2_libcall = (rtx) 0;
79
80rtx dsp16xx_mulhi3_libcall = (rtx) 0;
81rtx dsp16xx_udivqi3_libcall = (rtx) 0;
82rtx dsp16xx_udivhi3_libcall = (rtx) 0;
83rtx dsp16xx_divqi3_libcall = (rtx) 0;
84rtx dsp16xx_divhi3_libcall = (rtx) 0;
85rtx dsp16xx_modqi3_libcall = (rtx) 0;
86rtx dsp16xx_modhi3_libcall = (rtx) 0;
87rtx dsp16xx_umodqi3_libcall = (rtx) 0;
88rtx dsp16xx_umodhi3_libcall = (rtx) 0;
89rtx dsp16xx_ashrhi3_libcall = (rtx) 0;
90rtx dsp16xx_ashlhi3_libcall = (rtx) 0;
91rtx dsp16xx_ucmphi2_libcall = (rtx) 0;
92rtx dsp16xx_lshrhi3_libcall = (rtx) 0;
93
69985118 94static const char *const himode_reg_name[] = HIMODE_REGISTER_NAMES;
c83c42d9
RK
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
69985118 101static const char *const ashift_right_asm[] =
c83c42d9
RK
102{
103 "%0=%0>>1",
104 "%0=%0>>4",
105 "%0=%0>>8",
106 "%0=%0>>16"
107};
108
69985118 109static const char *const ashift_right_asm_first[] =
c83c42d9
RK
110{
111 "%0=%1>>1",
112 "%0=%1>>4",
113 "%0=%1>>8",
114 "%0=%1>>16"
115};
116
69985118 117static const char *const ashift_left_asm[] =
c83c42d9
RK
118{
119 "%0=%0<<1",
120 "%0=%0<<4",
121 "%0=%0<<8",
122 "%0=%0<<16"
123};
124
69985118 125static const char *const ashift_left_asm_first[] =
c83c42d9
RK
126{
127 "%0=%1<<1",
128 "%0=%1<<4",
129 "%0=%1<<8",
130 "%0=%1<<16"
131};
132
69985118 133static const char *const lshift_right_asm[] =
c83c42d9
RK
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
69985118 141static const char *const lshift_right_asm_first[] =
c83c42d9
RK
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
69985118 149static int reg_save_size PARAMS ((void));
08c148a8
NB
150static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
151static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
dff06f62 152
672a6f42 153/* Initialize the GCC target structure. */
301d03af
RS
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
08c148a8
NB
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
69985118 165
f6897b10 166struct gcc_target targetm = TARGET_INITIALIZER;
dff06f62 167
c83c42d9
RK
168int
169hard_regno_mode_ok (regno, mode)
69985118
KG
170 int regno;
171 enum machine_mode mode;
c83c42d9
RK
172{
173 switch ((int) mode)
174 {
175 case VOIDmode:
176 return 1;
177
6b0880cb
MC
178 /* We can't use the c0-c2 for QImode, since they are only
179 8 bits in length. */
c83c42d9
RK
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
6b0880cb 189 modes. */
c83c42d9
RK
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
209enum reg_class
210dsp16xx_reg_class_from_letter (c)
69985118 211 int c;
c83c42d9
RK
212{
213 switch (c)
214 {
215 case 'A':
216 return ACCUM_REGS;
dff06f62
MC
217
218 case 'l':
219 return A0_REG;
220
221 case 'C':
222 return A1_REG;
c83c42d9
RK
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
c83c42d9
RK
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:
dff06f62 291 return NO_REGS;
c83c42d9
RK
292 }
293}
6b0880cb 294
c83c42d9 295/* Return the class number of the smallest class containing
6b0880cb 296 reg number REGNO. */
c83c42d9
RK
297
298int
299regno_reg_class(regno)
69985118 300 int regno;
c83c42d9
RK
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
6b0880cb 369 needed to hold a value of mode MODE. */
c83c42d9
RK
370
371int
372class_max_nregs(class, mode)
69985118
KG
373 enum reg_class class ATTRIBUTE_UNUSED;
374 enum machine_mode mode;
c83c42d9
RK
375{
376 return (GET_MODE_SIZE(mode));
377}
378
379enum reg_class
380limit_reload_class (mode, class)
dff06f62 381 enum machine_mode mode ATTRIBUTE_UNUSED;
69985118 382 enum reg_class class;
c83c42d9 383{
dff06f62 384 return class;
c83c42d9
RK
385}
386
387int
388dsp16xx_register_move_cost (from, to)
69985118 389 enum reg_class from, to;
c83c42d9 390{
c83c42d9
RK
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
c83c42d9
RK
408 if (from == YBASE_VIRT_REGS)
409 {
dff06f62
MC
410 if (to == YBASE_VIRT_REGS)
411 return 16;
412
c83c42d9
RK
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 {
dff06f62 418 return 8;
c83c42d9
RK
419 }
420 else
dff06f62 421 return 10;
c83c42d9
RK
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 {
dff06f62 431 return 8;
c83c42d9
RK
432 }
433 else
dff06f62 434 return 10;
c83c42d9 435 }
dff06f62
MC
436
437 return 8;
c83c42d9
RK
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
447enum reg_class
448preferred_reload_class (x, class)
449 rtx x;
450 enum reg_class class;
451{
452 /* The ybase registers cannot have constants copied directly
6b0880cb 453 to them. */
c83c42d9
RK
454
455 if (CONSTANT_P (x))
456 {
dff06f62
MC
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
bf0e974b 504 we can copy the register into. */
dff06f62
MC
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 }
c83c42d9
RK
694 }
695
dff06f62 696 /* If x (the input) is a ybase register, restrict the class of registers
6b0880cb 697 we can copy the register into. */
dff06f62
MC
698
699 if (REG_P (x) && !TARGET_RESERVE_YBASE
c83c42d9 700 && IS_YBASE_REGISTER_WINDOW (REGNO(x)))
dff06f62
MC
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 }
c83c42d9
RK
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
dff06f62 804 /* If the accumulators are not part of the class
6b0880cb 805 being reloaded into, return NO_REGS. */
dff06f62
MC
806#if 0
807 if (!reg_class_subset_p (ACCUM_REGS, class))
808 return (!reload_in_progress ? NO_REGS : class);
809#endif
c83c42d9
RK
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
6b0880cb 814 PLUS. We can only use one accumulator because
c83c42d9 815 'reload_inqi' only allows one alternative to be
6b0880cb 816 used. */
c83c42d9
RK
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 {
dff06f62 833 /* We can't copy from a memory location into a
6b0880cb 834 ybase register. */
dff06f62 835 if (reg_class_subset_p(YBASE_VIRT_REGS, class))
c83c42d9 836 {
dff06f62
MC
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 }
c83c42d9
RK
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
893enum reg_class
894secondary_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
dff06f62
MC
904 /* If we are reloading a plus into a high accumulator register,
905 we need a scratch low accumulator, because the low half gets
6b0880cb 906 clobbered. */
dff06f62
MC
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
c83c42d9
RK
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)
6b0880cb 929 we need an additional register. */
c83c42d9
RK
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
dff06f62
MC
944 if (class == ACCUM_OR_YBASE_REGS && REG_P(in)
945 && IS_YBASE_ELIGIBLE_REG(regno))
946 {
947 return NO_REGS;
948 }
949
c83c42d9
RK
950 /* We can copy the ybase registers into:
951 r0-r3, a0-a1, y, p, & x or the union of
6b0880cb 952 any of these. */
c83c42d9
RK
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
6b0880cb 1000 between any of these registers. */
c83c42d9
RK
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
6b0880cb 1066 except the ybase virtual registers. */
c83c42d9
RK
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)
6b0880cb 1081 we need a low accumulator, not a high one. */
c83c42d9
RK
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
1095int
1096symbolic_address_operand (op, mode)
69985118
KG
1097 rtx op;
1098 enum machine_mode mode ATTRIBUTE_UNUSED;
c83c42d9 1099{
69985118 1100 return (symbolic_address_p (op));
c83c42d9
RK
1101}
1102
69985118
KG
1103int
1104symbolic_address_p (op)
1105 rtx op;
c83c42d9
RK
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
6b0880cb 1127 (*rn++), and (*rn--). */
c83c42d9
RK
1128
1129int
1130Y_address_operand (op, mode)
69985118
KG
1131 rtx op;
1132 enum machine_mode mode;
c83c42d9 1133{
69985118 1134 return (memory_address_p (mode, op) && !symbolic_address_p (op));
c83c42d9
RK
1135}
1136
1137int
1138sp_operand (op, mode)
69985118
KG
1139 rtx op;
1140 enum machine_mode mode ATTRIBUTE_UNUSED;
c83c42d9
RK
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
1148int
1149sp_operand2 (op, mode)
69985118
KG
1150 rtx op;
1151 enum machine_mode mode ATTRIBUTE_UNUSED;
c83c42d9
RK
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
1169int
1170nonmemory_arith_operand (op, mode)
69985118
KG
1171 rtx op;
1172 enum machine_mode mode;
c83c42d9
RK
1173{
1174 return (immediate_operand (op, mode) || arith_reg_operand (op, mode));
1175}
1176
1177int
1178arith_reg_operand (op, mode)
69985118
KG
1179 rtx op;
1180 enum machine_mode mode;
c83c42d9
RK
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
1189int
1190call_address_operand (op, mode)
69985118
KG
1191 rtx op;
1192 enum machine_mode mode ATTRIBUTE_UNUSED;
c83c42d9
RK
1193{
1194 if (symbolic_address_p (op) || REG_P(op))
1195 {
1196 return 1;
1197 }
1198
1199 return 0;
1200}
1201
1202int
1203dsp16xx_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
1213void
1214notice_update_cc(exp)
69985118 1215 rtx exp;
c83c42d9
RK
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 }
6b0880cb 1262 /* Certain instructions effect the condition codes. */
c83c42d9 1263 else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT)
6b0880cb 1264 switch (GET_CODE (SET_SRC (exp)))
c83c42d9
RK
1265 {
1266 case PLUS:
1267 case MINUS:
1268 if (REG_P (SET_DEST (exp)))
1269 {
6b0880cb 1270 /* Address registers don't set the condition codes. */
c83c42d9
RK
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:
c83c42d9
RK
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
1319int
1320dsp16xx_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
69985118
KG
1331long
1332compute_frame_size (size)
1333 int size;
c83c42d9
RK
1334{
1335 long total_size;
1336 long var_size;
1337 long args_size;
1338 long extra_size;
1339 long reg_size;
1340
6b0880cb 1341 /* This value is needed to compute reg_size. */
dff06f62
MC
1342 current_frame_info.function_makes_calls = !leaf_function_p ();
1343
c83c42d9
RK
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;
c83c42d9
RK
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
1372int
1373dsp16xx_call_saved_register (regno)
69985118 1374 int regno;
c83c42d9 1375{
dff06f62
MC
1376#if 0
1377 if (regno == REG_PR && current_frame_info.function_makes_calls)
1378 return 1;
1379#endif
c83c42d9
RK
1380 return (regs_ever_live[regno] && !call_used_regs[regno] &&
1381 !IS_YBASE_REGISTER_WINDOW(regno));
c83c42d9
RK
1382}
1383
1384int
1385ybase_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
55710451 1400static void
08c148a8 1401dsp16xx_output_function_prologue (file, size)
69985118 1402 FILE *file;
6b0880cb 1403 HOST_WIDE_INT size;
c83c42d9
RK
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
6b0880cb 1414 fprintf (file, "\t/* FUNCTION PROLOGUE: */\n");
55710451 1415 fprintf (file, "\t/* total=%ld, vars= %ld, regs= %d, args=%d, extra= %ld */\n",
c83c42d9
RK
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
55710451 1422 fprintf (file, "\t/* fp save offset= %ld, sp save_offset= %ld */\n\n",
c83c42d9
RK
1423 current_frame_info.fp_save_offset,
1424 current_frame_info.sp_save_offset);
6b0880cb 1425 /* Set up the 'ybase' register window. */
c83c42d9
RK
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
c83c42d9
RK
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
dff06f62 1442 {
6b0880cb 1443 if (SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0))
55710451 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]);
dff06f62 1445 else
c725bd79 1446 fatal_error ("stack size > 32k");
dff06f62 1447 }
c83c42d9
RK
1448 }
1449
dff06f62 1450 /* Save any registers this function uses, unless they are
6b0880cb 1451 used in a call, in which case we don't need to. */
c83c42d9 1452
6b0880cb 1453 for(regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno)
c83c42d9
RK
1454 if (dsp16xx_call_saved_register (regno))
1455 {
6b0880cb 1456 fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[regno]);
c83c42d9 1457 }
dff06f62
MC
1458
1459 /* For debugging purposes, we want the return address to be at a predictable
6b0880cb 1460 location. */
dff06f62 1461 if (current_frame_info.function_makes_calls)
6b0880cb 1462 fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[RETURN_ADDRESS_REGNUM]);
dff06f62 1463
c83c42d9
RK
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
c725bd79 1469 error ("stack size > 32k");
c83c42d9 1470 }
dff06f62 1471
c83c42d9
RK
1472 if (frame_pointer_needed)
1473 {
6b0880cb
MC
1474 fprintf (file, "\t%s=%s\n", a1h, sp);
1475 fprintf (file, "\t%s=%s\n", fp, a1h); /* Establish new base frame */
55710451 1476 fprintf (file, "\t%s=%ld\n", reg_names[REG_J], -total_size);
6b0880cb 1477 fprintf (file, "\t*%s++%s\n", fp, reg_names[REG_J]);
c83c42d9
RK
1478 }
1479
6b0880cb 1480 fprintf (file, "\t/* END FUNCTION PROLOGUE: */\n\n");
c83c42d9
RK
1481}
1482
1483void
1484init_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}
55710451 1510static void
08c148a8 1511dsp16xx_output_function_epilogue (file, size)
69985118 1512 FILE *file;
6b0880cb 1513 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
c83c42d9
RK
1514{
1515 int regno;
c83c42d9
RK
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
6b0880cb 1522 fprintf (file, "\n\t/* FUNCTION EPILOGUE: */\n");
c83c42d9
RK
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 {
55710451 1530 fprintf (file, "\t%s=%ld\n\t*%s++%s\n",
c83c42d9
RK
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 }
dff06f62
MC
1544
1545 if (current_frame_info.function_makes_calls)
6b0880cb 1546 fprintf (file, "\t%s=pop(*%s)\n", reg_names[RETURN_ADDRESS_REGNUM], sp);
c83c42d9
RK
1547
1548 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1549 if (dsp16xx_call_saved_register(regno))
1550 {
6b0880cb 1551 fprintf (file, "\t%s=pop(*%s)\n", reg_names[regno], sp);
c83c42d9
RK
1552 }
1553
c83c42d9
RK
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 {
55710451 1560 fprintf (file, "\t%s=%ld\n\t*%s++%s\n",
c83c42d9
RK
1561 reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]);
1562 }
1563 }
1564
1565 fprintf (file, "\treturn\n");
6b0880cb 1566 /* Reset the frame info for the next function. */
c83c42d9
RK
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
1577int
1578emit_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
1593void
1594double_reg_from_memory (operands)
69985118 1595 rtx operands[];
c83c42d9
RK
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
6b0880cb 1609 /* We can't use j anymore since the compiler can allocate it. */
c83c42d9
RK
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;
dff06f62 1616 int offset = 0;
c83c42d9
RK
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
1641void
1642double_reg_to_memory (operands)
69985118 1643 rtx operands[];
c83c42d9
RK
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
6b0880cb 1657 /* We can't use j anymore since the compiler can allocate it. */
c83c42d9
RK
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;
dff06f62 1666 int offset = 0;
c83c42d9
RK
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
c725bd79 1678 fatal_error ("invalid addressing mode");
c83c42d9 1679
dff06f62 1680 fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]);
c83c42d9
RK
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
1691void
1692override_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
ad85216e 1709 save_chip_name = xstrdup (chip_name);
c83c42d9 1710
1dcd444b
KG
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);
c83c42d9
RK
1715}
1716
dff06f62
MC
1717int
1718next_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}
b979ef45 1732
c83c42d9
RK
1733enum rtx_code
1734next_cc_user_code (insn)
69985118 1735 rtx insn;
c83c42d9 1736{
dff06f62 1737 /* If no insn could be found we assume that the jump has been
6b0880cb 1738 deleted and the compare will be deleted later. */
dff06f62 1739
6b0880cb 1740 if (!(insn = next_cc0_user (insn)))
dff06f62 1741 return (enum rtx_code) 0;
c83c42d9
RK
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
1754void
1755print_operand(file, op, letter)
69985118
KG
1756 FILE *file;
1757 rtx op;
1758 int letter;
c83c42d9
RK
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
6b0880cb 1809 if (code == REG)
c83c42d9 1810 {
6b0880cb 1811 /* Print the low half of a 32-bit register pair. */
c83c42d9 1812 if (letter == 'w')
400500c4 1813 fprintf (file, "%s", reg_names[REGNO (op) + 1]);
c83c42d9 1814 else if (letter == 'u' || !letter)
400500c4 1815 fprintf (file, "%s", reg_names[REGNO (op)]);
c83c42d9 1816 else if (letter == 'b')
400500c4 1817 fprintf (file, "%sh", reg_names[REGNO (op)]);
c83c42d9 1818 else if (letter == 'm')
400500c4 1819 fprintf (file, "%s", himode_reg_name[REGNO (op)]);
c83c42d9 1820 else
c725bd79 1821 output_operand_lossage ("bad register extension code");
c83c42d9 1822 }
400500c4
RK
1823 else if (code == MEM)
1824 output_address (XEXP(op,0));
1825 else if (code == CONST_INT)
1826 {
d2a0c2ee 1827 HOST_WIDE_INT val = INTVAL (op);
400500c4
RK
1828
1829 if (letter == 'H')
1830 fprintf (file, HOST_WIDE_INT_PRINT_HEX, val & 0xffff);
c83c42d9 1831 else if (letter == 'h')
400500c4
RK
1832 fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1833 else if (letter == 'U')
6b0880cb 1834 fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
c83c42d9 1835 else
6b0880cb 1836 output_addr_const(file, op);
b216cd4a 1837 }
6b0880cb 1838 else if (code == CONST_DOUBLE && GET_MODE(op) != DImode)
b216cd4a
ZW
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);
e0c32c62 1844 fprintf (file, "0x%lx", l);
b216cd4a 1845 }
dff06f62 1846 else if (code == CONST)
400500c4 1847 {
dff06f62
MC
1848 rtx addr = XEXP (op, 0);
1849
1850 if (GET_CODE (addr) != PLUS)
1851 {
6b0880cb 1852 output_addr_const(file, op);
dff06f62
MC
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
6b0880cb 1883 output_addr_const(file, op);
400500c4
RK
1884 }
1885 else
1886 output_addr_const (file, op);
c83c42d9
RK
1887}
1888
1889
1890void
1891print_operand_address(file, addr)
69985118
KG
1892 FILE *file;
1893 rtx addr;
c83c42d9
RK
1894{
1895 rtx base;
dff06f62 1896 int offset = 0;;
c83c42d9
RK
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);
b3656137
KG
1914 else
1915 abort();
c83c42d9
RK
1916 if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM)
1917 {
1918 if (offset >= -31 && offset <= 0)
1919 offset = 31 + offset;
1920 else
c725bd79 1921 fatal_error ("invalid offset in ybase addressing");
c83c42d9
RK
1922 }
1923 else
c725bd79 1924 fatal_error ("invalid register in ybase addressing");
c83c42d9
RK
1925
1926 fprintf (file, "*(%d)", offset);
1927 break;
1928
1929 default:
6b0880cb
MC
1930 if (FITS_5_BITS (addr))
1931 fprintf (file, "*(0x%x)", (INTVAL (addr) & 0x20));
c83c42d9 1932 else
6b0880cb 1933 output_addr_const (file, addr);
c83c42d9
RK
1934 }
1935}
1936
1937void
400500c4 1938output_dsp16xx_float_const (operands)
69985118 1939 rtx *operands;
c83c42d9 1940{
c83c42d9
RK
1941 rtx src = operands[1];
1942
c83c42d9
RK
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
3a598fbe 1949 operands[1] = GEN_INT (value);
c83c42d9 1950 output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands);
c83c42d9
RK
1951}
1952
69985118 1953static int
c83c42d9
RK
1954reg_save_size ()
1955{
1956 int reg_save_size = 0;
dff06f62
MC
1957 int regno;
1958
c83c42d9
RK
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
6b0880cb 1965 /* If the function makes calls we will save need to save the 'pr' register. */
dff06f62
MC
1966 if (current_frame_info.function_makes_calls)
1967 reg_save_size += 1;
1968
c83c42d9
RK
1969 return (reg_save_size);
1970}
1971
dff06f62 1972#if 0
c83c42d9
RK
1973int
1974dsp16xx_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}
dff06f62 1987#endif
c83c42d9
RK
1988
1989int
1990initial_frame_pointer_offset()
1991{
c83c42d9
RK
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
6b0880cb 2004 to shift by 'shift_amount'. */
c83c42d9
RK
2005
2006#if 0
2007void
2008emit_1600_core_shift (shift_op, operands, shift_amount, mode)
69985118
KG
2009 enum rtx_code shift_op;
2010 rtx *operands;
2011 int shift_amount;
2012 enum machine_mode mode;
c83c42d9
RK
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++)
c5c76735
JL
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))));
c83c42d9
RK
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++)
c5c76735
JL
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))));
c83c42d9
RK
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++)
c5c76735
JL
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))));
c83c42d9
RK
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++)
c5c76735
JL
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))));
c83c42d9
RK
2066 first_shift_emitted = 1;
2067 }
2068 }
2069}
2070#else
2071void
2072emit_1600_core_shift (shift_op, operands, shift_amount)
69985118
KG
2073 enum rtx_code shift_op;
2074 rtx *operands;
2075 int shift_amount;
c83c42d9
RK
2076{
2077 int quotient;
2078 int i;
2079 int first_shift_emitted = 0;
69985118
KG
2080 const char * const *shift_asm_ptr;
2081 const char * const *shift_asm_ptr_first;
c83c42d9
RK
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
c725bd79 2099 fatal_error ("invalid shift operator in emit_1600_core_shift");
c83c42d9
RK
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
dff06f62
MC
2142
2143int
2144num_1600_core_shifts (shift_amount)
2145int 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
c83c42d9 2193void
69985118
KG
2194asm_output_common(file, name, size, rounded)
2195 FILE *file;
2196 const char *name;
2197 int size ATTRIBUTE_UNUSED;
2198 int rounded;
c83c42d9
RK
2199{
2200 bss_section ();
5eb99654 2201 (*targetm.asm_out.globalize_label) (file, name);
c83c42d9
RK
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
2210void
2211asm_output_local(file, name, size, rounded)
69985118
KG
2212 FILE *file;
2213 const char *name;
2214 int size ATTRIBUTE_UNUSED;
2215 int rounded;
c83c42d9
RK
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
c83c42d9
RK
2226int
2227dsp16xx_address_cost (addr)
69985118 2228 rtx addr;
c83c42d9
RK
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\f
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
5519a4f9 2310 must begin on an even register boundary
c83c42d9
RK
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
6b0880cb 2317 where GCC did not expect to have register arguments, followed. */
c83c42d9
RK
2318
2319struct rtx_def *
2320dsp16xx_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
dff06f62
MC
2332 if (type == void_type_node)
2333 return (struct rtx_def *) 0;
2334
c83c42d9 2335 if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type))
c5c76735 2336 return gen_rtx_REG (mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG);
c83c42d9
RK
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
2346void
2347dsp16xx_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 */
69985118 2351 int named ATTRIBUTE_UNUSED;/* whether or not the argument was named */
c83c42d9
RK
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
2366void
dff06f62
MC
2367coff_dsp16xx_file_start (file)
2368 FILE *file;
c83c42d9 2369{
dff06f62
MC
2370 fprintf (file, "#include <%s.h>\n", save_chip_name);
2371}
2372
2373void
2374luxworks_dsp16xx_file_start (file)
2375 FILE *file;
2376{
2377 char *temp_filename;
2378 int len, err_code;
2379
2380
6b0880cb 2381 fprintf (file, "\t.debug ");
dff06f62
MC
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 }
c83c42d9 2394#endif
6b0880cb 2395 fprintf (file, "\"%s\"\n", temp_filename);
dff06f62
MC
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
6b0880cb
MC
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");
c83c42d9
RK
2409}
2410
2411rtx
2412gen_tst_reg (x)
2413 rtx x;
2414{
2415 enum machine_mode mode;
2416
2417 mode = GET_MODE (x);
2418
2419 if (mode == QImode)
400500c4
RK
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)))));
c83c42d9 2425 else if (mode == HImode)
c5c76735 2426 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x));
c83c42d9 2427 else
c725bd79 2428 fatal_error ("invalid mode for gen_tst_reg");
c83c42d9
RK
2429
2430 return cc0_rtx;
2431}
2432
2433rtx
2434gen_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
6b0880cb 2442 do anything here. */
c83c42d9
RK
2443
2444 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
2445 return cc0_rtx;
2446
2447 if (mode == QImode)
2448 {
c5c76735
JL
2449 if (code == GTU || code == GEU
2450 || code == LTU || code == LEU)
c83c42d9 2451 {
c5c76735
JL
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)))));
c83c42d9
RK
2461 }
2462 else
2463 {
c5c76735
JL
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)))));
c83c42d9
RK
2472 }
2473 }
2474 else if (mode == HImode)
2475 {
c5c76735
JL
2476 if (code == GTU || code == GEU
2477 || code == LTU || code == LEU)
c83c42d9 2478 {
dff06f62
MC
2479 emit_insn (gen_rtx_PARALLEL
2480 (VOIDmode,
c5c76735 2481 gen_rtvec (5,
dff06f62
MC
2482 gen_rtx_SET (VOIDmode, cc0_rtx,
2483 gen_rtx_COMPARE (VOIDmode, x, y)),
2484 gen_rtx_CLOBBER (VOIDmode,
c5c76735 2485 gen_rtx_SCRATCH (QImode)),
dff06f62 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)))));
c83c42d9
RK
2492 }
2493 else
c5c76735
JL
2494 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
2495 gen_rtx_COMPARE (VOIDmode,
2496 force_reg (HImode, x),
2497 force_reg (HImode,y))));
c83c42d9
RK
2498 }
2499 else
c725bd79 2500 fatal_error ("invalid mode for integer comparison in gen_compare_reg");
c83c42d9
RK
2501
2502 return cc0_rtx;
2503}
2504
69985118 2505const char *
c83c42d9
RK
2506output_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}
dff06f62
MC
2524
2525int
2526uns_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
2548int
2549signed_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}