1 /* Subroutines for assembler code output on the DSP1610.
2 Copyright (C) 1994, 1995, 1997, 1998, 2001 Free Software Foundation, Inc.
3 Contributed by Michael Collison (collison@isisinc.net).
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* Some output-actions in dsp1600.md need these. */
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
32 #include "insn-attr.h"
42 #include "target-def.h"
44 const char *text_seg_name;
45 const char *rsect_text;
46 const char *data_seg_name;
47 const char *rsect_data;
48 const char *bss_seg_name;
49 const char *rsect_bss;
50 const char *const_seg_name;
51 const char *rsect_const;
53 const char *chip_name;
54 const char *save_chip_name;
56 /* Save the operands of a compare. The 16xx has not lt or gt, so
57 in these cases we swap the operands and reverse the condition. */
59 rtx dsp16xx_compare_op0;
60 rtx dsp16xx_compare_op1;
61 rtx (*dsp16xx_compare_gen) PARAMS (());
63 static const char *fp;
64 static const char *sp;
65 static const char *rr;
66 static const char *a1h;
68 struct dsp16xx_frame_info current_frame_info;
69 struct dsp16xx_frame_info zero_frame_info;
71 rtx dsp16xx_addhf3_libcall = (rtx) 0;
72 rtx dsp16xx_subhf3_libcall = (rtx) 0;
73 rtx dsp16xx_mulhf3_libcall = (rtx) 0;
74 rtx dsp16xx_divhf3_libcall = (rtx) 0;
75 rtx dsp16xx_cmphf3_libcall = (rtx) 0;
76 rtx dsp16xx_fixhfhi2_libcall = (rtx) 0;
77 rtx dsp16xx_floathihf2_libcall = (rtx) 0;
78 rtx dsp16xx_neghf2_libcall = (rtx) 0;
80 rtx dsp16xx_mulhi3_libcall = (rtx) 0;
81 rtx dsp16xx_udivqi3_libcall = (rtx) 0;
82 rtx dsp16xx_udivhi3_libcall = (rtx) 0;
83 rtx dsp16xx_divqi3_libcall = (rtx) 0;
84 rtx dsp16xx_divhi3_libcall = (rtx) 0;
85 rtx dsp16xx_modqi3_libcall = (rtx) 0;
86 rtx dsp16xx_modhi3_libcall = (rtx) 0;
87 rtx dsp16xx_umodqi3_libcall = (rtx) 0;
88 rtx dsp16xx_umodhi3_libcall = (rtx) 0;
89 rtx dsp16xx_ashrhi3_libcall = (rtx) 0;
90 rtx dsp16xx_ashlhi3_libcall = (rtx) 0;
91 rtx dsp16xx_ucmphi2_libcall = (rtx) 0;
92 rtx dsp16xx_lshrhi3_libcall = (rtx) 0;
94 static const char *const himode_reg_name[] = HIMODE_REGISTER_NAMES;
96 #define SHIFT_INDEX_1 0
97 #define SHIFT_INDEX_4 1
98 #define SHIFT_INDEX_8 2
99 #define SHIFT_INDEX_16 3
101 static const char *const ashift_right_asm[] =
109 static const char *const ashift_right_asm_first[] =
117 static const char *const ashift_left_asm[] =
125 static const char *const ashift_left_asm_first[] =
133 static const char *const lshift_right_asm[] =
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"
141 static const char *const lshift_right_asm_first[] =
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"
149 static int reg_save_size PARAMS ((void));
150 static void dsp16xx_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
151 static void dsp16xx_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
153 /* Initialize the GCC target structure. */
154 #undef TARGET_ASM_BYTE_OP
155 #define TARGET_ASM_BYTE_OP "\tint\t"
156 #undef TARGET_ASM_ALIGNED_HI_OP
157 #define TARGET_ASM_ALIGNED_HI_OP NULL
158 #undef TARGET_ASM_ALIGNED_SI_OP
159 #define TARGET_ASM_ALIGNED_SI_OP NULL
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
166 struct gcc_target targetm = TARGET_INITIALIZER;
169 hard_regno_mode_ok (regno, mode)
171 enum machine_mode mode;
178 /* We can't use the c0-c2 for QImode, since they are only
182 if (regno != REG_C0 && regno != REG_C1 && regno != REG_C2)
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
198 if (regno == REG_A0 || regno == REG_A1 || regno == REG_Y || regno == REG_PROD
199 || (IS_YBASE_REGISTER_WINDOW(regno) && ((regno & 1) == 0)))
210 dsp16xx_reg_class_from_letter (c)
225 return ACCUM_HIGH_REGS;
255 return ACCUM_Y_OR_P_REGS;
261 return (TARGET_BMU ? BMU_REGS : NO_REGS);
264 return YBASE_VIRT_REGS;
276 return YBASE_ELIGIBLE_REGS;
279 return ACCUM_LOW_REGS;
282 return NON_YBASE_REGS;
288 return SLOW_MEM_LOAD_REGS;
295 /* Return the class number of the smallest class containing
299 regno_reg_class(regno)
305 return (int) A0L_REG;
307 return (int) A1L_REG;
310 return (int) A0H_REG;
312 return (int) A1H_REG;
327 case REG_R0: case REG_R1: case REG_R2: case REG_R3:
328 return (int) Y_ADDR_REGS;
333 return (int) GENERAL_REGS;
336 return (int) GENERAL_REGS;
339 return (int) GENERAL_REGS;
341 case REG_AR0: case REG_AR1: case REG_AR2: case REG_AR3:
342 return (int) BMU_REGS;
344 case REG_C0: case REG_C1: case REG_C2:
345 return (int) GENERAL_REGS;
348 return (int) GENERAL_REGS;
351 return (int) GENERAL_REGS;
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;
364 return (int) NO_REGS;
368 /* A C expression for the maximum number of consecutive registers of class CLASS
369 needed to hold a value of mode MODE. */
372 class_max_nregs(class, mode)
373 enum reg_class class ATTRIBUTE_UNUSED;
374 enum machine_mode mode;
376 return (GET_MODE_SIZE(mode));
380 limit_reload_class (mode, class)
381 enum machine_mode mode ATTRIBUTE_UNUSED;
382 enum reg_class class;
388 dsp16xx_register_move_cost (from, to)
389 enum reg_class from, to;
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)
395 if (to == Y_REG || to == P_REG)
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)
408 if (from == YBASE_VIRT_REGS)
410 if (to == YBASE_VIRT_REGS)
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 ||
424 if (to == YBASE_VIRT_REGS)
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 ||
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. */
448 preferred_reload_class (x, class)
450 enum reg_class class;
452 /* The ybase registers cannot have constants copied directly
459 case YBASE_VIRT_REGS:
460 return (!reload_in_progress ? NO_REGS : class);
462 case ACCUM_LOW_OR_YBASE_REGS:
463 return ACCUM_LOW_REGS;
465 case ACCUM_OR_YBASE_REGS:
468 case X_OR_YBASE_REGS:
471 case Y_OR_YBASE_REGS:
474 case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
475 return YL_OR_PL_OR_ACCUM_LOW_REGS;
477 case P_OR_YBASE_REGS:
480 case ACCUM_Y_P_OR_YBASE_REGS:
481 return ACCUM_Y_OR_P_REGS;
483 case Y_ADDR_OR_YBASE_REGS:
486 case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
487 return NON_HIGH_YBASE_ELIGIBLE_REGS;;
489 case YBASE_OR_YBASE_ELIGIBLE_REGS:
490 return YBASE_ELIGIBLE_REGS;
492 case NO_HIGH_ALL_REGS:
493 return NOHIGH_NON_YBASE_REGS;
496 return NON_YBASE_REGS;
503 /* If x is not an accumulator or a ybase register, restrict the class of registers
504 we can copy the register into. */
506 if (REG_P (x) && !IS_ACCUM_REG (REGNO (x)) && !IS_YBASE_REGISTER_WINDOW (REGNO (x)))
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:
517 return (!reload_in_progress ? NO_REGS : class);
519 case X_OR_ACCUM_LOW_REGS:
520 return ACCUM_LOW_REGS;
522 case X_OR_ACCUM_REGS:
526 return (!reload_in_progress ? NO_REGS : class);
528 case YH_OR_ACCUM_HIGH_REGS:
529 return ACCUM_HIGH_REGS;
533 return (!reload_in_progress ? NO_REGS : class);
535 case YL_OR_ACCUM_LOW_REGS:
536 return ACCUM_LOW_REGS;
539 case X_OR_Y_REGS: case Y_REG:
540 return (!reload_in_progress ? NO_REGS : class);
542 case ACCUM_OR_Y_REGS:
546 case X_OR_PH_REGS: case PL_REG:
547 return (!reload_in_progress ? NO_REGS : class);
549 case PL_OR_ACCUM_LOW_REGS:
550 return ACCUM_LOW_REGS;
553 return (!reload_in_progress ? NO_REGS : class);
555 case YL_OR_PL_OR_ACCUM_LOW_REGS:
556 return ACCUM_LOW_REGS;
559 return (!reload_in_progress ? NO_REGS : class);
561 case ACCUM_OR_P_REGS:
565 return (!reload_in_progress ? NO_REGS : class);
567 case ACCUM_LOW_OR_YL_OR_P_REGS:
568 return ACCUM_LOW_REGS;
571 return (!reload_in_progress ? NO_REGS : class);
573 case ACCUM_Y_OR_P_REGS:
576 case NO_FRAME_Y_ADDR_REGS:
578 return (!reload_in_progress ? NO_REGS : class);
580 case ACCUM_LOW_OR_Y_ADDR_REGS:
581 return ACCUM_LOW_REGS;
583 case ACCUM_OR_Y_ADDR_REGS:
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);
591 case NON_HIGH_YBASE_ELIGIBLE_REGS:
592 return ACCUM_LOW_REGS;
594 case YBASE_ELIGIBLE_REGS:
598 case J_OR_DAU_16_BIT_REGS:
600 return (!reload_in_progress ? NO_REGS : class);
602 case YBASE_VIRT_REGS:
603 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
606 return (!reload_in_progress ? NO_REGS : class);
608 case ACCUM_LOW_OR_YBASE_REGS:
609 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
612 return ACCUM_LOW_REGS;
614 case ACCUM_OR_YBASE_REGS:
615 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
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;
625 return (!reload_in_progress ? NO_REGS : class);
627 case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
628 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
629 return ACCUM_LOW_OR_YBASE_REGS;
631 return ACCUM_LOW_REGS;
633 case P_OR_YBASE_REGS:
634 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
635 return YBASE_VIRT_REGS;
637 return (!reload_in_progress ? NO_REGS : class);
639 case ACCUM_Y_P_OR_YBASE_REGS:
640 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
641 return ACCUM_OR_YBASE_REGS;
645 case Y_ADDR_OR_YBASE_REGS:
646 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
647 return YBASE_VIRT_REGS;
649 return (!reload_in_progress ? NO_REGS : class);
651 case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
652 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
653 return ACCUM_LOW_OR_YBASE_REGS;
655 return ACCUM_LOW_REGS;
657 case YBASE_OR_YBASE_ELIGIBLE_REGS:
658 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
659 return ACCUM_OR_YBASE_REGS;
663 case NO_HIGH_ALL_REGS:
664 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
665 return ACCUM_LOW_OR_YBASE_REGS;
667 return ACCUM_LOW_REGS;
670 if (IS_YBASE_ELIGIBLE_REG (REGNO (x)))
671 return ACCUM_OR_YBASE_REGS;
675 case NOHIGH_NON_ADDR_REGS:
676 return ACCUM_LOW_REGS;
679 case SLOW_MEM_LOAD_REGS:
682 case NOHIGH_NON_YBASE_REGS:
683 return ACCUM_LOW_REGS;
685 case NO_ACCUM_NON_YBASE_REGS:
686 return (!reload_in_progress ? NO_REGS : class);
696 /* If x (the input) is a ybase register, restrict the class of registers
697 we can copy the register into. */
699 if (REG_P (x) && !TARGET_RESERVE_YBASE
700 && IS_YBASE_REGISTER_WINDOW (REGNO(x)))
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:
728 return (!reload_in_progress ? NO_REGS : class);
730 case J_OR_DAU_16_BIT_REGS:
731 return ACCUM_HIGH_REGS;
734 case YBASE_VIRT_REGS:
735 return (!reload_in_progress ? NO_REGS : class);
737 case ACCUM_LOW_OR_YBASE_REGS:
738 return ACCUM_LOW_REGS;
740 case ACCUM_OR_YBASE_REGS:
743 case X_OR_YBASE_REGS:
746 case Y_OR_YBASE_REGS:
749 case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
750 return YL_OR_PL_OR_ACCUM_LOW_REGS;
752 case P_OR_YBASE_REGS:
755 case ACCUM_Y_P_OR_YBASE_REGS:
756 return ACCUM_Y_OR_P_REGS;
758 case Y_ADDR_OR_YBASE_REGS:
761 case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
762 return NON_HIGH_YBASE_ELIGIBLE_REGS;
764 case YBASE_OR_YBASE_ELIGIBLE_REGS:
765 return YBASE_ELIGIBLE_REGS;
767 case NO_HIGH_ALL_REGS:
768 return NON_HIGH_YBASE_ELIGIBLE_REGS;
771 return YBASE_ELIGIBLE_REGS;
773 case NOHIGH_NON_ADDR_REGS:
774 return ACCUM_LOW_OR_YL_OR_P_REGS;
777 return ACCUM_Y_OR_P_REGS;
779 case SLOW_MEM_LOAD_REGS:
780 return ACCUM_OR_Y_ADDR_REGS;
782 case NOHIGH_NON_YBASE_REGS:
783 return NON_HIGH_YBASE_ELIGIBLE_REGS;
785 case NO_ACCUM_NON_YBASE_REGS:
789 return YBASE_ELIGIBLE_REGS;
793 if (GET_CODE (x) == PLUS)
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))
801 if (class == ACCUM_HIGH_REGS)
804 /* If the accumulators are not part of the class
805 being reloaded into, return NO_REGS. */
807 if (!reg_class_subset_p (ACCUM_REGS, class))
808 return (!reload_in_progress ? NO_REGS : class);
810 if (reg_class_subset_p (ACCUM_HIGH_REGS, class))
811 return ACCUM_HIGH_REGS;
813 /* We will use accumulator 'a1l' for reloading a
814 PLUS. We can only use one accumulator because
815 'reload_inqi' only allows one alternative to be
818 else if (class == ACCUM_LOW_REGS)
820 else if (class == A0L_REG)
826 if (class == NON_YBASE_REGS || class == YBASE_ELIGIBLE_REGS)
831 else if (GET_CODE (x) == MEM)
833 /* We can't copy from a memory location into a
835 if (reg_class_subset_p(YBASE_VIRT_REGS, class))
839 case YBASE_VIRT_REGS:
840 return (!reload_in_progress ? NO_REGS : class);
842 case ACCUM_LOW_OR_YBASE_REGS:
843 return ACCUM_LOW_REGS;
845 case ACCUM_OR_YBASE_REGS:
848 case X_OR_YBASE_REGS:
851 case Y_OR_YBASE_REGS:
854 case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
855 return YL_OR_PL_OR_ACCUM_LOW_REGS;
857 case P_OR_YBASE_REGS:
860 case ACCUM_Y_P_OR_YBASE_REGS:
861 return ACCUM_Y_OR_P_REGS;
863 case Y_ADDR_OR_YBASE_REGS:
866 case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
867 return NON_HIGH_YBASE_ELIGIBLE_REGS;
869 case YBASE_OR_YBASE_ELIGIBLE_REGS:
870 return YBASE_ELIGIBLE_REGS;
872 case NO_HIGH_ALL_REGS:
873 return NOHIGH_NON_YBASE_REGS;
876 return NON_YBASE_REGS;
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. */
894 secondary_reload_class (class, mode, in)
895 enum reg_class class;
896 enum machine_mode mode;
901 if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
902 regno = true_regnum (in);
904 /* If we are reloading a plus into a high accumulator register,
905 we need a scratch low accumulator, because the low half gets
908 if (class == ACCUM_HIGH_REGS
912 if (GET_CODE (in) == PLUS && mode == QImode)
913 return ACCUM_LOW_REGS;
916 if (class == ACCUM_HIGH_REGS
917 || class == ACCUM_LOW_REGS
923 if (GET_CODE (in) == PLUS && mode == QImode)
925 rtx addr0 = XEXP (in, 0);
926 rtx addr1 = XEXP (in, 1);
928 /* If we are reloading a plus (reg:QI) (reg:QI)
929 we need an additional register. */
930 if (REG_P (addr0) && REG_P (addr1))
935 /* We can place anything into ACCUM_REGS and can put ACCUM_REGS
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))
944 if (class == ACCUM_OR_YBASE_REGS && REG_P(in)
945 && IS_YBASE_ELIGIBLE_REG(regno))
950 /* We can copy the ybase registers into:
951 r0-r3, a0-a1, y, p, & x or the union of
954 if (!TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW(regno))
959 case (int) X_OR_ACCUM_LOW_REGS:
960 case (int) X_OR_ACCUM_REGS:
962 case (int) YH_OR_ACCUM_HIGH_REGS:
963 case (int) X_OR_YH_REGS:
965 case (int) YL_OR_ACCUM_LOW_REGS:
966 case (int) X_OR_Y_REGS:
967 case (int) X_OR_YL_REGS:
969 case (int) ACCUM_OR_Y_REGS:
971 case (int) X_OR_PH_REGS:
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:
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:
992 return ACCUM_HIGH_REGS;
996 /* We can copy r0-r3, a0-a1, y, & p
997 directly to the ybase registers. In addition
998 we can use any of the ybase virtual registers
999 as the secondary reload registers when copying
1000 between any of these registers. */
1002 if (!TARGET_RESERVE_YBASE && regno != -1)
1019 if (class == YBASE_VIRT_REGS)
1023 switch ((int) class)
1026 case (int) X_OR_ACCUM_LOW_REGS:
1027 case (int) X_OR_ACCUM_REGS:
1029 case (int) YH_OR_ACCUM_HIGH_REGS:
1030 case (int) X_OR_YH_REGS:
1032 case (int) YL_OR_ACCUM_LOW_REGS:
1033 case (int) X_OR_Y_REGS:
1034 case (int) X_OR_YL_REGS:
1036 case (int) ACCUM_OR_Y_REGS:
1038 case (int) X_OR_PH_REGS:
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:
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;
1065 /* Memory or constants can be moved from or to any register
1066 except the ybase virtual registers. */
1067 if (regno == -1 && GET_CODE(in) != PLUS)
1069 if (class == YBASE_VIRT_REGS)
1070 return NON_YBASE_REGS;
1075 if (GET_CODE (in) == PLUS && mode == QImode)
1077 rtx addr0 = XEXP (in, 0);
1078 rtx addr1 = XEXP (in, 1);
1080 /* If we are reloading a plus (reg:QI) (reg:QI)
1081 we need a low accumulator, not a high one. */
1082 if (REG_P (addr0) && REG_P (addr1))
1083 return ACCUM_LOW_REGS;
1091 /* Otherwise, we need a high accumulator(s). */
1092 return ACCUM_HIGH_REGS;
1096 symbolic_address_operand (op, mode)
1098 enum machine_mode mode ATTRIBUTE_UNUSED;
1100 return (symbolic_address_p (op));
1104 symbolic_address_p (op)
1107 switch (GET_CODE (op))
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);
1125 /* For a Y address space operand we allow only *rn, *rn++, *rn--.
1126 This routine only recognizes *rn, the '<>' constraints recognize
1127 (*rn++), and (*rn--). */
1130 Y_address_operand (op, mode)
1132 enum machine_mode mode;
1134 return (memory_address_p (mode, op) && !symbolic_address_p (op));
1138 sp_operand (op, mode)
1140 enum machine_mode mode ATTRIBUTE_UNUSED;
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);
1149 sp_operand2 (op, mode)
1151 enum machine_mode mode ATTRIBUTE_UNUSED;
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))))))
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))))))
1170 nonmemory_arith_operand (op, mode)
1172 enum machine_mode mode;
1174 return (immediate_operand (op, mode) || arith_reg_operand (op, mode));
1178 arith_reg_operand (op, mode)
1180 enum machine_mode mode;
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)));
1190 call_address_operand (op, mode)
1192 enum machine_mode mode ATTRIBUTE_UNUSED;
1194 if (symbolic_address_p (op) || REG_P(op))
1203 dsp16xx_comparison_operator (op, mode)
1205 enum machine_mode mode;
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));
1214 notice_update_cc(exp)
1217 if (GET_CODE (exp) == SET)
1219 /* Jumps do not alter the cc's. */
1221 if (SET_DEST (exp) == pc_rtx)
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))
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;
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)))
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;
1249 /* Function calls clobber the cc's. */
1250 else if (GET_CODE (SET_SRC (exp)) == CALL)
1255 /* Tests and compares set the cc's in predictable ways. */
1256 else if (SET_DEST (exp) == cc0_rtx)
1259 cc_status.value1 = SET_SRC (exp);
1262 /* Certain instructions effect the condition codes. */
1263 else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT)
1264 switch (GET_CODE (SET_SRC (exp)))
1268 if (REG_P (SET_DEST (exp)))
1270 /* Address registers don't set the condition codes. */
1271 if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp))))
1286 cc_status.value1 = SET_SRC (exp);
1287 cc_status.value2 = SET_DEST (exp);
1298 else if (GET_CODE (exp) == PARALLEL
1299 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1301 if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
1304 if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
1307 cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
1320 dsp16xx_makes_calls ()
1324 for (insn = get_insns (); insn; insn = next_insn (insn))
1325 if (GET_CODE (insn) == CALL_INSN)
1332 compute_frame_size (size)
1341 /* This value is needed to compute reg_size. */
1342 current_frame_info.function_makes_calls = !leaf_function_p ();
1347 args_size = current_function_outgoing_args_size;
1348 reg_size = reg_save_size ();
1350 total_size = var_size + args_size + extra_size + reg_size;
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;
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;
1373 dsp16xx_call_saved_register (regno)
1377 if (regno == REG_PR && current_frame_info.function_makes_calls)
1380 return (regs_ever_live[regno] && !call_used_regs[regno] &&
1381 !IS_YBASE_REGISTER_WINDOW(regno));
1385 ybase_regs_ever_used ()
1390 for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++)
1391 if (regs_ever_live[regno])
1401 dsp16xx_output_function_prologue (file, 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];
1412 total_size = compute_frame_size (size);
1414 fprintf (file, "\t/* FUNCTION PROLOGUE: */\n");
1415 fprintf (file, "\t/* total=%ld, vars= %ld, regs= %d, args=%d, extra= %ld */\n",
1416 current_frame_info.total_size,
1417 current_frame_info.var_size,
1418 current_frame_info.reg_size,
1419 current_function_outgoing_args_size,
1420 current_frame_info.extra_size);
1422 fprintf (file, "\t/* fp save offset= %ld, sp save_offset= %ld */\n\n",
1423 current_frame_info.fp_save_offset,
1424 current_frame_info.sp_save_offset);
1425 /* Set up the 'ybase' register window. */
1427 if (ybase_regs_ever_used())
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);
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);
1437 if (current_frame_info.var_size)
1439 if (current_frame_info.var_size == 1)
1440 fprintf (file, "\t*%s++\n", sp);
1443 if (SMALL_INTVAL(current_frame_info.var_size) && ((current_frame_info.var_size & 0x8000) == 0))
1444 fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J], current_frame_info.var_size, sp, reg_names[REG_J]);
1446 fatal_error ("stack size > 32k");
1450 /* Save any registers this function uses, unless they are
1451 used in a call, in which case we don't need to. */
1453 for(regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno)
1454 if (dsp16xx_call_saved_register (regno))
1456 fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[regno]);
1459 /* For debugging purposes, we want the return address to be at a predictable
1461 if (current_frame_info.function_makes_calls)
1462 fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[RETURN_ADDRESS_REGNUM]);
1464 if (current_frame_info.args_size)
1466 if (current_frame_info.args_size == 1)
1467 fprintf (file, "\t*%s++\n", sp);
1469 error ("stack size > 32k");
1472 if (frame_pointer_needed)
1474 fprintf (file, "\t%s=%s\n", a1h, sp);
1475 fprintf (file, "\t%s=%s\n", fp, a1h); /* Establish new base frame */
1476 fprintf (file, "\t%s=%ld\n", reg_names[REG_J], -total_size);
1477 fprintf (file, "\t*%s++%s\n", fp, reg_names[REG_J]);
1480 fprintf (file, "\t/* END FUNCTION PROLOGUE: */\n\n");
1484 init_emulation_routines ()
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;
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;
1511 dsp16xx_output_function_epilogue (file, size)
1513 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
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];
1522 fprintf (file, "\n\t/* FUNCTION EPILOGUE: */\n");
1524 if (current_frame_info.args_size)
1526 if (current_frame_info.args_size == 1)
1527 fprintf (file, "\t*%s--\n", sp);
1530 fprintf (file, "\t%s=%ld\n\t*%s++%s\n",
1531 reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]);
1535 if (ybase_regs_ever_used())
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);
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);
1545 if (current_frame_info.function_makes_calls)
1546 fprintf (file, "\t%s=pop(*%s)\n", reg_names[RETURN_ADDRESS_REGNUM], sp);
1548 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1549 if (dsp16xx_call_saved_register(regno))
1551 fprintf (file, "\t%s=pop(*%s)\n", reg_names[regno], sp);
1554 if (current_frame_info.var_size)
1556 if (current_frame_info.var_size == 1)
1557 fprintf (file, "\t*%s--\n", sp);
1560 fprintf (file, "\t%s=%ld\n\t*%s++%s\n",
1561 reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]);
1565 fprintf (file, "\treturn\n");
1566 /* Reset the frame info for the next function. */
1567 current_frame_info = zero_frame_info;
1568 init_emulation_routines ();
1571 /* Emit insns to move operands[1] into operands[0].
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
1578 emit_move_sequence (operands, mode)
1580 enum machine_mode mode;
1582 register rtx operand0 = operands[0];
1583 register rtx operand1 = operands[1];
1585 /* We can only store registers to memory. */
1587 if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG)
1588 operands[1] = force_reg (mode, operand1);
1594 double_reg_from_memory (operands)
1599 if (GET_CODE(XEXP(operands[1],0)) == POST_INC)
1601 output_asm_insn ("%u0=%1", operands);
1602 output_asm_insn ("%w0=%1", operands);
1604 else if (GET_CODE(XEXP(operands[1],0)) == POST_DEC)
1606 xoperands[1] = XEXP (XEXP (operands[1], 0), 0);
1607 xoperands[0] = operands[0];
1609 /* We can't use j anymore since the compiler can allocate it. */
1610 /* output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */
1611 output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands);
1613 else if (GET_CODE(XEXP(operands[1],0)) == PLUS)
1618 output_asm_insn ("%u0=%1", operands);
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;
1629 fprintf (asm_out_file, "\t%s=*(%d)\n", reg_names[REGNO(operands[0]) + 1], offset + 31);
1633 xoperands[1] = XEXP(operands[1],0);
1634 xoperands[0] = operands[0];
1636 output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands);
1642 double_reg_to_memory (operands)
1647 if (GET_CODE(XEXP(operands[0],0)) == POST_INC)
1649 output_asm_insn ("%0=%u1", operands);
1650 output_asm_insn ("%0=%w1", operands);
1652 else if (GET_CODE(XEXP(operands[0],0)) == POST_DEC)
1654 xoperands[0] = XEXP (XEXP (operands[0], 0), 0);
1655 xoperands[1] = operands[1];
1657 /* We can't use j anymore since the compiler can allocate it. */
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);
1663 else if (GET_CODE(XEXP(operands[0],0)) == PLUS)
1668 output_asm_insn ("%0=%u1", operands);
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;
1678 fatal_error ("invalid addressing mode");
1680 fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31, reg_names[REGNO(operands[1]) + 1]);
1684 xoperands[0] = XEXP(operands[0],0);
1685 xoperands[1] = operands[1];
1687 output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands);
1694 if (chip_name == (char *) 0)
1695 chip_name = DEFAULT_CHIP_NAME;
1697 if (text_seg_name == (char *) 0)
1698 text_seg_name = DEFAULT_TEXT_SEG_NAME;
1700 if (data_seg_name == (char *) 0)
1701 data_seg_name = DEFAULT_DATA_SEG_NAME;
1703 if (bss_seg_name == (char *) 0)
1704 bss_seg_name = DEFAULT_BSS_SEG_NAME;
1706 if (const_seg_name == (char *) 0)
1707 const_seg_name = DEFAULT_CONST_SEG_NAME;
1709 save_chip_name = xstrdup (chip_name);
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);
1718 next_cc_user_unsigned (insn)
1721 switch (next_cc_user_code (insn))
1734 next_cc_user_code (insn)
1737 /* If no insn could be found we assume that the jump has been
1738 deleted and the compare will be deleted later. */
1740 if (!(insn = next_cc0_user (insn)))
1741 return (enum rtx_code) 0;
1742 else if (GET_CODE (insn) == JUMP_INSN
1743 && GET_CODE (PATTERN (insn)) == SET
1744 && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
1745 return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0));
1746 else if (GET_CODE (insn) == INSN
1747 && GET_CODE (PATTERN (insn)) == SET
1748 && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode))
1749 return GET_CODE (SET_SRC (PATTERN (insn)));
1755 print_operand(file, op, letter)
1762 code = GET_CODE(op);
1767 code = reverse_condition (code);
1776 else if (code == NE)
1781 else if (code == GT || code == GTU)
1786 else if (code == LT || code == LTU)
1791 else if (code == GE || code == GEU)
1796 else if (code == LE || code == LEU)
1811 /* Print the low half of a 32-bit register pair. */
1813 fprintf (file, "%s", reg_names[REGNO (op) + 1]);
1814 else if (letter == 'u' || !letter)
1815 fprintf (file, "%s", reg_names[REGNO (op)]);
1816 else if (letter == 'b')
1817 fprintf (file, "%sh", reg_names[REGNO (op)]);
1818 else if (letter == 'm')
1819 fprintf (file, "%s", himode_reg_name[REGNO (op)]);
1821 output_operand_lossage ("bad register extension code");
1823 else if (code == MEM)
1824 output_address (XEXP(op,0));
1825 else if (code == CONST_INT)
1827 HOST_WIDE_INT val = INTVAL (op);
1830 fprintf (file, HOST_WIDE_INT_PRINT_HEX, val & 0xffff);
1831 else if (letter == 'h')
1832 fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1833 else if (letter == 'U')
1834 fprintf (file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
1836 output_addr_const(file, op);
1838 else if (code == CONST_DOUBLE && GET_MODE(op) != DImode)
1842 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1843 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1844 fprintf (file, "0x%lx", l);
1846 else if (code == CONST)
1848 rtx addr = XEXP (op, 0);
1850 if (GET_CODE (addr) != PLUS)
1852 output_addr_const(file, op);
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))
1860 int n = INTVAL (XEXP(addr, 1));
1861 output_addr_const (file, XEXP (addr, 0));
1864 fprintf (file, "+");
1866 n = (int) (short) n;
1867 fprintf (file, "%d", n);
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))
1873 int n = INTVAL (XEXP(addr, 0));
1874 output_addr_const (file, XEXP (addr, 1));
1877 fprintf (file, "+");
1879 n = (int) (short) n;
1880 fprintf (file, "%d", n);
1883 output_addr_const(file, op);
1886 output_addr_const (file, op);
1891 print_operand_address(file, addr)
1898 switch (GET_CODE (addr))
1901 fprintf (file, "*%s", reg_names[REGNO (addr)]);
1904 fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]);
1907 fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]);
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);
1916 if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM)
1918 if (offset >= -31 && offset <= 0)
1919 offset = 31 + offset;
1921 fatal_error ("invalid offset in ybase addressing");
1924 fatal_error ("invalid register in ybase addressing");
1926 fprintf (file, "*(%d)", offset);
1930 if (FITS_5_BITS (addr))
1931 fprintf (file, "*(0x%x)", (INTVAL (addr) & 0x20));
1933 output_addr_const (file, addr);
1938 output_dsp16xx_float_const (operands)
1941 rtx src = operands[1];
1946 REAL_VALUE_FROM_CONST_DOUBLE (d, src);
1947 REAL_VALUE_TO_TARGET_SINGLE (d, value);
1949 operands[1] = GEN_INT (value);
1950 output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands);
1956 int reg_save_size = 0;
1959 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1960 if (dsp16xx_call_saved_register (regno))
1962 reg_save_size += UNITS_PER_WORD;
1965 /* If the function makes calls we will save need to save the 'pr' register. */
1966 if (current_frame_info.function_makes_calls)
1969 return (reg_save_size);
1974 dsp16xx_starting_frame_offset()
1976 int reg_save_size = 0;
1979 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1980 if (dsp16xx_call_saved_register (regno))
1982 reg_save_size += UNITS_PER_WORD;
1985 return (reg_save_size);
1990 initial_frame_pointer_offset()
1994 offset = compute_frame_size (get_frame_size());
1996 #ifdef STACK_GROWS_DOWNWARD
2003 /* Generate the minimum number of 1600 core shift instructions
2004 to shift by 'shift_amount'. */
2008 emit_1600_core_shift (shift_op, operands, shift_amount, mode)
2009 enum rtx_code shift_op;
2012 enum machine_mode mode;
2016 int first_shift_emitted = 0;
2018 while (shift_amount != 0)
2020 if (shift_amount/16)
2022 quotient = shift_amount/16;
2023 shift_amount = shift_amount - (quotient * 16);
2024 for (i = 0; i < quotient; i++)
2025 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2026 gen_rtx (shift_op, mode,
2028 ? operands[0] : operands[1],
2030 first_shift_emitted = 1;
2032 else if (shift_amount/8)
2034 quotient = shift_amount/8;
2035 shift_amount = shift_amount - (quotient * 8);
2036 for (i = 0; i < quotient; i++)
2037 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2038 gen_rtx (shift_op, mode,
2040 ? operands[0] : operands[1],
2042 first_shift_emitted = 1;
2044 else if (shift_amount/4)
2046 quotient = shift_amount/4;
2047 shift_amount = shift_amount - (quotient * 4);
2048 for (i = 0; i < quotient; i++)
2049 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2050 gen_rtx (shift_op, mode,
2052 ? operands[0] : operands[1],
2054 first_shift_emitted = 1;
2056 else if (shift_amount/1)
2058 quotient = shift_amount/1;
2059 shift_amount = shift_amount - (quotient * 1);
2060 for (i = 0; i < quotient; i++)
2061 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2062 gen_rtx (shift_op, mode,
2064 ? operands[0] : operands[1],
2066 first_shift_emitted = 1;
2072 emit_1600_core_shift (shift_op, operands, shift_amount)
2073 enum rtx_code shift_op;
2079 int first_shift_emitted = 0;
2080 const char * const *shift_asm_ptr;
2081 const char * const *shift_asm_ptr_first;
2083 if (shift_op == ASHIFT)
2085 shift_asm_ptr = ashift_left_asm;
2086 shift_asm_ptr_first = ashift_left_asm_first;
2088 else if (shift_op == ASHIFTRT)
2090 shift_asm_ptr = ashift_right_asm;
2091 shift_asm_ptr_first = ashift_right_asm_first;
2093 else if (shift_op == LSHIFTRT)
2095 shift_asm_ptr = lshift_right_asm;
2096 shift_asm_ptr_first = lshift_right_asm_first;
2099 fatal_error ("invalid shift operator in emit_1600_core_shift");
2101 while (shift_amount != 0)
2103 if (shift_amount/16)
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;
2112 else if (shift_amount/8)
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;
2121 else if (shift_amount/4)
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;
2130 else if (shift_amount/1)
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;
2144 num_1600_core_shifts (shift_amount)
2149 int first_shift_emitted = 0;
2152 while (shift_amount != 0)
2154 if (shift_amount/16)
2156 quotient = shift_amount/16;
2157 shift_amount = shift_amount - (quotient * 16);
2158 for (i = 0; i < quotient; i++)
2160 first_shift_emitted = 1;
2162 else if (shift_amount/8)
2164 quotient = shift_amount/8;
2165 shift_amount = shift_amount - (quotient * 8);
2166 for (i = 0; i < quotient; i++)
2169 first_shift_emitted = 1;
2171 else if (shift_amount/4)
2173 quotient = shift_amount/4;
2174 shift_amount = shift_amount - (quotient * 4);
2175 for (i = 0; i < quotient; i++)
2178 first_shift_emitted = 1;
2180 else if (shift_amount/1)
2182 quotient = shift_amount/1;
2183 shift_amount = shift_amount - (quotient * 1);
2184 for (i = 0; i < quotient; i++)
2187 first_shift_emitted = 1;
2194 asm_output_common(file, name, size, rounded)
2197 int size ATTRIBUTE_UNUSED;
2201 (*targetm.asm_out.globalize_label) (file, name);
2202 assemble_name (file, name);
2205 fprintf (file, "%d * int\n", rounded);
2207 fprintf (file, "int\n");
2211 asm_output_local(file, name, size, rounded)
2214 int size ATTRIBUTE_UNUSED;
2218 assemble_name (file, name);
2221 fprintf (file, "%d * int\n", rounded);
2223 fprintf (file, "int\n");
2227 dsp16xx_address_cost (addr)
2230 switch (GET_CODE (addr))
2240 rtx offset = const0_rtx;
2241 addr = eliminate_constant_term (addr, &offset);
2243 if (GET_CODE (addr) == LABEL_REF)
2246 if (GET_CODE (addr) != SYMBOL_REF)
2249 if (INTVAL (offset) == 0)
2254 case POST_INC: case POST_DEC:
2255 return (GET_MODE (addr) == QImode ? 1 : 2);
2257 case SYMBOL_REF: case LABEL_REF:
2262 register rtx plus0 = XEXP (addr, 0);
2263 register rtx plus1 = XEXP (addr, 1);
2265 if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
2267 plus0 = XEXP (addr, 1);
2268 plus1 = XEXP (addr, 0);
2271 if (GET_CODE (plus0) != REG)
2274 switch (GET_CODE (plus1))
2285 return dsp16xx_address_cost (plus1) + 1;
2294 /* Determine whether a function argument is passed in a register, and
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.
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.
2308 On the dsp1610 the first four words of args are normally in registers
2309 and the rest are pushed. If we a long or on float mode, the argument
2310 must begin on an even register boundary
2312 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2313 For structures that are passed in memory, but could have been
2314 passed in registers, we first load the structure into the
2315 register, and then when the last argument is passed, we store
2316 the registers into the stack locations. This fixes some bugs
2317 where GCC did not expect to have register arguments, followed. */
2320 dsp16xx_function_arg (args_so_far, mode, type, named)
2321 CUMULATIVE_ARGS args_so_far;
2322 enum machine_mode mode;
2328 if ((args_so_far & 1) != 0
2329 && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
2332 if (type == void_type_node)
2333 return (struct rtx_def *) 0;
2335 if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type))
2336 return gen_rtx_REG (mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG);
2338 return (struct rtx_def *) 0;
2341 return (struct rtx_def *) 0;
2344 /* Advance the argument to the next argument position. */
2347 dsp16xx_function_arg_advance (cum, mode, type, named)
2348 CUMULATIVE_ARGS *cum; /* current arg information */
2349 enum machine_mode mode; /* current arg mode */
2350 tree type; /* type of the argument or 0 if lib support */
2351 int named ATTRIBUTE_UNUSED;/* whether or not the argument was named */
2356 && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
2359 if (mode != BLKmode)
2360 *cum += GET_MODE_SIZE (mode);
2362 *cum += int_size_in_bytes (type);
2367 coff_dsp16xx_file_start (file)
2370 fprintf (file, "#include <%s.h>\n", save_chip_name);
2374 luxworks_dsp16xx_file_start (file)
2377 char *temp_filename;
2381 fprintf (file, "\t.debug ");
2382 err_code = (TARGET_DEBUG) ? fprintf (file, "yes, ") : fprintf (file, "no, ");
2383 err_code = (TARGET_SAVE_TEMPS) ? fprintf (file, "asm, ") : fprintf (file, "temp, ");
2384 len = strlen (main_input_filename);
2385 temp_filename = (char *) xmalloc (len + 2);
2386 strcpy (temp_filename, main_input_filename);
2389 while (*p != '\0') {
2395 fprintf (file, "\"%s\"\n", temp_filename);
2397 fprintf (file, "#include <%s.h>\n", save_chip_name);
2400 * Add dummy sections, so that they always exist in the
2401 * object code. These have been created so that the number and
2402 * type of sections remain consistent with and without -g option. Note
2403 * that the .data, .text, .const and .bss are always created when -g
2404 * is provided as an option. */
2405 fprintf (file, "\t.rsect \".text\" , nodelete\n");
2406 fprintf (file, "\t.rsect \".data\" , nodelete\n");
2407 fprintf (file, "\t.rsect \".const\" , nodelete\n");
2408 fprintf (file, "\t.rsect \".bss\" , nodelete\n");
2415 enum machine_mode mode;
2417 mode = GET_MODE (x);
2420 emit_insn (gen_rtx_PARALLEL
2422 gen_rtvec (2, gen_rtx_SET (VOIDmode, cc0_rtx, x),
2423 gen_rtx_CLOBBER (VOIDmode,
2424 gen_rtx_SCRATCH (QImode)))));
2425 else if (mode == HImode)
2426 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x));
2428 fatal_error ("invalid mode for gen_tst_reg");
2434 gen_compare_reg (code, x, y)
2438 enum machine_mode mode;
2440 mode = GET_MODE (x);
2441 /* For floating point compare insns, a call is generated so don't
2442 do anything here. */
2444 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
2449 if (code == GTU || code == GEU
2450 || code == LTU || code == LEU)
2452 emit_insn (gen_rtx_PARALLEL
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)))));
2464 emit_insn (gen_rtx_PARALLEL
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)))));
2474 else if (mode == HImode)
2476 if (code == GTU || code == GEU
2477 || code == LTU || code == LEU)
2479 emit_insn (gen_rtx_PARALLEL
2482 gen_rtx_SET (VOIDmode, cc0_rtx,
2483 gen_rtx_COMPARE (VOIDmode, x, y)),
2484 gen_rtx_CLOBBER (VOIDmode,
2485 gen_rtx_SCRATCH (QImode)),
2486 gen_rtx_CLOBBER (VOIDmode,
2487 gen_rtx_SCRATCH (QImode)),
2488 gen_rtx_CLOBBER (VOIDmode,
2489 gen_rtx_SCRATCH (QImode)),
2490 gen_rtx_CLOBBER (VOIDmode,
2491 gen_rtx_SCRATCH (QImode)))));
2494 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
2495 gen_rtx_COMPARE (VOIDmode,
2496 force_reg (HImode, x),
2497 force_reg (HImode,y))));
2500 fatal_error ("invalid mode for integer comparison in gen_compare_reg");
2506 output_block_move (operands)
2509 int loop_count = INTVAL(operands[2]);
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);
2517 xoperands[0] = operands[0];
2518 xoperands[1] = operands[4];
2519 output_asm_insn ("*%0++=%1", xoperands);
2521 fprintf (asm_out_file, "\t}\n");
2526 uns_comparison_operator (op, mode)
2528 enum machine_mode mode;
2530 if (mode == VOIDmode || GET_MODE (op) == mode)
2534 code = GET_CODE(op);
2536 if (code == LEU || code == LTU || code == GEU
2549 signed_comparison_operator (op, mode)
2551 enum machine_mode mode;
2553 if (mode == VOIDmode || GET_MODE (op) == mode)
2557 code = GET_CODE(op);
2559 if (!(code == LEU || code == LTU || code == GEU