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@world.std.com).
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 struct rtx_def *(*dsp16xx_compare_gen)();
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));
151 /* Initialize the GCC target structure. */
153 struct gcc_target target = TARGET_INITIALIZER;
156 hard_regno_mode_ok (regno, mode)
158 enum machine_mode mode;
166 We can't use the c0-c2 for QImode, since they are only
170 if (regno != REG_C0 && regno != REG_C1 && regno != REG_C2)
175 /* We only allow a0, a1, y, and p to be allocated for 32-bit modes.
176 Additionally we allow the virtual ybase registers to be used for 32-bit
186 if (regno == REG_A0 || regno == REG_A1 || regno == REG_Y || regno == REG_PROD
187 || (IS_YBASE_REGISTER_WINDOW(regno) && ((regno & 1) == 0)))
198 dsp16xx_reg_class_from_letter (c)
207 return ACCUM_HIGH_REGS;
237 return ACCUM_Y_OR_P_REGS;
240 return NO_FRAME_Y_ADDR_REGS;
246 return (TARGET_BMU ? BMU_REGS : NO_REGS);
249 return YBASE_VIRT_REGS;
261 return YBASE_ELIGIBLE_REGS;
264 return ACCUM_LOW_REGS;
267 return NON_YBASE_REGS;
273 return SLOW_MEM_LOAD_REGS;
279 /* Return the class number of the smallest class containing
283 regno_reg_class(regno)
289 return (int) A0L_REG;
291 return (int) A1L_REG;
294 return (int) A0H_REG;
296 return (int) A1H_REG;
311 case REG_R0: case REG_R1: case REG_R2: case REG_R3:
312 return (int) Y_ADDR_REGS;
317 return (int) GENERAL_REGS;
320 return (int) GENERAL_REGS;
323 return (int) GENERAL_REGS;
325 case REG_AR0: case REG_AR1: case REG_AR2: case REG_AR3:
326 return (int) BMU_REGS;
328 case REG_C0: case REG_C1: case REG_C2:
329 return (int) GENERAL_REGS;
332 return (int) GENERAL_REGS;
335 return (int) GENERAL_REGS;
337 case REG_YBASE0: case REG_YBASE1: case REG_YBASE2: case REG_YBASE3:
338 case REG_YBASE4: case REG_YBASE5: case REG_YBASE6: case REG_YBASE7:
339 case REG_YBASE8: case REG_YBASE9: case REG_YBASE10: case REG_YBASE11:
340 case REG_YBASE12: case REG_YBASE13: case REG_YBASE14: case REG_YBASE15:
341 case REG_YBASE16: case REG_YBASE17: case REG_YBASE18: case REG_YBASE19:
342 case REG_YBASE20: case REG_YBASE21: case REG_YBASE22: case REG_YBASE23:
343 case REG_YBASE24: case REG_YBASE25: case REG_YBASE26: case REG_YBASE27:
344 case REG_YBASE28: case REG_YBASE29: case REG_YBASE30: case REG_YBASE31:
345 return (int) YBASE_VIRT_REGS;
348 return (int) NO_REGS;
352 /* A C expression for the maximum number of consecutive registers of class CLASS
353 needed to hold a value of mode MODE */
356 class_max_nregs(class, mode)
357 enum reg_class class ATTRIBUTE_UNUSED;
358 enum machine_mode mode;
360 return (GET_MODE_SIZE(mode));
364 limit_reload_class (mode, class)
365 enum machine_mode mode;
366 enum reg_class class;
377 case ACCUM_HIGH_REGS:
386 if (GET_MODE_SIZE(mode) == 1)
387 return ACCUM_LOW_REGS;
392 case X_OR_ACCUM_LOW_REGS:
395 case X_OR_ACCUM_REGS:
396 if (GET_MODE_SIZE(mode) == 1)
397 return X_OR_ACCUM_LOW_REGS;
404 case YH_OR_ACCUM_HIGH_REGS:
411 /* Register 'yl' is invalid for QImode, so we should never
415 case YL_OR_ACCUM_LOW_REGS:
420 if (GET_MODE_SIZE(mode) > 1)
425 case ACCUM_OR_Y_REGS:
426 if (GET_MODE_SIZE(mode) > 1)
429 return YL_OR_ACCUM_LOW_REGS;
434 case PL_OR_ACCUM_LOW_REGS:
439 if (GET_MODE_SIZE(mode) > 1)
444 case ACCUM_OR_P_REGS:
445 if (GET_MODE_SIZE(mode) > 1)
448 return PL_OR_ACCUM_LOW_REGS;
451 case ACCUM_LOW_OR_YL_OR_P_REGS:
457 case ACCUM_Y_OR_P_REGS:
458 if (GET_MODE_SIZE(mode) > 1)
461 return ACCUM_LOW_OR_YL_OR_P_REGS;
463 case NO_FRAME_Y_ADDR_REGS:
465 case ACCUM_LOW_OR_Y_ADDR_REGS:
468 case ACCUM_OR_Y_ADDR_REGS:
469 if (GET_MODE_SIZE(mode) > 1)
472 return ACCUM_LOW_OR_Y_ADDR_REGS;
474 case X_OR_Y_ADDR_REGS:
477 case Y_OR_Y_ADDR_REGS:
478 case P_OR_Y_ADDR_REGS:
479 case NON_HIGH_YBASE_ELIGIBLE_REGS:
484 case YBASE_ELIGIBLE_REGS:
485 if (GET_MODE_SIZE(mode) > 1)
486 return ACCUM_Y_P_OR_YBASE_REGS;
488 return NON_HIGH_YBASE_ELIGIBLE_REGS;
490 case J_OR_DAU_16_BIT_REGS:
491 if (GET_MODE_SIZE(mode) == 1)
497 case NOHIGH_NON_ADDR_REGS:
501 if (GET_MODE_SIZE(mode) > 1)
504 return NOHIGH_NON_ADDR_REGS;
506 case NOHIGH_NON_YBASE_REGS:
510 if (GET_MODE_SIZE(mode) > 1)
513 return NOHIGH_NON_YBASE_REGS;
515 case YBASE_VIRT_REGS:
516 case ACCUM_LOW_OR_YBASE_REGS:
519 case ACCUM_OR_YBASE_REGS:
520 if (GET_MODE_SIZE(mode) > 1)
523 return ACCUM_LOW_OR_YBASE_REGS;
525 case X_OR_YBASE_REGS:
528 case Y_OR_YBASE_REGS:
529 case ACCUM_LOW_YL_PL_OR_YBASE_REGS:
530 case P_OR_YBASE_REGS:
533 case ACCUM_Y_P_OR_YBASE_REGS:
534 return ACCUM_LOW_YL_PL_OR_YBASE_REGS;
536 case Y_ADDR_OR_YBASE_REGS:
537 case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS:
540 case YBASE_OR_YBASE_ELIGIBLE_REGS:
541 if (GET_MODE_SIZE(mode) > 1)
544 return YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS;
546 case NO_HIGH_ALL_REGS:
550 if (GET_MODE_SIZE(mode) > 1)
553 return NO_HIGH_ALL_REGS;
561 dsp16xx_register_move_cost (from, to)
562 enum reg_class from, to;
565 if (from == NO_REGS || to == NO_REGS || (from == to))
569 if (from == A0H_REG || from == A0L_REG || from == A0_REG ||
570 from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG ||
571 from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS)
573 if (to == Y_REG || to == P_REG)
579 if (to == A0H_REG || to == A0L_REG || to == A0_REG ||
580 to == A1H_REG || to == ACCUM_HIGH_REGS || to == A1L_REG ||
581 to == ACCUM_LOW_REGS || to == A1_REG || to == ACCUM_REGS)
587 if (from == YBASE_VIRT_REGS)
589 if (to == X_REG || to == YH_REG || to == YL_REG ||
590 to == Y_REG || to == PL_REG || to == PH_REG ||
591 to == P_REG || to == Y_ADDR_REGS || to == YBASE_ELIGIBLE_REGS ||
600 if (to == YBASE_VIRT_REGS)
602 if (from == X_REG || from == YH_REG || from == YL_REG ||
603 from == Y_REG || from == PL_REG || from == PH_REG ||
604 from == P_REG || from == Y_ADDR_REGS || from == YBASE_ELIGIBLE_REGS ||
616 /* Given an rtx X being reloaded into a reg required to be
617 in class CLASS, return the class of reg to actually use.
618 In general this is just CLASS; but on some machines
619 in some cases it is preferable to use a more restrictive class.
620 Also, we must ensure that a PLUS is reloaded either
621 into an accumulator or an address register. */
624 preferred_reload_class (x, class)
626 enum reg_class class;
628 /* The ybase registers cannot have constants copied directly
633 if (class == ALL_REGS)
634 return NON_YBASE_REGS;
637 if (class == ALL_REGS && REG_P (x) && !TARGET_RESERVE_YBASE
638 && IS_YBASE_REGISTER_WINDOW (REGNO(x)))
639 return YBASE_ELIGIBLE_REGS;
641 if (GET_CODE (x) == PLUS)
643 if (GET_MODE (x) == QImode
644 && REG_P (XEXP (x,0))
645 && (XEXP (x,0) == frame_pointer_rtx
646 || XEXP (x,0) == stack_pointer_rtx)
647 && (GET_CODE (XEXP (x,1)) == CONST_INT))
649 if (class == ACCUM_HIGH_REGS)
652 if (reg_class_subset_p (ACCUM_HIGH_REGS, class))
653 return ACCUM_HIGH_REGS;
655 /* We will use accumulator 'a1l' for reloading a
656 PLUS. We can only use one accumulator because
657 'reload_inqi' only allows one alternative to be
660 else if (class == ACCUM_LOW_REGS)
662 else if (class == A0L_REG)
668 if (class == NON_YBASE_REGS || class == YBASE_ELIGIBLE_REGS)
673 else if (GET_CODE (x) == MEM)
675 if (class == ALL_REGS)
678 if (GET_MODE(x) == HImode)
679 return NO_ACCUM_NON_YBASE_REGS;
682 return NON_YBASE_REGS;
691 /* Return the register class of a scratch register needed to copy IN into
692 or out of a register in CLASS in MODE. If it can be done directly,
693 NO_REGS is returned. */
696 secondary_reload_class (class, mode, in)
697 enum reg_class class;
698 enum machine_mode mode;
703 if (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
704 regno = true_regnum (in);
706 if (class == ACCUM_HIGH_REGS
707 || class == ACCUM_LOW_REGS
713 if (GET_CODE (in) == PLUS && mode == QImode)
715 rtx addr0 = XEXP (in, 0);
716 rtx addr1 = XEXP (in, 1);
718 /* If we are reloading a plus (reg:QI) (reg:QI)
719 we need an additional register. */
720 if (REG_P (addr0) && REG_P (addr1))
725 /* We can place anything into ACCUM_REGS and can put ACCUM_REGS
728 if ((class == ACCUM_REGS || class == ACCUM_HIGH_REGS ||
729 class == ACCUM_LOW_REGS || class == A0H_REG || class == A0L_REG ||
730 class == A1H_REG || class == A1_REG) ||
731 (regno >= REG_A0 && regno < REG_A1L + 1))
734 /* We can copy the ybase registers into:
735 r0-r3, a0-a1, y, p, & x or the union of
738 if (!TARGET_RESERVE_YBASE && IS_YBASE_REGISTER_WINDOW(regno))
743 case (int) X_OR_ACCUM_LOW_REGS:
744 case (int) X_OR_ACCUM_REGS:
746 case (int) YH_OR_ACCUM_HIGH_REGS:
747 case (int) X_OR_YH_REGS:
749 case (int) YL_OR_ACCUM_LOW_REGS:
750 case (int) X_OR_Y_REGS:
751 case (int) X_OR_YL_REGS:
753 case (int) ACCUM_OR_Y_REGS:
755 case (int) X_OR_PH_REGS:
757 case (int) PL_OR_ACCUM_LOW_REGS:
758 case (int) X_OR_PL_REGS:
759 case (int) YL_OR_PL_OR_ACCUM_LOW_REGS:
761 case (int) ACCUM_OR_P_REGS:
762 case (int) YL_OR_P_REGS:
763 case (int) ACCUM_LOW_OR_YL_OR_P_REGS:
764 case (int) Y_OR_P_REGS:
765 case (int) ACCUM_Y_OR_P_REGS:
766 case (int) Y_ADDR_REGS:
767 case (int) ACCUM_LOW_OR_Y_ADDR_REGS:
768 case (int) ACCUM_OR_Y_ADDR_REGS:
769 case (int) X_OR_Y_ADDR_REGS:
770 case (int) Y_OR_Y_ADDR_REGS:
771 case (int) P_OR_Y_ADDR_REGS:
772 case (int) YBASE_ELIGIBLE_REGS:
776 return ACCUM_HIGH_REGS;
780 /* We can copy r0-r3, a0-a1, y, & p
781 directly to the ybase registers. In addition
782 we can use any of the ybase virtual registers
783 as the secondary reload registers when copying
784 between any of these registers. */
786 if (!TARGET_RESERVE_YBASE && regno != -1)
803 if (class == YBASE_VIRT_REGS)
810 case (int) X_OR_ACCUM_LOW_REGS:
811 case (int) X_OR_ACCUM_REGS:
813 case (int) YH_OR_ACCUM_HIGH_REGS:
814 case (int) X_OR_YH_REGS:
816 case (int) YL_OR_ACCUM_LOW_REGS:
817 case (int) X_OR_Y_REGS:
818 case (int) X_OR_YL_REGS:
820 case (int) ACCUM_OR_Y_REGS:
822 case (int) X_OR_PH_REGS:
824 case (int) PL_OR_ACCUM_LOW_REGS:
825 case (int) X_OR_PL_REGS:
826 case (int) YL_OR_PL_OR_ACCUM_LOW_REGS:
828 case (int) ACCUM_OR_P_REGS:
829 case (int) YL_OR_P_REGS:
830 case (int) ACCUM_LOW_OR_YL_OR_P_REGS:
831 case (int) Y_OR_P_REGS:
832 case (int) ACCUM_Y_OR_P_REGS:
833 case (int) Y_ADDR_REGS:
834 case (int) ACCUM_LOW_OR_Y_ADDR_REGS:
835 case (int) ACCUM_OR_Y_ADDR_REGS:
836 case (int) X_OR_Y_ADDR_REGS:
837 case (int) Y_OR_Y_ADDR_REGS:
838 case (int) P_OR_Y_ADDR_REGS:
839 case (int) YBASE_ELIGIBLE_REGS:
840 return YBASE_VIRT_REGS;
849 /* Memory or constants can be moved from or to any register
850 except the ybase virtual registers */
851 if (regno == -1 && GET_CODE(in) != PLUS)
853 if (class == YBASE_VIRT_REGS)
854 return NON_YBASE_REGS;
859 if (GET_CODE (in) == PLUS && mode == QImode)
861 rtx addr0 = XEXP (in, 0);
862 rtx addr1 = XEXP (in, 1);
864 /* If we are reloading a plus (reg:QI) (reg:QI)
865 we need a low accumulator, not a high one. */
866 if (REG_P (addr0) && REG_P (addr1))
867 return ACCUM_LOW_REGS;
875 /* Otherwise, we need a high accumulator(s). */
876 return ACCUM_HIGH_REGS;
880 symbolic_address_operand (op, mode)
882 enum machine_mode mode ATTRIBUTE_UNUSED;
884 return (symbolic_address_p (op));
888 symbolic_address_p (op)
891 switch (GET_CODE (op))
899 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
900 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
901 && GET_CODE (XEXP (op, 1)) == CONST_INT
902 && INTVAL (XEXP (op,1)) < 0x20);
909 /* For a Y address space operand we allow only *rn, *rn++, *rn--.
910 This routine only recognizes *rn, the '<>' constraints recognize
914 Y_address_operand (op, mode)
916 enum machine_mode mode;
918 return (memory_address_p (mode, op) && !symbolic_address_p (op));
922 sp_operand (op, mode)
924 enum machine_mode mode ATTRIBUTE_UNUSED;
926 return (GET_CODE (op) == PLUS
927 && (XEXP (op, 0) == stack_pointer_rtx
928 || XEXP (op, 0) == frame_pointer_rtx)
929 && GET_CODE (XEXP (op,1)) == CONST_INT);
933 sp_operand2 (op, mode)
935 enum machine_mode mode ATTRIBUTE_UNUSED;
937 if ((GET_CODE (op) == PLUS
938 && (XEXP (op, 0) == stack_pointer_rtx
939 || XEXP (op, 0) == frame_pointer_rtx)
940 && (REG_P (XEXP (op,1))
941 && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1))))))
943 else if ((GET_CODE (op) == PLUS
944 && (XEXP (op, 1) == stack_pointer_rtx
945 || XEXP (op, 1) == frame_pointer_rtx)
946 && (REG_P (XEXP (op,0))
947 && IS_ADDRESS_REGISTER (REGNO (XEXP(op, 1))))))
954 nonmemory_arith_operand (op, mode)
956 enum machine_mode mode;
958 return (immediate_operand (op, mode) || arith_reg_operand (op, mode));
962 arith_reg_operand (op, mode)
964 enum machine_mode mode;
966 return (register_operand (op, mode)
967 && (GET_CODE (op) != REG
968 || REGNO (op) >= FIRST_PSEUDO_REGISTER
969 || (!(IS_YBASE_REGISTER_WINDOW (REGNO (op)))
970 && REGNO (op) != FRAME_POINTER_REGNUM)));
974 call_address_operand (op, mode)
976 enum machine_mode mode ATTRIBUTE_UNUSED;
978 if (symbolic_address_p (op) || REG_P(op))
987 dsp16xx_comparison_operator (op, mode)
989 enum machine_mode mode;
991 return ((mode == VOIDmode || GET_MODE (op) == mode)
992 && GET_RTX_CLASS (GET_CODE (op)) == '<'
993 && (GET_CODE(op) != GE && GET_CODE (op) != LT &&
994 GET_CODE (op) != GEU && GET_CODE (op) != LTU));
998 notice_update_cc(exp)
1001 if (GET_CODE (exp) == SET)
1003 /* Jumps do not alter the cc's. */
1005 if (SET_DEST (exp) == pc_rtx)
1008 /* Moving register or memory into a register:
1009 it doesn't alter the cc's, but it might invalidate
1010 the RTX's which we remember the cc's came from.
1011 (Note that moving a constant 0 or 1 MAY set the cc's). */
1012 if (REG_P (SET_DEST (exp))
1013 && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
1015 if (cc_status.value1
1016 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1))
1017 cc_status.value1 = 0;
1018 if (cc_status.value2
1019 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2))
1020 cc_status.value2 = 0;
1023 /* Moving register into memory doesn't alter the cc's.
1024 It may invalidate the RTX's which we remember the cc's came from. */
1025 if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
1027 if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
1028 cc_status.value1 = 0;
1029 if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
1030 cc_status.value2 = 0;
1033 /* Function calls clobber the cc's. */
1034 else if (GET_CODE (SET_SRC (exp)) == CALL)
1039 /* Tests and compares set the cc's in predictable ways. */
1040 else if (SET_DEST (exp) == cc0_rtx)
1043 cc_status.value1 = SET_SRC (exp);
1046 /* Certain instructions effect the condition codes. */
1047 else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp))) == MODE_INT)
1048 switch( GET_CODE (SET_SRC (exp)) )
1052 if (REG_P (SET_DEST (exp)))
1054 /* Address registers don't set the condition codes */
1055 if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp))))
1070 cc_status.value1 = SET_SRC (exp);
1071 cc_status.value2 = SET_DEST (exp);
1082 else if (GET_CODE (exp) == PARALLEL
1083 && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
1085 if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx)
1088 if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx)
1091 cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0));
1104 dsp16xx_makes_calls ()
1108 for (insn = get_insns (); insn; insn = next_insn (insn))
1109 if (GET_CODE (insn) == CALL_INSN)
1116 compute_frame_size (size)
1128 args_size = current_function_outgoing_args_size;
1129 reg_size = reg_save_size ();
1131 total_size = var_size + args_size + extra_size + reg_size;
1134 /* Save other computed information. */
1135 current_frame_info.total_size = total_size;
1136 current_frame_info.var_size = var_size;
1137 current_frame_info.args_size = args_size;
1138 current_frame_info.extra_size = extra_size;
1139 current_frame_info.reg_size = reg_size;
1140 current_frame_info.initialized = reload_completed;
1141 current_frame_info.reg_size = reg_size / UNITS_PER_WORD;
1142 current_frame_info.function_makes_calls = dsp16xx_makes_calls ();
1146 unsigned long offset = args_size + var_size + reg_size;
1147 current_frame_info.sp_save_offset = offset;
1148 current_frame_info.fp_save_offset = offset - total_size;
1155 dsp16xx_call_saved_register (regno)
1158 return (regs_ever_live[regno] && !call_used_regs[regno] &&
1159 !IS_YBASE_REGISTER_WINDOW(regno));
1164 ybase_regs_ever_used ()
1169 for (regno = REG_YBASE0; regno <= REG_YBASE31; regno++)
1170 if (regs_ever_live[regno])
1180 function_prologue (file, size)
1186 fp = reg_names[FRAME_POINTER_REGNUM];
1187 sp = reg_names[STACK_POINTER_REGNUM];
1188 rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */
1189 a1h = reg_names[REG_A1];
1191 total_size = compute_frame_size (size);
1193 fprintf( file, "\t/* FUNCTION PROLOGUE: */\n" );
1194 fprintf (file, "\t/* total=%ld, vars= %ld, regs= %d, args=%d, extra= %ld */\n",
1195 current_frame_info.total_size,
1196 current_frame_info.var_size,
1197 current_frame_info.reg_size,
1198 current_function_outgoing_args_size,
1199 current_frame_info.extra_size);
1201 fprintf (file, "\t/* fp save offset= %ld, sp save_offset= %ld */\n\n",
1202 current_frame_info.fp_save_offset,
1203 current_frame_info.sp_save_offset);
1204 /* Set up the 'ybase' register window. */
1206 if (ybase_regs_ever_used())
1208 fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]);
1209 if (TARGET_YBASE_HIGH)
1210 fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
1212 fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h);
1213 fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
1217 if (current_frame_info.function_makes_calls)
1218 fprintf( file, "\t*%s++=%s\n", sp, rr ); /* Push return address */
1222 if (current_frame_info.var_size)
1224 if (current_frame_info.var_size == 1)
1225 fprintf (file, "\t*%s++\n", sp);
1226 else if (SMALL_INTVAL (current_frame_info.var_size)
1227 && ((current_frame_info.var_size & 0x8000) == 0))
1228 fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J],
1229 current_frame_info.var_size, sp, reg_names[REG_J]);
1231 error ("Stack size > 32k");
1234 /* Save any registers this function uses, unless they are used in a call,
1235 in which case we don't need to. */
1237 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++ regno)
1238 if (dsp16xx_call_saved_register (regno))
1240 #if OLD_REGISTER_SAVE
1241 fprintf (file, "\t*%s++=%s\n", sp, reg_names[regno]);
1243 fprintf (file, "\tpush(*%s)=%s\n", sp, reg_names[regno]);
1247 if (current_frame_info.args_size)
1249 if (current_frame_info.args_size == 1)
1250 fprintf (file, "\t*%s++\n", sp);
1251 else if (SMALL_INTVAL (current_frame_info.args_size)
1252 && (current_frame_info.args_size & 0x8000) == 0)
1253 fprintf (file, "\t%s=%ld\n\t*%s++%s\n", reg_names[REG_J],
1254 current_frame_info.args_size, sp, reg_names[REG_J]);
1256 error ("Stack size > 32k");
1259 if (frame_pointer_needed)
1261 fprintf (file, "\t%s=%s\n", a1h, sp);
1262 fprintf (file, "\t%s=%s\n", fp, a1h); /* Establish new base frame */
1263 fprintf (file, "\t%s=%ld\n", reg_names[REG_J], -total_size);
1264 fprintf (file, "\t*%s++%s\n", fp, reg_names[REG_J]);
1267 fprintf (file, "\t/* END FUNCTION PROLOGUE: */\n\n");
1271 init_emulation_routines ()
1273 dsp16xx_addhf3_libcall = (rtx) 0;
1274 dsp16xx_subhf3_libcall = (rtx) 0;
1275 dsp16xx_mulhf3_libcall = (rtx) 0;
1276 dsp16xx_divhf3_libcall = (rtx) 0;
1277 dsp16xx_cmphf3_libcall = (rtx) 0;
1278 dsp16xx_fixhfhi2_libcall = (rtx) 0;
1279 dsp16xx_floathihf2_libcall = (rtx) 0;
1280 dsp16xx_neghf2_libcall = (rtx) 0;
1282 dsp16xx_mulhi3_libcall = (rtx) 0;
1283 dsp16xx_udivqi3_libcall = (rtx) 0;
1284 dsp16xx_udivhi3_libcall = (rtx) 0;
1285 dsp16xx_divqi3_libcall = (rtx) 0;
1286 dsp16xx_divhi3_libcall = (rtx) 0;
1287 dsp16xx_modqi3_libcall = (rtx) 0;
1288 dsp16xx_modhi3_libcall = (rtx) 0;
1289 dsp16xx_umodqi3_libcall = (rtx) 0;
1290 dsp16xx_umodhi3_libcall = (rtx) 0;
1291 dsp16xx_ashrhi3_libcall = (rtx) 0;
1292 dsp16xx_ashlhi3_libcall = (rtx) 0;
1293 dsp16xx_ucmphi2_libcall = (rtx) 0;
1294 dsp16xx_lshrhi3_libcall = (rtx) 0;
1298 function_epilogue (file, size)
1300 int size ATTRIBUTE_UNUSED;
1303 #if OLD_REGISTER_SAVE
1304 int initial_stack_dec = 0;
1307 fp = reg_names[FRAME_POINTER_REGNUM];
1308 sp = reg_names[STACK_POINTER_REGNUM];
1309 rr = reg_names[RETURN_ADDRESS_REGNUM]; /* return address register */
1310 a1h = reg_names[REG_A1];
1312 fprintf( file, "\n\t/* FUNCTION EPILOGUE: */\n" );
1314 if (current_frame_info.args_size)
1316 if (current_frame_info.args_size == 1)
1317 fprintf (file, "\t*%s--\n", sp);
1320 fprintf (file, "\t%s=%ld\n\t*%s++%s\n",
1321 reg_names[REG_J], -current_frame_info.args_size, sp, reg_names[REG_J]);
1325 if (ybase_regs_ever_used())
1327 fprintf (file, "\t%s=%s\n", a1h, reg_names[REG_YBASE]);
1328 if (TARGET_YBASE_HIGH)
1329 fprintf (file, "\t%s=%sh+32\n", reg_names[REG_A1], a1h);
1331 fprintf (file, "\t%s=%sh-32\n", reg_names[REG_A1], a1h);
1332 fprintf (file, "\t%s=%s\n", reg_names[REG_YBASE], a1h);
1335 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
1336 if (dsp16xx_call_saved_register(regno))
1338 #if OLD_REGISTER_SAVE
1339 if (!initial_stack_dec)
1341 initial_stack_dec = 1;
1342 fprintf (file, "\t*%s--\n", sp);
1346 #if OLD_REGISTER_SAVE
1347 fprintf( file, "\t%s=*%s--\n", reg_names[regno], sp );
1349 fprintf( file, "\t%s=pop(*%s)\n", reg_names[regno], sp );
1353 /* If we restored any registers we have to account for the
1354 initial pre-decrement. But only if we had any local variables
1356 #if OLD_REGISTER_SAVE
1357 if (initial_stack_dec)
1358 fprintf (file, "\t*%s++\n", sp);
1361 if (current_frame_info.var_size)
1363 if (current_frame_info.var_size == 1)
1364 fprintf (file, "\t*%s--\n", sp);
1367 fprintf (file, "\t%s=%ld\n\t*%s++%s\n",
1368 reg_names[REG_J], -current_frame_info.var_size, sp, reg_names[REG_J]);
1372 fprintf (file, "\treturn\n");
1373 /* Reset the frame info for the next function */
1374 current_frame_info = zero_frame_info;
1375 init_emulation_routines ();
1378 /* Emit insns to move operands[1] into operands[0].
1380 Return 1 if we have written out everything that needs to be done to
1381 do the move. Otherwise, return 0 and the caller will emit the move
1385 emit_move_sequence (operands, mode)
1387 enum machine_mode mode;
1389 register rtx operand0 = operands[0];
1390 register rtx operand1 = operands[1];
1392 /* We can only store registers to memory. */
1394 if (GET_CODE (operand0) == MEM && GET_CODE (operand1) != REG)
1395 operands[1] = force_reg (mode, operand1);
1401 double_reg_from_memory (operands)
1406 if (GET_CODE(XEXP(operands[1],0)) == POST_INC)
1408 output_asm_insn ("%u0=%1", operands);
1409 output_asm_insn ("%w0=%1", operands);
1411 else if (GET_CODE(XEXP(operands[1],0)) == POST_DEC)
1413 xoperands[1] = XEXP (XEXP (operands[1], 0), 0);
1414 xoperands[0] = operands[0];
1416 /* We can't use j anymore since the compiler can allocate it. */
1417 /* output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */
1418 output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands);
1420 else if (GET_CODE(XEXP(operands[1],0)) == PLUS)
1425 output_asm_insn ("%u0=%1", operands);
1428 /* In order to print out the least significant word we must
1429 use 'offset + 1'. */
1430 addr = XEXP (operands[1], 0);
1431 if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1432 offset = INTVAL(XEXP(addr,0)) + 1;
1433 else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1434 offset = INTVAL(XEXP(addr,1)) + 1;
1436 fprintf (asm_out_file, "\t%s=*(%d)\n", reg_names[REGNO(operands[0]) + 1], offset + 31);
1440 xoperands[1] = XEXP(operands[1],0);
1441 xoperands[0] = operands[0];
1443 output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands);
1449 double_reg_to_memory (operands)
1454 if (GET_CODE(XEXP(operands[0],0)) == POST_INC)
1456 output_asm_insn ("%0=%u1", operands);
1457 output_asm_insn ("%0=%w1", operands);
1459 else if (GET_CODE(XEXP(operands[0],0)) == POST_DEC)
1461 xoperands[0] = XEXP (XEXP (operands[0], 0), 0);
1462 xoperands[1] = operands[1];
1464 /* We can't use j anymore since the compiler can allocate it. */
1466 /* output_asm_insn ("j=-3\n\t*%0++=%u1\n\t*%0++j=%w1", xoperands); */
1467 output_asm_insn ("*%0++=%u1\n\t*%0--=%w1\n\t*%0--\n\t*%0--", xoperands);
1470 else if (GET_CODE(XEXP(operands[0],0)) == PLUS)
1475 output_asm_insn ("%0=%u1", operands);
1477 /* In order to print out the least significant word we must
1478 use 'offset + 1'. */
1479 addr = XEXP (operands[0], 0);
1480 if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1481 offset = INTVAL(XEXP(addr,0)) + 1;
1482 else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1483 offset = INTVAL(XEXP(addr,1)) + 1;
1487 fprintf (asm_out_file, "\t*(%d)=%s\n", offset + 31,
1488 reg_names[REGNO(operands[1]) + 1]);
1492 xoperands[0] = XEXP(operands[0],0);
1493 xoperands[1] = operands[1];
1495 output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands);
1504 if (chip_name == (char *) 0)
1505 chip_name = DEFAULT_CHIP_NAME;
1507 if (text_seg_name == (char *) 0)
1508 text_seg_name = DEFAULT_TEXT_SEG_NAME;
1510 if (data_seg_name == (char *) 0)
1511 data_seg_name = DEFAULT_DATA_SEG_NAME;
1513 if (bss_seg_name == (char *) 0)
1514 bss_seg_name = DEFAULT_BSS_SEG_NAME;
1516 if (const_seg_name == (char *) 0)
1517 const_seg_name = DEFAULT_CONST_SEG_NAME;
1519 save_chip_name = xstrdup (chip_name);
1521 rsect_text = tmp = (char *) xmalloc (strlen(".rsect ") +
1522 strlen(text_seg_name) + 3);
1523 sprintf (tmp, ".rsect \"%s\"", text_seg_name);
1525 rsect_data = tmp = (char *) xmalloc (strlen(".rsect ") +
1526 strlen(data_seg_name) + 3);
1527 sprintf (tmp, ".rsect \"%s\"", data_seg_name);
1529 rsect_bss = tmp = (char *) xmalloc (strlen(".rsect ") +
1530 strlen(bss_seg_name) + 3);
1531 sprintf (tmp, ".rsect \"%s\"", bss_seg_name);
1533 rsect_const = tmp = (char *) xmalloc (strlen(".rsect ") +
1534 strlen(const_seg_name) + 3);
1535 sprintf (tmp, ".rsect \"%s\"", const_seg_name);
1539 if (TARGET_OPTIMIZE_SPEED)
1541 flag_unroll_loops = 1;
1542 flag_inline_functions = 1;
1546 /* Mark our global variables for GC. */
1547 ggc_add_rtx_root (&dsp16xx_addhf3_libcall, 1);
1548 ggc_add_rtx_root (&dsp16xx_subhf3_libcall, 1);
1549 ggc_add_rtx_root (&dsp16xx_mulhf3_libcall, 1);
1550 ggc_add_rtx_root (&dsp16xx_divhf3_libcall, 1);
1551 ggc_add_rtx_root (&dsp16xx_cmphf3_libcall, 1);
1552 ggc_add_rtx_root (&dsp16xx_fixhfhi2_libcall, 1);
1553 ggc_add_rtx_root (&dsp16xx_floathihf2_libcall, 1);
1554 ggc_add_rtx_root (&dsp16xx_neghf2_libcall, 1);
1555 ggc_add_rtx_root (&dsp16xx_mulhi3_libcall, 1);
1556 ggc_add_rtx_root (&dsp16xx_udivqi3_libcall, 1);
1557 ggc_add_rtx_root (&dsp16xx_udivhi3_libcall, 1);
1558 ggc_add_rtx_root (&dsp16xx_divqi3_libcall, 1);
1559 ggc_add_rtx_root (&dsp16xx_divhi3_libcall, 1);
1560 ggc_add_rtx_root (&dsp16xx_modqi3_libcall, 1);
1561 ggc_add_rtx_root (&dsp16xx_modhi3_libcall, 1);
1562 ggc_add_rtx_root (&dsp16xx_umodqi3_libcall, 1);
1563 ggc_add_rtx_root (&dsp16xx_umodhi3_libcall, 1);
1564 ggc_add_rtx_root (&dsp16xx_ashrhi3_libcall, 1);
1565 ggc_add_rtx_root (&dsp16xx_ashlhi3_libcall, 1);
1566 ggc_add_rtx_root (&dsp16xx_ucmphi2_libcall, 1);
1567 ggc_add_rtx_root (&dsp16xx_lshrhi3_libcall, 1);
1572 next_cc_user_code (insn)
1575 if ( !(insn = next_cc0_user (insn)))
1577 else if (GET_CODE (insn) == JUMP_INSN
1578 && GET_CODE (PATTERN (insn)) == SET
1579 && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
1580 return GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0));
1581 else if (GET_CODE (insn) == INSN
1582 && GET_CODE (PATTERN (insn)) == SET
1583 && comparison_operator (SET_SRC (PATTERN (insn)), VOIDmode))
1584 return GET_CODE (SET_SRC (PATTERN (insn)));
1590 next_cc_user_unsigned (insn)
1593 switch (next_cc_user_code (insn))
1606 print_operand(file, op, letter)
1613 code = GET_CODE(op);
1618 code = reverse_condition (code);
1627 else if (code == NE)
1632 else if (code == GT || code == GTU)
1637 else if (code == LT || code == LTU)
1642 else if (code == GE || code == GEU)
1647 else if (code == LE || code == LEU)
1662 /* Print the low half of a 32-bit register pair */
1664 fprintf (file, "%s", reg_names[REGNO (op) + 1]);
1665 else if (letter == 'u' || !letter)
1666 fprintf (file, "%s", reg_names[REGNO (op)]);
1667 else if (letter == 'b')
1668 fprintf (file, "%sh", reg_names[REGNO (op)]);
1669 else if (letter == 'm')
1670 fprintf (file, "%s", himode_reg_name[REGNO (op)]);
1672 output_operand_lossgae ("Bad register extension code");
1674 else if (code == MEM)
1675 output_address (XEXP(op,0));
1676 else if (code == CONST_INT)
1678 HOST_WIDE_INT val = INTVAL (op);
1681 fprintf (file, HOST_WIDE_INT_PRINT_HEX, val & 0xffff);
1682 else if (letter == 'h')
1683 fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
1684 else if (letter == 'U')
1685 fprint(f file, HOST_WIDE_INT_PRINT_HEX, (val >> 16) & 0xffff);
1687 output_addr_const (file, op);
1689 else if (code == CONST_DOUBLE && GET_MODE (op) != DImode)
1691 union {double d; int i[2]; } u;
1692 union {float f; int i; } u1;
1694 u.i[0] = CONST_DOUBLE_LOW (op);
1695 u.i[1] = CONST_DOUBLE_HIGH (op);
1697 fprintf (file, "0x%x", u1.i);
1700 output_addr_const (file, op);
1705 print_operand_address(file, addr)
1712 switch (GET_CODE (addr))
1715 fprintf (file, "*%s", reg_names[REGNO (addr)]);
1718 fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]);
1721 fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]);
1724 if (GET_CODE (XEXP(addr,0)) == CONST_INT)
1725 offset = INTVAL(XEXP(addr,0)), base = XEXP(addr,1);
1726 else if (GET_CODE (XEXP(addr,1)) == CONST_INT)
1727 offset = INTVAL(XEXP(addr,1)), base = XEXP(addr,0);
1728 if (GET_CODE (base) == REG && REGNO(base) == STACK_POINTER_REGNUM)
1730 if (offset >= -31 && offset <= 0)
1731 offset = 31 + offset;
1738 fprintf (file, "*(%d)", offset);
1742 if( FITS_5_BITS( addr ) )
1743 fprintf( file, "*(0x%x)", (INTVAL(addr) & 0x20) );
1745 output_addr_const(file, addr);
1750 output_dsp16xx_float_const (operands)
1753 rtx src = operands[1];
1755 #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
1759 REAL_VALUE_FROM_CONST_DOUBLE (d, src);
1760 REAL_VALUE_TO_TARGET_SINGLE (d, value);
1762 operands[1] = GEN_INT (value);
1763 output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands);
1765 fatal_error ("inline float constants not supported on this host");
1772 int reg_save_size = 0;
1775 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1776 if (dsp16xx_call_saved_register (regno))
1778 reg_save_size += UNITS_PER_WORD;
1781 return (reg_save_size);
1785 dsp16xx_starting_frame_offset()
1787 int reg_save_size = 0;
1790 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1791 if (dsp16xx_call_saved_register (regno))
1793 reg_save_size += UNITS_PER_WORD;
1796 return (reg_save_size);
1800 initial_frame_pointer_offset()
1804 offset = compute_frame_size (get_frame_size());
1806 #ifdef STACK_GROWS_DOWNWARD
1813 /* Generate the minimum number of 1600 core shift instructions
1814 to shift by 'shift_amount'. */
1818 emit_1600_core_shift (shift_op, operands, shift_amount, mode)
1819 enum rtx_code shift_op;
1822 enum machine_mode mode;
1826 int first_shift_emitted = 0;
1828 while (shift_amount != 0)
1830 if (shift_amount/16)
1832 quotient = shift_amount/16;
1833 shift_amount = shift_amount - (quotient * 16);
1834 for (i = 0; i < quotient; i++)
1835 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1836 gen_rtx (shift_op, mode,
1838 ? operands[0] : operands[1],
1840 first_shift_emitted = 1;
1842 else if (shift_amount/8)
1844 quotient = shift_amount/8;
1845 shift_amount = shift_amount - (quotient * 8);
1846 for (i = 0; i < quotient; i++)
1847 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1848 gen_rtx (shift_op, mode,
1850 ? operands[0] : operands[1],
1852 first_shift_emitted = 1;
1854 else if (shift_amount/4)
1856 quotient = shift_amount/4;
1857 shift_amount = shift_amount - (quotient * 4);
1858 for (i = 0; i < quotient; i++)
1859 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1860 gen_rtx (shift_op, mode,
1862 ? operands[0] : operands[1],
1864 first_shift_emitted = 1;
1866 else if (shift_amount/1)
1868 quotient = shift_amount/1;
1869 shift_amount = shift_amount - (quotient * 1);
1870 for (i = 0; i < quotient; i++)
1871 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
1872 gen_rtx (shift_op, mode,
1874 ? operands[0] : operands[1],
1876 first_shift_emitted = 1;
1882 emit_1600_core_shift (shift_op, operands, shift_amount)
1883 enum rtx_code shift_op;
1889 int first_shift_emitted = 0;
1890 const char * const *shift_asm_ptr;
1891 const char * const *shift_asm_ptr_first;
1893 if (shift_op == ASHIFT)
1895 shift_asm_ptr = ashift_left_asm;
1896 shift_asm_ptr_first = ashift_left_asm_first;
1898 else if (shift_op == ASHIFTRT)
1900 shift_asm_ptr = ashift_right_asm;
1901 shift_asm_ptr_first = ashift_right_asm_first;
1903 else if (shift_op == LSHIFTRT)
1905 shift_asm_ptr = lshift_right_asm;
1906 shift_asm_ptr_first = lshift_right_asm_first;
1911 while (shift_amount != 0)
1913 if (shift_amount/16)
1915 quotient = shift_amount/16;
1916 shift_amount = shift_amount - (quotient * 16);
1917 for (i = 0; i < quotient; i++)
1918 output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_16]
1919 : shift_asm_ptr_first[SHIFT_INDEX_16]), operands);
1920 first_shift_emitted = 1;
1922 else if (shift_amount/8)
1924 quotient = shift_amount/8;
1925 shift_amount = shift_amount - (quotient * 8);
1926 for (i = 0; i < quotient; i++)
1927 output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_8]
1928 : shift_asm_ptr_first[SHIFT_INDEX_8]), operands);
1929 first_shift_emitted = 1;
1931 else if (shift_amount/4)
1933 quotient = shift_amount/4;
1934 shift_amount = shift_amount - (quotient * 4);
1935 for (i = 0; i < quotient; i++)
1936 output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_4]
1937 : shift_asm_ptr_first[SHIFT_INDEX_4]), operands);
1938 first_shift_emitted = 1;
1940 else if (shift_amount/1)
1942 quotient = shift_amount/1;
1943 shift_amount = shift_amount - (quotient * 1);
1944 for (i = 0; i < quotient; i++)
1945 output_asm_insn ((first_shift_emitted ? shift_asm_ptr[SHIFT_INDEX_1]
1946 : shift_asm_ptr_first[SHIFT_INDEX_1]), operands);
1947 first_shift_emitted = 1;
1953 asm_output_common(file, name, size, rounded)
1956 int size ATTRIBUTE_UNUSED;
1960 ASM_GLOBALIZE_LABEL (file, name);
1961 assemble_name (file, name);
1964 fprintf (file, "%d * int\n", rounded);
1966 fprintf (file, "int\n");
1970 asm_output_local(file, name, size, rounded)
1973 int size ATTRIBUTE_UNUSED;
1977 assemble_name (file, name);
1980 fprintf (file, "%d * int\n", rounded);
1982 fprintf (file, "int\n");
1986 asm_output_float (file, fp_const)
1990 #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
1991 REAL_VALUE_TYPE d = fp_const;
1994 REAL_VALUE_TO_TARGET_SINGLE (d, value);
1995 fputs ("\tint ", file);
1996 #ifdef WORDS_BIG_ENDIAN
1997 fprintf (file, "0x%-4.4lx, 0x%-4.4lx", (value >> 16) & 0xffff,
2000 fprintf (file, "0x%-4.4lx, 0x%-4.4lx", value & 0xffff,
2001 (value >> 16) & 0xffff);
2005 fatal_error ("inline float constants not supported on this host");
2010 asm_output_long (file, value)
2014 fputs ("\tint ", file);
2015 #ifdef WORDS_BIG_ENDIAN
2016 fprintf (file, "0x%-4.4lx, 0x%-4.4lx", (value >> 16) & 0xffff, (value & 0xffff));
2018 fprintf (file, "0x%-4.4lx, 0x%-4.4lx", (value & 0xffff), (value >> 16) & 0xffff);
2024 dsp16xx_address_cost (addr)
2027 switch (GET_CODE (addr))
2037 rtx offset = const0_rtx;
2038 addr = eliminate_constant_term (addr, &offset);
2040 if (GET_CODE (addr) == LABEL_REF)
2043 if (GET_CODE (addr) != SYMBOL_REF)
2046 if (INTVAL (offset) == 0)
2051 case POST_INC: case POST_DEC:
2052 return (GET_MODE (addr) == QImode ? 1 : 2);
2054 case SYMBOL_REF: case LABEL_REF:
2059 register rtx plus0 = XEXP (addr, 0);
2060 register rtx plus1 = XEXP (addr, 1);
2062 if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
2064 plus0 = XEXP (addr, 1);
2065 plus1 = XEXP (addr, 0);
2068 if (GET_CODE (plus0) != REG)
2071 switch (GET_CODE (plus1))
2082 return dsp16xx_address_cost (plus1) + 1;
2091 /* Determine whether a function argument is passed in a register, and
2094 The arguments are CUM, which summarizes all the previous
2095 arguments; MODE, the machine mode of the argument; TYPE,
2096 the data type of the argument as a tree node or 0 if that is not known
2097 (which happens for C support library functions); and NAMED,
2098 which is 1 for an ordinary argument and 0 for nameless arguments that
2099 correspond to `...' in the called function's prototype.
2101 The value of the expression should either be a `reg' RTX for the
2102 hard register in which to pass the argument, or zero to pass the
2103 argument on the stack.
2105 On the dsp1610 the first four words of args are normally in registers
2106 and the rest are pushed. If we a long or on float mode, the argument
2107 must begin on a even register boundary
2109 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2110 For structures that are passed in memory, but could have been
2111 passed in registers, we first load the structure into the
2112 register, and then when the last argument is passed, we store
2113 the registers into the stack locations. This fixes some bugs
2114 where GCC did not expect to have register arguments, followed */
2118 dsp16xx_function_arg (args_so_far, mode, type, named)
2119 CUMULATIVE_ARGS args_so_far;
2120 enum machine_mode mode;
2126 if ((args_so_far & 1) != 0
2127 && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
2130 if (named && args_so_far < 4 && !MUST_PASS_IN_STACK (mode,type))
2131 return gen_rtx_REG (mode, args_so_far + FIRST_REG_FOR_FUNCTION_ARG);
2133 return (struct rtx_def *) 0;
2136 return (struct rtx_def *) 0;
2139 /* Advance the argument to the next argument position. */
2142 dsp16xx_function_arg_advance (cum, mode, type, named)
2143 CUMULATIVE_ARGS *cum; /* current arg information */
2144 enum machine_mode mode; /* current arg mode */
2145 tree type; /* type of the argument or 0 if lib support */
2146 int named ATTRIBUTE_UNUSED;/* whether or not the argument was named */
2151 && (mode == HImode || GET_MODE_CLASS(mode) == MODE_FLOAT))
2154 if (mode != BLKmode)
2155 *cum += GET_MODE_SIZE (mode);
2157 *cum += int_size_in_bytes (type);
2162 dsp16xx_file_start ()
2164 fprintf (asm_out_file, "#include <%s.h>\n", save_chip_name);
2167 fprintf (asm_out_file, "#include <1610.h>\n");
2175 enum machine_mode mode;
2177 mode = GET_MODE (x);
2180 emit_insn (gen_rtx_PARALLEL
2182 gen_rtvec (2, gen_rtx_SET (VOIDmode, cc0_rtx, x),
2183 gen_rtx_CLOBBER (VOIDmode,
2184 gen_rtx_SCRATCH (QImode)))));
2185 else if (mode == HImode)
2186 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx, x));
2194 gen_compare_reg (code, x, y)
2198 enum machine_mode mode;
2200 mode = GET_MODE (x);
2201 /* For floating point compare insns, a call is generated so don't
2202 do anything here. */
2204 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
2209 if (code == GTU || code == GEU
2210 || code == LTU || code == LEU)
2212 emit_insn (gen_rtx_PARALLEL
2215 gen_rtx_SET (VOIDmode, cc0_rtx,
2216 gen_rtx_COMPARE (mode, x, y)),
2217 gen_rtx_CLOBBER (VOIDmode,
2218 gen_rtx_SCRATCH (QImode)),
2219 gen_rtx_CLOBBER (VOIDmode,
2220 gen_rtx_SCRATCH (QImode)))));
2224 emit_insn (gen_rtx_PARALLEL
2226 gen_rtvec (3, gen_rtx_SET (VOIDmode, cc0_rtx,
2227 gen_rtx_COMPARE (mode, x, y)),
2228 gen_rtx_CLOBBER (VOIDmode,
2229 gen_rtx_SCRATCH (QImode)),
2230 gen_rtx_CLOBBER (VOIDmode,
2231 gen_rtx_SCRATCH (QImode)))));
2234 else if (mode == HImode)
2236 if (code == GTU || code == GEU
2237 || code == LTU || code == LEU)
2240 emit_insn (gen_rtx_PARALLEL
2243 gen_rtx_SET (VOIDmode, cc0_rtx,
2244 gen_rtx_COMPARE (VOIDmode,
2246 gen_rtx_CLOBBER (VOIDmode,
2247 gen_rtx_SCRATCH (QImode)),
2248 gen_rtx_CLOBBER (VOIDmode,
2249 gen_rtx_SCRATCH (QImode)),
2250 gen_rtx_CLOBBER (VOIDmode,
2251 gen_rtx_SCRATCH (QImode)),
2252 gen_rtx_CLOBBER (VOIDmode,
2253 gen_rtx_SCRATCH (QImode)))));
2255 if (!dsp16xx_ucmphi2_libcall)
2256 dsp16xx_ucmphi2_libcall = gen_rtx_SYMBOL_REF (Pmode, UCMPHI2_LIBCALL);
2257 emit_library_call (dsp16xx_ucmphi2_libcall, 1, HImode, 2,
2258 x, HImode, y, HImode);
2259 emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode))));
2263 emit_insn (gen_rtx_SET (VOIDmode, cc0_rtx,
2264 gen_rtx_COMPARE (VOIDmode,
2265 force_reg (HImode, x),
2266 force_reg (HImode,y))));
2275 output_block_move (operands)
2278 int loop_count = INTVAL(operands[2]);
2281 fprintf (asm_out_file, "\tdo %d {\n", loop_count);
2282 xoperands[0] = operands[4];
2283 xoperands[1] = operands[1];
2284 output_asm_insn ("%0=*%1++", xoperands);
2286 xoperands[0] = operands[0];
2287 xoperands[1] = operands[4];
2288 output_asm_insn ("*%0++=%1", xoperands);
2290 fprintf (asm_out_file, "\t}\n");