1 /* Subroutines for assembler code output on the DSP1610.
2 Copyright (C) 1994, 1995 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"
31 #include "insn-flags.h"
33 #include "insn-attr.h"
50 /* Save the operands of a compare. The 16xx has not lt or gt, so
51 in these cases we swap the operands and reverse the condition */
53 rtx dsp16xx_compare_op0
;
54 rtx dsp16xx_compare_op1
;
55 struct rtx_def
*(*dsp16xx_compare_gen
)();
62 struct dsp16xx_frame_info current_frame_info
;
63 struct dsp16xx_frame_info zero_frame_info
;
65 rtx dsp16xx_addhf3_libcall
= (rtx
) 0;
66 rtx dsp16xx_subhf3_libcall
= (rtx
) 0;
67 rtx dsp16xx_mulhf3_libcall
= (rtx
) 0;
68 rtx dsp16xx_divhf3_libcall
= (rtx
) 0;
69 rtx dsp16xx_cmphf3_libcall
= (rtx
) 0;
70 rtx dsp16xx_fixhfhi2_libcall
= (rtx
) 0;
71 rtx dsp16xx_floathihf2_libcall
= (rtx
) 0;
72 rtx dsp16xx_neghf2_libcall
= (rtx
) 0;
74 rtx dsp16xx_mulhi3_libcall
= (rtx
) 0;
75 rtx dsp16xx_udivqi3_libcall
= (rtx
) 0;
76 rtx dsp16xx_udivhi3_libcall
= (rtx
) 0;
77 rtx dsp16xx_divqi3_libcall
= (rtx
) 0;
78 rtx dsp16xx_divhi3_libcall
= (rtx
) 0;
79 rtx dsp16xx_modqi3_libcall
= (rtx
) 0;
80 rtx dsp16xx_modhi3_libcall
= (rtx
) 0;
81 rtx dsp16xx_umodqi3_libcall
= (rtx
) 0;
82 rtx dsp16xx_umodhi3_libcall
= (rtx
) 0;
83 rtx dsp16xx_ashrhi3_libcall
= (rtx
) 0;
84 rtx dsp16xx_ashlhi3_libcall
= (rtx
) 0;
85 rtx dsp16xx_ucmphi2_libcall
= (rtx
) 0;
86 rtx dsp16xx_lshrhi3_libcall
= (rtx
) 0;
88 char *himode_reg_name
[] = HIMODE_REGISTER_NAMES
;
90 #define SHIFT_INDEX_1 0
91 #define SHIFT_INDEX_4 1
92 #define SHIFT_INDEX_8 2
93 #define SHIFT_INDEX_16 3
95 static char *ashift_right_asm
[] =
103 static char *ashift_right_asm_first
[] =
111 static char *ashift_left_asm
[] =
119 static char *ashift_left_asm_first
[] =
127 static char *lshift_right_asm
[] =
129 "%0=%0>>1\n\t%0=%b0&0x7fff",
130 "%0=%0>>4\n\t%0=%b0&0x0fff",
131 "%0=%0>>8\n\t%0=%b0&0x00ff",
132 "%0=%0>>16\n\t%0=%b0&0x0000"
135 static char *lshift_right_asm_first
[] =
137 "%0=%1>>1\n\t%0=%b0&0x7fff",
138 "%0=%1>>4\n\t%0=%b0&0x0fff",
139 "%0=%1>>8\n\t%0=%b0&0x00ff",
140 "%0=%1>>16\n\t%0=%b0&0x0000"
144 hard_regno_mode_ok (regno
, mode
)
146 enum machine_mode mode
;
154 We can't use the c0-c2 for QImode, since they are only
158 if (regno
!= REG_C0
&& regno
!= REG_C1
&& regno
!= REG_C2
)
163 /* We only allow a0, a1, y, and p to be allocated for 32-bit modes.
164 Additionally we allow the virtual ybase registers to be used for 32-bit
174 if (regno
== REG_A0
|| regno
== REG_A1
|| regno
== REG_Y
|| regno
== REG_PROD
175 || (IS_YBASE_REGISTER_WINDOW(regno
) && ((regno
& 1) == 0)))
186 dsp16xx_reg_class_from_letter (c
)
195 return ACCUM_HIGH_REGS
;
225 return ACCUM_Y_OR_P_REGS
;
228 return NO_FRAME_Y_ADDR_REGS
;
234 return (TARGET_BMU
? BMU_REGS
: NO_REGS
);
237 return YBASE_VIRT_REGS
;
249 return YBASE_ELIGIBLE_REGS
;
252 return ACCUM_LOW_REGS
;
255 return NON_YBASE_REGS
;
261 return SLOW_MEM_LOAD_REGS
;
264 fatal ("Invalid register class letter %c", c
);
268 /* Return the class number of the smallest class containing
272 regno_reg_class(regno
)
278 return (int) A0L_REG
;
280 return (int) A1L_REG
;
283 return (int) A0H_REG
;
285 return (int) A1H_REG
;
300 case REG_R0
: case REG_R1
: case REG_R2
: case REG_R3
:
301 return (int) Y_ADDR_REGS
;
306 return (int) GENERAL_REGS
;
309 return (int) GENERAL_REGS
;
312 return (int) GENERAL_REGS
;
314 case REG_AR0
: case REG_AR1
: case REG_AR2
: case REG_AR3
:
315 return (int) BMU_REGS
;
317 case REG_C0
: case REG_C1
: case REG_C2
:
318 return (int) GENERAL_REGS
;
321 return (int) GENERAL_REGS
;
324 return (int) GENERAL_REGS
;
326 case REG_YBASE0
: case REG_YBASE1
: case REG_YBASE2
: case REG_YBASE3
:
327 case REG_YBASE4
: case REG_YBASE5
: case REG_YBASE6
: case REG_YBASE7
:
328 case REG_YBASE8
: case REG_YBASE9
: case REG_YBASE10
: case REG_YBASE11
:
329 case REG_YBASE12
: case REG_YBASE13
: case REG_YBASE14
: case REG_YBASE15
:
330 case REG_YBASE16
: case REG_YBASE17
: case REG_YBASE18
: case REG_YBASE19
:
331 case REG_YBASE20
: case REG_YBASE21
: case REG_YBASE22
: case REG_YBASE23
:
332 case REG_YBASE24
: case REG_YBASE25
: case REG_YBASE26
: case REG_YBASE27
:
333 case REG_YBASE28
: case REG_YBASE29
: case REG_YBASE30
: case REG_YBASE31
:
334 return (int) YBASE_VIRT_REGS
;
337 return (int) NO_REGS
;
341 /* A C expression for the maximum number of consecutive registers of class CLASS
342 needed to hold a value of mode MODE */
345 class_max_nregs(class, mode
)
346 enum reg_class
class;
347 enum machine_mode mode
;
349 return (GET_MODE_SIZE(mode
));
353 limit_reload_class (mode
, class)
354 enum machine_mode mode
;
355 enum reg_class
class;
366 case ACCUM_HIGH_REGS
:
367 fatal ("ACCUM_HIGH_REGS class in limit_reload_class");
375 if (GET_MODE_SIZE(mode
) == 1)
376 return ACCUM_LOW_REGS
;
381 case X_OR_ACCUM_LOW_REGS
:
384 case X_OR_ACCUM_REGS
:
385 if (GET_MODE_SIZE(mode
) == 1)
386 return X_OR_ACCUM_LOW_REGS
;
393 case YH_OR_ACCUM_HIGH_REGS
:
394 fatal ("YH_OR_ACCUM_HIGH_REGS found in limit_reload_class");
400 /* Register 'yl' is invalid for QImode, so we should never
403 fatal ("YL found in limit_reload_class");
405 case YL_OR_ACCUM_LOW_REGS
:
410 if (GET_MODE_SIZE(mode
) > 1)
415 case ACCUM_OR_Y_REGS
:
416 if (GET_MODE_SIZE(mode
) > 1)
419 return YL_OR_ACCUM_LOW_REGS
;
424 case PL_OR_ACCUM_LOW_REGS
:
429 if (GET_MODE_SIZE(mode
) > 1)
434 case ACCUM_OR_P_REGS
:
435 if (GET_MODE_SIZE(mode
) > 1)
438 return PL_OR_ACCUM_LOW_REGS
;
441 case ACCUM_LOW_OR_YL_OR_P_REGS
:
447 case ACCUM_Y_OR_P_REGS
:
448 if (GET_MODE_SIZE(mode
) > 1)
451 return ACCUM_LOW_OR_YL_OR_P_REGS
;
453 case NO_FRAME_Y_ADDR_REGS
:
455 case ACCUM_LOW_OR_Y_ADDR_REGS
:
458 case ACCUM_OR_Y_ADDR_REGS
:
459 if (GET_MODE_SIZE(mode
) > 1)
462 return ACCUM_LOW_OR_Y_ADDR_REGS
;
464 case X_OR_Y_ADDR_REGS
:
467 case Y_OR_Y_ADDR_REGS
:
468 case P_OR_Y_ADDR_REGS
:
469 case NON_HIGH_YBASE_ELIGIBLE_REGS
:
474 case YBASE_ELIGIBLE_REGS
:
475 if (GET_MODE_SIZE(mode
) > 1)
476 return ACCUM_Y_P_OR_YBASE_REGS
;
478 return NON_HIGH_YBASE_ELIGIBLE_REGS
;
480 case J_OR_DAU_16_BIT_REGS
:
481 if (GET_MODE_SIZE(mode
) == 1)
487 case NOHIGH_NON_ADDR_REGS
:
491 if (GET_MODE_SIZE(mode
) > 1)
494 return NOHIGH_NON_ADDR_REGS
;
496 case NOHIGH_NON_YBASE_REGS
:
500 if (GET_MODE_SIZE(mode
) > 1)
503 return NOHIGH_NON_YBASE_REGS
;
505 case YBASE_VIRT_REGS
:
506 case ACCUM_LOW_OR_YBASE_REGS
:
509 case ACCUM_OR_YBASE_REGS
:
510 if (GET_MODE_SIZE(mode
) > 1)
513 return ACCUM_LOW_OR_YBASE_REGS
;
515 case X_OR_YBASE_REGS
:
518 case Y_OR_YBASE_REGS
:
519 case ACCUM_LOW_YL_PL_OR_YBASE_REGS
:
520 case P_OR_YBASE_REGS
:
523 case ACCUM_Y_P_OR_YBASE_REGS
:
524 return ACCUM_LOW_YL_PL_OR_YBASE_REGS
;
526 case Y_ADDR_OR_YBASE_REGS
:
527 case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS
:
530 case YBASE_OR_YBASE_ELIGIBLE_REGS
:
531 if (GET_MODE_SIZE(mode
) > 1)
534 return YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS
;
536 case NO_HIGH_ALL_REGS
:
540 if (GET_MODE_SIZE(mode
) > 1)
543 return NO_HIGH_ALL_REGS
;
551 dsp16xx_register_move_cost (from
, to
)
552 enum reg_class from
, to
;
555 if (from
== NO_REGS
|| to
== NO_REGS
|| (from
== to
))
559 if (from
== A0H_REG
|| from
== A0L_REG
|| from
== A0_REG
||
560 from
== A1H_REG
|| from
== ACCUM_HIGH_REGS
|| from
== A1L_REG
||
561 from
== ACCUM_LOW_REGS
|| from
== A1_REG
|| from
== ACCUM_REGS
)
563 if (to
== Y_REG
|| to
== P_REG
)
569 if (to
== A0H_REG
|| to
== A0L_REG
|| to
== A0_REG
||
570 to
== A1H_REG
|| to
== ACCUM_HIGH_REGS
|| to
== A1L_REG
||
571 to
== ACCUM_LOW_REGS
|| to
== A1_REG
|| to
== ACCUM_REGS
)
577 if (from
== YBASE_VIRT_REGS
)
579 if (to
== X_REG
|| to
== YH_REG
|| to
== YL_REG
||
580 to
== Y_REG
|| to
== PL_REG
|| to
== PH_REG
||
581 to
== P_REG
|| to
== Y_ADDR_REGS
|| to
== YBASE_ELIGIBLE_REGS
||
590 if (to
== YBASE_VIRT_REGS
)
592 if (from
== X_REG
|| from
== YH_REG
|| from
== YL_REG
||
593 from
== Y_REG
|| from
== PL_REG
|| from
== PH_REG
||
594 from
== P_REG
|| from
== Y_ADDR_REGS
|| from
== YBASE_ELIGIBLE_REGS
||
606 /* Given an rtx X being reloaded into a reg required to be
607 in class CLASS, return the class of reg to actually use.
608 In general this is just CLASS; but on some machines
609 in some cases it is preferable to use a more restrictive class.
610 Also, we must ensure that a PLUS is reloaded either
611 into an accumulator or an address register. */
614 preferred_reload_class (x
, class)
616 enum reg_class
class;
618 /* The ybase registers cannot have constants copied directly
623 if (class == ALL_REGS
)
624 return NON_YBASE_REGS
;
627 if (class == ALL_REGS
&& REG_P (x
) && !TARGET_RESERVE_YBASE
628 && IS_YBASE_REGISTER_WINDOW (REGNO(x
)))
629 return YBASE_ELIGIBLE_REGS
;
631 if (GET_CODE (x
) == PLUS
)
633 if (GET_MODE (x
) == QImode
634 && REG_P (XEXP (x
,0))
635 && (XEXP (x
,0) == frame_pointer_rtx
636 || XEXP (x
,0) == stack_pointer_rtx
)
637 && (GET_CODE (XEXP (x
,1)) == CONST_INT
))
639 if (class == ACCUM_HIGH_REGS
)
642 if (reg_class_subset_p (ACCUM_HIGH_REGS
, class))
643 return ACCUM_HIGH_REGS
;
645 /* We will use accumulator 'a1l' for reloading a
646 PLUS. We can only use one accumulator because
647 'reload_inqi' only allows one alternative to be
650 else if (class == ACCUM_LOW_REGS
)
652 else if (class == A0L_REG
)
658 if (class == NON_YBASE_REGS
|| class == YBASE_ELIGIBLE_REGS
)
663 else if (GET_CODE (x
) == MEM
)
665 if (class == ALL_REGS
)
668 if (GET_MODE(x
) == HImode
)
669 return NO_ACCUM_NON_YBASE_REGS
;
672 return NON_YBASE_REGS
;
681 /* Return the register class of a scratch register needed to copy IN into
682 or out of a register in CLASS in MODE. If it can be done directly,
683 NO_REGS is returned. */
686 secondary_reload_class (class, mode
, in
)
687 enum reg_class
class;
688 enum machine_mode mode
;
693 if (GET_CODE (in
) == REG
|| GET_CODE (in
) == SUBREG
)
694 regno
= true_regnum (in
);
696 if (class == ACCUM_HIGH_REGS
697 || class == ACCUM_LOW_REGS
703 if (GET_CODE (in
) == PLUS
&& mode
== QImode
)
705 rtx addr0
= XEXP (in
, 0);
706 rtx addr1
= XEXP (in
, 1);
708 /* If we are reloading a plus (reg:QI) (reg:QI)
709 we need an additional register. */
710 if (REG_P (addr0
) && REG_P (addr1
))
715 /* We can place anything into ACCUM_REGS and can put ACCUM_REGS
718 if ((class == ACCUM_REGS
|| class == ACCUM_HIGH_REGS
||
719 class == ACCUM_LOW_REGS
|| class == A0H_REG
|| class == A0L_REG
||
720 class == A1H_REG
|| class == A1_REG
) ||
721 (regno
>= REG_A0
&& regno
< REG_A1L
+ 1))
724 /* We can copy the ybase registers into:
725 r0-r3, a0-a1, y, p, & x or the union of
728 if (!TARGET_RESERVE_YBASE
&& IS_YBASE_REGISTER_WINDOW(regno
))
733 case (int) X_OR_ACCUM_LOW_REGS
:
734 case (int) X_OR_ACCUM_REGS
:
736 case (int) YH_OR_ACCUM_HIGH_REGS
:
737 case (int) X_OR_YH_REGS
:
739 case (int) YL_OR_ACCUM_LOW_REGS
:
740 case (int) X_OR_Y_REGS
:
741 case (int) X_OR_YL_REGS
:
743 case (int) ACCUM_OR_Y_REGS
:
745 case (int) X_OR_PH_REGS
:
747 case (int) PL_OR_ACCUM_LOW_REGS
:
748 case (int) X_OR_PL_REGS
:
749 case (int) YL_OR_PL_OR_ACCUM_LOW_REGS
:
751 case (int) ACCUM_OR_P_REGS
:
752 case (int) YL_OR_P_REGS
:
753 case (int) ACCUM_LOW_OR_YL_OR_P_REGS
:
754 case (int) Y_OR_P_REGS
:
755 case (int) ACCUM_Y_OR_P_REGS
:
756 case (int) Y_ADDR_REGS
:
757 case (int) ACCUM_LOW_OR_Y_ADDR_REGS
:
758 case (int) ACCUM_OR_Y_ADDR_REGS
:
759 case (int) X_OR_Y_ADDR_REGS
:
760 case (int) Y_OR_Y_ADDR_REGS
:
761 case (int) P_OR_Y_ADDR_REGS
:
762 case (int) YBASE_ELIGIBLE_REGS
:
766 return ACCUM_HIGH_REGS
;
770 /* We can copy r0-r3, a0-a1, y, & p
771 directly to the ybase registers. In addition
772 we can use any of the ybase virtual registers
773 as the secondary reload registers when copying
774 between any of these registers. */
776 if (!TARGET_RESERVE_YBASE
&& regno
!= -1)
793 if (class == YBASE_VIRT_REGS
)
800 case (int) X_OR_ACCUM_LOW_REGS
:
801 case (int) X_OR_ACCUM_REGS
:
803 case (int) YH_OR_ACCUM_HIGH_REGS
:
804 case (int) X_OR_YH_REGS
:
806 case (int) YL_OR_ACCUM_LOW_REGS
:
807 case (int) X_OR_Y_REGS
:
808 case (int) X_OR_YL_REGS
:
810 case (int) ACCUM_OR_Y_REGS
:
812 case (int) X_OR_PH_REGS
:
814 case (int) PL_OR_ACCUM_LOW_REGS
:
815 case (int) X_OR_PL_REGS
:
816 case (int) YL_OR_PL_OR_ACCUM_LOW_REGS
:
818 case (int) ACCUM_OR_P_REGS
:
819 case (int) YL_OR_P_REGS
:
820 case (int) ACCUM_LOW_OR_YL_OR_P_REGS
:
821 case (int) Y_OR_P_REGS
:
822 case (int) ACCUM_Y_OR_P_REGS
:
823 case (int) Y_ADDR_REGS
:
824 case (int) ACCUM_LOW_OR_Y_ADDR_REGS
:
825 case (int) ACCUM_OR_Y_ADDR_REGS
:
826 case (int) X_OR_Y_ADDR_REGS
:
827 case (int) Y_OR_Y_ADDR_REGS
:
828 case (int) P_OR_Y_ADDR_REGS
:
829 case (int) YBASE_ELIGIBLE_REGS
:
830 return YBASE_VIRT_REGS
;
839 /* Memory or constants can be moved from or to any register
840 except the ybase virtual registers */
841 if (regno
== -1 && GET_CODE(in
) != PLUS
)
843 if (class == YBASE_VIRT_REGS
)
844 return NON_YBASE_REGS
;
849 if (GET_CODE (in
) == PLUS
&& mode
== QImode
)
851 rtx addr0
= XEXP (in
, 0);
852 rtx addr1
= XEXP (in
, 1);
854 /* If we are reloading a plus (reg:QI) (reg:QI)
855 we need a low accumulator, not a high one. */
856 if (REG_P (addr0
) && REG_P (addr1
))
857 return ACCUM_LOW_REGS
;
865 /* Otherwise, we need a high accumulator(s). */
866 return ACCUM_HIGH_REGS
;
870 symbolic_address_operand (op
, mode
)
872 enum machine_mode mode
;
874 return (symbolic_address_p (op
));
878 int symbolic_address_p (op
)
881 switch (GET_CODE (op
))
889 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
890 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
891 && GET_CODE (XEXP (op
, 1)) == CONST_INT
892 && INTVAL (XEXP (op
,1)) < 0x20);
899 /* For a Y address space operand we allow only *rn, *rn++, *rn--.
900 This routine only recognizes *rn, the '<>' constraints recognize
904 Y_address_operand (op
, mode
)
906 enum machine_mode mode
;
908 return (memory_address_p (mode
, op
) && !symbolic_address_p (op
));
912 sp_operand (op
, mode
)
914 enum machine_mode mode
;
916 return (GET_CODE (op
) == PLUS
917 && (XEXP (op
, 0) == stack_pointer_rtx
918 || XEXP (op
, 0) == frame_pointer_rtx
)
919 && GET_CODE (XEXP (op
,1)) == CONST_INT
);
923 sp_operand2 (op
, mode
)
925 enum machine_mode mode
;
927 if ((GET_CODE (op
) == PLUS
928 && (XEXP (op
, 0) == stack_pointer_rtx
929 || XEXP (op
, 0) == frame_pointer_rtx
)
930 && (REG_P (XEXP (op
,1))
931 && IS_ADDRESS_REGISTER (REGNO (XEXP(op
, 1))))))
933 else if ((GET_CODE (op
) == PLUS
934 && (XEXP (op
, 1) == stack_pointer_rtx
935 || XEXP (op
, 1) == frame_pointer_rtx
)
936 && (REG_P (XEXP (op
,0))
937 && IS_ADDRESS_REGISTER (REGNO (XEXP(op
, 1))))))
944 nonmemory_arith_operand (op
, mode
)
946 enum machine_mode mode
;
948 return (immediate_operand (op
, mode
) || arith_reg_operand (op
, mode
));
952 arith_reg_operand (op
, mode
)
954 enum machine_mode mode
;
956 return (register_operand (op
, mode
)
957 && (GET_CODE (op
) != REG
958 || REGNO (op
) >= FIRST_PSEUDO_REGISTER
959 || (!(IS_YBASE_REGISTER_WINDOW (REGNO (op
)))
960 && REGNO (op
) != FRAME_POINTER_REGNUM
)));
964 call_address_operand (op
, mode
)
966 enum machine_mode mode
;
968 if (symbolic_address_p (op
) || REG_P(op
))
977 dsp16xx_comparison_operator (op
, mode
)
979 enum machine_mode mode
;
981 return ((mode
== VOIDmode
|| GET_MODE (op
) == mode
)
982 && GET_RTX_CLASS (GET_CODE (op
)) == '<'
983 && (GET_CODE(op
) != GE
&& GET_CODE (op
) != LT
&&
984 GET_CODE (op
) != GEU
&& GET_CODE (op
) != LTU
));
988 notice_update_cc(exp
)
991 if (GET_CODE (exp
) == SET
)
993 /* Jumps do not alter the cc's. */
995 if (SET_DEST (exp
) == pc_rtx
)
998 /* Moving register or memory into a register:
999 it doesn't alter the cc's, but it might invalidate
1000 the RTX's which we remember the cc's came from.
1001 (Note that moving a constant 0 or 1 MAY set the cc's). */
1002 if (REG_P (SET_DEST (exp
))
1003 && (REG_P (SET_SRC (exp
)) || GET_CODE (SET_SRC (exp
)) == MEM
))
1005 if (cc_status
.value1
1006 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value1
))
1007 cc_status
.value1
= 0;
1008 if (cc_status
.value2
1009 && reg_overlap_mentioned_p (SET_DEST (exp
), cc_status
.value2
))
1010 cc_status
.value2
= 0;
1013 /* Moving register into memory doesn't alter the cc's.
1014 It may invalidate the RTX's which we remember the cc's came from. */
1015 if (GET_CODE (SET_DEST (exp
)) == MEM
&& REG_P (SET_SRC (exp
)))
1017 if (cc_status
.value1
&& GET_CODE (cc_status
.value1
) == MEM
)
1018 cc_status
.value1
= 0;
1019 if (cc_status
.value2
&& GET_CODE (cc_status
.value2
) == MEM
)
1020 cc_status
.value2
= 0;
1023 /* Function calls clobber the cc's. */
1024 else if (GET_CODE (SET_SRC (exp
)) == CALL
)
1029 /* Tests and compares set the cc's in predictable ways. */
1030 else if (SET_DEST (exp
) == cc0_rtx
)
1033 cc_status
.value1
= SET_SRC (exp
);
1036 /* Certain instructions effect the condition codes. */
1037 else if (GET_MODE_CLASS (GET_MODE (SET_SRC (exp
))) == MODE_INT
)
1038 switch( GET_CODE (SET_SRC (exp
)) )
1042 if (REG_P (SET_DEST (exp
)))
1044 /* Address registers don't set the condition codes */
1045 if (IS_ADDRESS_REGISTER (REGNO (SET_DEST (exp
))))
1060 cc_status
.value1
= SET_SRC (exp
);
1061 cc_status
.value2
= SET_DEST (exp
);
1072 else if (GET_CODE (exp
) == PARALLEL
1073 && GET_CODE (XVECEXP (exp
, 0, 0)) == SET
)
1075 if (SET_DEST (XVECEXP (exp
, 0, 0)) == pc_rtx
)
1078 if (SET_DEST (XVECEXP (exp
, 0, 0)) == cc0_rtx
)
1081 cc_status
.value1
= SET_SRC (XVECEXP (exp
, 0, 0));
1094 dsp16xx_makes_calls ()
1098 for (insn
= get_insns (); insn
; insn
= next_insn (insn
))
1099 if (GET_CODE (insn
) == CALL_INSN
)
1105 long compute_frame_size (size
)
1117 args_size
= current_function_outgoing_args_size
;
1118 reg_size
= reg_save_size ();
1120 total_size
= var_size
+ args_size
+ extra_size
+ reg_size
;
1123 /* Save other computed information. */
1124 current_frame_info
.total_size
= total_size
;
1125 current_frame_info
.var_size
= var_size
;
1126 current_frame_info
.args_size
= args_size
;
1127 current_frame_info
.extra_size
= extra_size
;
1128 current_frame_info
.reg_size
= reg_size
;
1129 current_frame_info
.initialized
= reload_completed
;
1130 current_frame_info
.reg_size
= reg_size
/ UNITS_PER_WORD
;
1131 current_frame_info
.function_makes_calls
= dsp16xx_makes_calls ();
1135 unsigned long offset
= args_size
+ var_size
+ reg_size
;
1136 current_frame_info
.sp_save_offset
= offset
;
1137 current_frame_info
.fp_save_offset
= offset
- total_size
;
1144 dsp16xx_call_saved_register (regno
)
1147 return (regs_ever_live
[regno
] && !call_used_regs
[regno
] &&
1148 !IS_YBASE_REGISTER_WINDOW(regno
));
1153 ybase_regs_ever_used ()
1158 for (regno
= REG_YBASE0
; regno
<= REG_YBASE31
; regno
++)
1159 if (regs_ever_live
[regno
])
1169 function_prologue (file
, size
)
1175 fp
= reg_names
[FRAME_POINTER_REGNUM
];
1176 sp
= reg_names
[STACK_POINTER_REGNUM
];
1177 rr
= reg_names
[RETURN_ADDRESS_REGNUM
]; /* return address register */
1178 a1h
= reg_names
[REG_A1
];
1180 total_size
= compute_frame_size (size
);
1182 fprintf( file
, "\t/* FUNCTION PROLOGUE: */\n" );
1183 fprintf (file
, "\t/* total=%d, vars= %d, regs= %d, args=%d, extra= %d */\n",
1184 current_frame_info
.total_size
,
1185 current_frame_info
.var_size
,
1186 current_frame_info
.reg_size
,
1187 current_function_outgoing_args_size
,
1188 current_frame_info
.extra_size
);
1190 fprintf (file
, "\t/* fp save offset= %d, sp save_offset= %d */\n\n",
1191 current_frame_info
.fp_save_offset
,
1192 current_frame_info
.sp_save_offset
);
1193 /* Set up the 'ybase' register window. */
1195 if (ybase_regs_ever_used())
1197 fprintf (file
, "\t%s=%s\n", a1h
, reg_names
[REG_YBASE
]);
1198 if (TARGET_YBASE_HIGH
)
1199 fprintf (file
, "\t%s=%sh-32\n", reg_names
[REG_A1
], a1h
);
1201 fprintf (file
, "\t%s=%sh+32\n", reg_names
[REG_A1
], a1h
);
1202 fprintf (file
, "\t%s=%s\n", reg_names
[REG_YBASE
], a1h
);
1206 if (current_frame_info
.function_makes_calls
)
1207 fprintf( file
, "\t*%s++=%s\n", sp
, rr
); /* Push return address */
1211 if (current_frame_info
.var_size
)
1213 if (current_frame_info
.var_size
== 1)
1214 fprintf (file
, "\t*%s++\n", sp
);
1217 if(SMALL_INTVAL(current_frame_info
.var_size
) && ((current_frame_info
.var_size
& 0x8000) == 0))
1218 fprintf (file
, "\t%s=%d\n\t*%s++%s\n", reg_names
[REG_J
], current_frame_info
.var_size
, sp
, reg_names
[REG_J
]);
1220 fatal ("Stack size > 32k");
1224 /* Save any registers this function uses, unless they are
1225 * used in a call, in which case we don't need to
1228 for( regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; ++ regno
)
1229 if (dsp16xx_call_saved_register (regno
))
1231 #if OLD_REGISTER_SAVE
1232 fprintf( file
, "\t*%s++=%s\n", sp
, reg_names
[regno
] );
1234 fprintf( file
, "\tpush(*%s)=%s\n", sp
, reg_names
[regno
] );
1238 if (current_frame_info
.args_size
)
1240 if (current_frame_info
.args_size
== 1)
1241 fprintf (file
, "\t*%s++\n", sp
);
1244 if(SMALL_INTVAL(current_frame_info
.args_size
) && ((current_frame_info
.args_size
& 0x8000) == 0))
1245 fprintf (file
, "\t%s=%d\n\t*%s++%s\n", reg_names
[REG_J
], current_frame_info
.args_size
, sp
, reg_names
[REG_J
]);
1247 fatal ("Stack size > 32k");
1251 if (frame_pointer_needed
)
1253 fprintf( file
, "\t%s=%s\n", a1h
, sp
);
1254 fprintf( file
, "\t%s=%s\n", fp
, a1h
); /* Establish new base frame */
1255 fprintf( file
, "\t%s=%d\n", reg_names
[REG_J
], -total_size
);
1256 fprintf( file
, "\t*%s++%s\n", fp
, reg_names
[REG_J
]);
1259 fprintf( file
, "\t/* END FUNCTION PROLOGUE: */\n\n" );
1263 init_emulation_routines ()
1265 dsp16xx_addhf3_libcall
= (rtx
) 0;
1266 dsp16xx_subhf3_libcall
= (rtx
) 0;
1267 dsp16xx_mulhf3_libcall
= (rtx
) 0;
1268 dsp16xx_divhf3_libcall
= (rtx
) 0;
1269 dsp16xx_cmphf3_libcall
= (rtx
) 0;
1270 dsp16xx_fixhfhi2_libcall
= (rtx
) 0;
1271 dsp16xx_floathihf2_libcall
= (rtx
) 0;
1272 dsp16xx_neghf2_libcall
= (rtx
) 0;
1274 dsp16xx_mulhi3_libcall
= (rtx
) 0;
1275 dsp16xx_udivqi3_libcall
= (rtx
) 0;
1276 dsp16xx_udivhi3_libcall
= (rtx
) 0;
1277 dsp16xx_divqi3_libcall
= (rtx
) 0;
1278 dsp16xx_divhi3_libcall
= (rtx
) 0;
1279 dsp16xx_modqi3_libcall
= (rtx
) 0;
1280 dsp16xx_modhi3_libcall
= (rtx
) 0;
1281 dsp16xx_umodqi3_libcall
= (rtx
) 0;
1282 dsp16xx_umodhi3_libcall
= (rtx
) 0;
1283 dsp16xx_ashrhi3_libcall
= (rtx
) 0;
1284 dsp16xx_ashlhi3_libcall
= (rtx
) 0;
1285 dsp16xx_ucmphi2_libcall
= (rtx
) 0;
1286 dsp16xx_lshrhi3_libcall
= (rtx
) 0;
1290 function_epilogue (file
, size
)
1295 int initial_stack_dec
= 0;
1297 fp
= reg_names
[FRAME_POINTER_REGNUM
];
1298 sp
= reg_names
[STACK_POINTER_REGNUM
];
1299 rr
= reg_names
[RETURN_ADDRESS_REGNUM
]; /* return address register */
1300 a1h
= reg_names
[REG_A1
];
1302 fprintf( file
, "\n\t/* FUNCTION EPILOGUE: */\n" );
1304 if (current_frame_info
.args_size
)
1306 if (current_frame_info
.args_size
== 1)
1307 fprintf (file
, "\t*%s--\n", sp
);
1310 fprintf (file
, "\t%s=%d\n\t*%s++%s\n",
1311 reg_names
[REG_J
], -current_frame_info
.args_size
, sp
, reg_names
[REG_J
]);
1315 if (ybase_regs_ever_used())
1317 fprintf (file
, "\t%s=%s\n", a1h
, reg_names
[REG_YBASE
]);
1318 if (TARGET_YBASE_HIGH
)
1319 fprintf (file
, "\t%s=%sh+32\n", reg_names
[REG_A1
], a1h
);
1321 fprintf (file
, "\t%s=%sh-32\n", reg_names
[REG_A1
], a1h
);
1322 fprintf (file
, "\t%s=%s\n", reg_names
[REG_YBASE
], a1h
);
1325 for (regno
= FIRST_PSEUDO_REGISTER
- 1; regno
>= 0; --regno
)
1326 if (dsp16xx_call_saved_register(regno
))
1328 #if OLD_REGISTER_SAVE
1329 if (!initial_stack_dec
)
1331 initial_stack_dec
= 1;
1332 fprintf (file
, "\t*%s--\n", sp
);
1336 #if OLD_REGISTER_SAVE
1337 fprintf( file
, "\t%s=*%s--\n", reg_names
[regno
], sp
);
1339 fprintf( file
, "\t%s=pop(*%s)\n", reg_names
[regno
], sp
);
1343 /* If we restored any registers we have to account for the
1344 initial pre-decrement. But only if we had any local variables
1346 #if OLD_REGISTER_SAVE
1347 if (initial_stack_dec
)
1348 fprintf (file
, "\t*%s++\n", sp
);
1351 if (current_frame_info
.var_size
)
1353 if (current_frame_info
.var_size
== 1)
1354 fprintf (file
, "\t*%s--\n", sp
);
1357 fprintf (file
, "\t%s=%d\n\t*%s++%s\n",
1358 reg_names
[REG_J
], -current_frame_info
.var_size
, sp
, reg_names
[REG_J
]);
1362 fprintf (file
, "\treturn\n");
1363 /* Reset the frame info for the next function */
1364 current_frame_info
= zero_frame_info
;
1365 init_emulation_routines ();
1368 /* Emit insns to move operands[1] into operands[0].
1370 Return 1 if we have written out everything that needs to be done to
1371 do the move. Otherwise, return 0 and the caller will emit the move
1375 emit_move_sequence (operands
, mode
)
1377 enum machine_mode mode
;
1379 register rtx operand0
= operands
[0];
1380 register rtx operand1
= operands
[1];
1382 /* We can only store registers to memory. */
1384 if (GET_CODE (operand0
) == MEM
&& GET_CODE (operand1
) != REG
)
1385 operands
[1] = force_reg (mode
, operand1
);
1391 double_reg_from_memory (operands
)
1396 if (GET_CODE(XEXP(operands
[1],0)) == POST_INC
)
1398 output_asm_insn ("%u0=%1", operands
);
1399 output_asm_insn ("%w0=%1", operands
);
1401 else if (GET_CODE(XEXP(operands
[1],0)) == POST_DEC
)
1403 xoperands
[1] = XEXP (XEXP (operands
[1], 0), 0);
1404 xoperands
[0] = operands
[0];
1406 /* We can't use j anymore since the compiler can allocate it. */
1407 /* output_asm_insn ("j=-3\n\t%u0=*%1++\n\t%w0=*%1++j", xoperands); */
1408 output_asm_insn ("%u0=*%1++\n\t%w0=*%1--\n\t*%1--\n\t*%1--", xoperands
);
1410 else if (GET_CODE(XEXP(operands
[1],0)) == PLUS
)
1416 output_asm_insn ("%u0=%1", operands
);
1419 /* In order to print out the least significant word we must
1420 use 'offset + 1'. */
1421 addr
= XEXP (operands
[1], 0);
1422 if (GET_CODE (XEXP(addr
,0)) == CONST_INT
)
1423 offset
= INTVAL(XEXP(addr
,0)) + 1;
1424 else if (GET_CODE (XEXP(addr
,1)) == CONST_INT
)
1425 offset
= INTVAL(XEXP(addr
,1)) + 1;
1427 fprintf (asm_out_file
, "\t%s=*(%d)\n", reg_names
[REGNO(operands
[0]) + 1], offset
+ 31);
1431 xoperands
[1] = XEXP(operands
[1],0);
1432 xoperands
[0] = operands
[0];
1434 output_asm_insn ("%u0=*%1++\n\t%w0=*%1--", xoperands
);
1440 double_reg_to_memory (operands
)
1445 if (GET_CODE(XEXP(operands
[0],0)) == POST_INC
)
1447 output_asm_insn ("%0=%u1", operands
);
1448 output_asm_insn ("%0=%w1", operands
);
1450 else if (GET_CODE(XEXP(operands
[0],0)) == POST_DEC
)
1452 xoperands
[0] = XEXP (XEXP (operands
[0], 0), 0);
1453 xoperands
[1] = operands
[1];
1455 /* We can't use j anymore since the compiler can allocate it. */
1457 /* output_asm_insn ("j=-3\n\t*%0++=%u1\n\t*%0++j=%w1", xoperands); */
1458 output_asm_insn ("*%0++=%u1\n\t*%0--=%w1\n\t*%0--\n\t*%0--", xoperands
);
1461 else if (GET_CODE(XEXP(operands
[0],0)) == PLUS
)
1466 output_asm_insn ("%0=%u1", operands
);
1468 /* In order to print out the least significant word we must
1469 use 'offset + 1'. */
1470 addr
= XEXP (operands
[0], 0);
1471 if (GET_CODE (XEXP(addr
,0)) == CONST_INT
)
1472 offset
= INTVAL(XEXP(addr
,0)) + 1;
1473 else if (GET_CODE (XEXP(addr
,1)) == CONST_INT
)
1474 offset
= INTVAL(XEXP(addr
,1)) + 1;
1476 fatal ("Invalid addressing mode");
1478 fprintf (asm_out_file
, "\t*(%d)=%s\n", offset
+ 31, reg_names
[REGNO(operands
[1]) + 1]);
1482 xoperands
[0] = XEXP(operands
[0],0);
1483 xoperands
[1] = operands
[1];
1485 output_asm_insn ("*%0++=%u1\n\t*%0--=%w1", xoperands
);
1492 if (chip_name
== (char *) 0)
1493 chip_name
= DEFAULT_CHIP_NAME
;
1495 if (text_seg_name
== (char *) 0)
1496 text_seg_name
= DEFAULT_TEXT_SEG_NAME
;
1498 if (data_seg_name
== (char *) 0)
1499 data_seg_name
= DEFAULT_DATA_SEG_NAME
;
1501 if (bss_seg_name
== (char *) 0)
1502 bss_seg_name
= DEFAULT_BSS_SEG_NAME
;
1504 if (const_seg_name
== (char *) 0)
1505 const_seg_name
= DEFAULT_CONST_SEG_NAME
;
1507 save_chip_name
= (char *) xmalloc (strlen(chip_name
) + 1);
1508 strcpy (save_chip_name
, chip_name
);
1510 rsect_text
= (char *) xmalloc (strlen(".rsect ") +
1511 strlen(text_seg_name
) + 3);
1512 rsect_data
= (char *) xmalloc (strlen(".rsect ") +
1513 strlen(data_seg_name
) + 3);
1514 rsect_bss
= (char *) xmalloc (strlen(".rsect ") +
1515 strlen(bss_seg_name
) + 3);
1516 rsect_const
= (char *) xmalloc (strlen(".rsect ") +
1517 strlen(const_seg_name
) + 3);
1519 sprintf (rsect_text
, ".rsect \"%s\"", text_seg_name
);
1520 sprintf (rsect_data
, ".rsect \"%s\"", data_seg_name
);
1521 sprintf (rsect_bss
, ".rsect \"%s\"", bss_seg_name
);
1522 sprintf (rsect_const
, ".rsect \"%s\"", const_seg_name
);
1526 if (TARGET_OPTIMIZE_SPEED
)
1528 flag_unroll_loops
= 1;
1529 flag_inline_functions
= 1;
1534 enum rtx_code save_next_cc_user_code
;
1537 next_cc_user_code (insn
)
1540 if ( !(insn
= next_cc0_user (insn
)))
1542 else if (GET_CODE (insn
) == JUMP_INSN
1543 && GET_CODE (PATTERN (insn
)) == SET
1544 && GET_CODE (SET_SRC (PATTERN (insn
))) == IF_THEN_ELSE
)
1545 return GET_CODE (XEXP (SET_SRC (PATTERN (insn
)), 0));
1546 else if (GET_CODE (insn
) == INSN
1547 && GET_CODE (PATTERN (insn
)) == SET
1548 && comparison_operator (SET_SRC (PATTERN (insn
)), VOIDmode
))
1549 return GET_CODE (SET_SRC (PATTERN (insn
)));
1555 print_operand(file
, op
, letter
)
1562 code
= GET_CODE(op
);
1567 code
= reverse_condition (code
);
1576 else if (code
== NE
)
1581 else if (code
== GT
|| code
== GTU
)
1586 else if (code
== LT
|| code
== LTU
)
1591 else if (code
== GE
|| code
== GEU
)
1596 else if (code
== LE
|| code
== LEU
)
1611 /* Print the low half of a 32-bit register pair */
1613 fprintf( file
, "%s", reg_names
[REGNO(op
)+1] );
1614 else if (letter
== 'u' || !letter
)
1615 fprintf( file
, "%s", reg_names
[REGNO(op
)]);
1616 else if (letter
== 'b')
1617 fprintf ( file
, "%sh", reg_names
[REGNO(op
)]);
1618 else if (letter
== 'm')
1619 fprintf (file
, "%s", himode_reg_name
[REGNO(op
)]);
1621 fatal("Bad register extension code");
1623 else if( code
== MEM
)
1624 output_address( XEXP(op
,0) );
1625 else if( code
== CONST_INT
)
1628 fprintf( file
, "0x%x", (INTVAL(op
) & 0xffff) );
1629 else if (letter
== 'h')
1630 fprintf( file
, "%d", INTVAL (op
) );
1631 else if( letter
== 'U' )
1632 fprintf( file
, "0x%x", ((INTVAL(op
) & 0xffff0000) >> 16) & 0xffff );
1634 output_addr_const( file
, op
);
1636 else if( code
== CONST_DOUBLE
&& GET_MODE(op
) != DImode
)
1638 union { double d
; int i
[2]; } u
;
1639 union { float f
; int i
; } u1
;
1640 u
.i
[0] = CONST_DOUBLE_LOW (op
);
1641 u
.i
[1] = CONST_DOUBLE_HIGH (op
);
1643 fprintf( file
, "0x%x", u1
.i
);
1645 else output_addr_const( file
, op
);
1650 print_operand_address(file
, addr
)
1657 switch (GET_CODE (addr
))
1660 fprintf (file
, "*%s", reg_names
[REGNO (addr
)]);
1663 fprintf (file
, "*%s--", reg_names
[REGNO (XEXP (addr
, 0))]);
1666 fprintf (file
, "*%s++", reg_names
[REGNO (XEXP (addr
, 0))]);
1669 if (GET_CODE (XEXP(addr
,0)) == CONST_INT
)
1670 offset
= INTVAL(XEXP(addr
,0)), base
= XEXP(addr
,1);
1671 else if (GET_CODE (XEXP(addr
,1)) == CONST_INT
)
1672 offset
= INTVAL(XEXP(addr
,1)), base
= XEXP(addr
,0);
1673 if (GET_CODE (base
) == REG
&& REGNO(base
) == STACK_POINTER_REGNUM
)
1675 if (offset
>= -31 && offset
<= 0)
1676 offset
= 31 + offset
;
1678 fatal ("Invalid offset in ybase addressing");
1681 fatal ("Invalid register in ybase addressing");
1683 fprintf (file
, "*(%d)", offset
);
1687 if( FITS_5_BITS( addr
) )
1688 fprintf( file
, "*(0x%x)", (INTVAL(addr
) & 0x20) );
1690 output_addr_const(file
, addr
);
1695 output_dsp16xx_float_const(operands
)
1698 rtx dst
= operands
[0];
1699 rtx src
= operands
[1];
1701 #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
1705 REAL_VALUE_FROM_CONST_DOUBLE (d
, src
);
1706 REAL_VALUE_TO_TARGET_SINGLE (d
, value
);
1708 operands
[1] = gen_rtx (CONST_INT
, VOIDmode
, value
);
1709 output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands
);
1711 fatal ("inline float constants not supported on this host");
1718 int reg_save_size
= 0;
1721 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1722 if (dsp16xx_call_saved_register (regno
))
1724 reg_save_size
+= UNITS_PER_WORD
;
1727 return (reg_save_size
);
1731 dsp16xx_starting_frame_offset()
1733 int reg_save_size
= 0;
1736 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1737 if (dsp16xx_call_saved_register (regno
))
1739 reg_save_size
+= UNITS_PER_WORD
;
1742 return (reg_save_size
);
1746 initial_frame_pointer_offset()
1752 offset
= compute_frame_size (get_frame_size());
1754 #ifdef STACK_GROWS_DOWNWARD
1761 /* Generate the minimum number of 1600 core shift instructions
1762 to shift by 'shift_amount'. */
1766 emit_1600_core_shift (shift_op
, operands
, shift_amount
, mode
)
1767 enum rtx_code shift_op
;
1770 enum machine_mode mode
;
1774 int first_shift_emitted
= 0;
1776 while (shift_amount
!= 0)
1778 if (shift_amount
/16)
1780 quotient
= shift_amount
/16;
1781 shift_amount
= shift_amount
- (quotient
* 16);
1782 for (i
= 0; i
< quotient
; i
++)
1783 emit_insn (gen_rtx (SET
, VOIDmode
, operands
[0],
1784 gen_rtx (shift_op
, mode
,
1785 first_shift_emitted
? operands
[0] : operands
[1],
1786 gen_rtx (CONST_INT
, VOIDmode
, 16))));
1787 first_shift_emitted
= 1;
1789 else if (shift_amount
/8)
1791 quotient
= shift_amount
/8;
1792 shift_amount
= shift_amount
- (quotient
* 8);
1793 for (i
= 0; i
< quotient
; i
++)
1794 emit_insn (gen_rtx (SET
, VOIDmode
, operands
[0],
1795 gen_rtx (shift_op
, mode
,
1796 first_shift_emitted
? operands
[0] : operands
[1],
1797 gen_rtx (CONST_INT
, VOIDmode
, 8))));
1798 first_shift_emitted
= 1;
1800 else if (shift_amount
/4)
1802 quotient
= shift_amount
/4;
1803 shift_amount
= shift_amount
- (quotient
* 4);
1804 for (i
= 0; i
< quotient
; i
++)
1805 emit_insn (gen_rtx (SET
, VOIDmode
, operands
[0],
1806 gen_rtx (shift_op
, mode
,
1807 first_shift_emitted
? operands
[0] : operands
[1],
1808 gen_rtx (CONST_INT
, VOIDmode
, 4))));
1809 first_shift_emitted
= 1;
1811 else if (shift_amount
/1)
1813 quotient
= shift_amount
/1;
1814 shift_amount
= shift_amount
- (quotient
* 1);
1815 for (i
= 0; i
< quotient
; i
++)
1816 emit_insn (gen_rtx (SET
, VOIDmode
, operands
[0],
1817 gen_rtx (shift_op
, mode
,
1818 first_shift_emitted
? operands
[0] : operands
[1],
1819 gen_rtx (CONST_INT
, VOIDmode
, 1))));
1820 first_shift_emitted
= 1;
1826 emit_1600_core_shift (shift_op
, operands
, shift_amount
)
1827 enum rtx_code shift_op
;
1833 int first_shift_emitted
= 0;
1834 char **shift_asm_ptr
;
1835 char **shift_asm_ptr_first
;
1837 if (shift_op
== ASHIFT
)
1839 shift_asm_ptr
= ashift_left_asm
;
1840 shift_asm_ptr_first
= ashift_left_asm_first
;
1842 else if (shift_op
== ASHIFTRT
)
1844 shift_asm_ptr
= ashift_right_asm
;
1845 shift_asm_ptr_first
= ashift_right_asm_first
;
1847 else if (shift_op
== LSHIFTRT
)
1849 shift_asm_ptr
= lshift_right_asm
;
1850 shift_asm_ptr_first
= lshift_right_asm_first
;
1853 fatal ("Invalid shift operator in emit_1600_core_shift");
1855 while (shift_amount
!= 0)
1857 if (shift_amount
/16)
1859 quotient
= shift_amount
/16;
1860 shift_amount
= shift_amount
- (quotient
* 16);
1861 for (i
= 0; i
< quotient
; i
++)
1862 output_asm_insn ((first_shift_emitted
? shift_asm_ptr
[SHIFT_INDEX_16
]
1863 : shift_asm_ptr_first
[SHIFT_INDEX_16
]), operands
);
1864 first_shift_emitted
= 1;
1866 else if (shift_amount
/8)
1868 quotient
= shift_amount
/8;
1869 shift_amount
= shift_amount
- (quotient
* 8);
1870 for (i
= 0; i
< quotient
; i
++)
1871 output_asm_insn ((first_shift_emitted
? shift_asm_ptr
[SHIFT_INDEX_8
]
1872 : shift_asm_ptr_first
[SHIFT_INDEX_8
]), operands
);
1873 first_shift_emitted
= 1;
1875 else if (shift_amount
/4)
1877 quotient
= shift_amount
/4;
1878 shift_amount
= shift_amount
- (quotient
* 4);
1879 for (i
= 0; i
< quotient
; i
++)
1880 output_asm_insn ((first_shift_emitted
? shift_asm_ptr
[SHIFT_INDEX_4
]
1881 : shift_asm_ptr_first
[SHIFT_INDEX_4
]), operands
);
1882 first_shift_emitted
= 1;
1884 else if (shift_amount
/1)
1886 quotient
= shift_amount
/1;
1887 shift_amount
= shift_amount
- (quotient
* 1);
1888 for (i
= 0; i
< quotient
; i
++)
1889 output_asm_insn ((first_shift_emitted
? shift_asm_ptr
[SHIFT_INDEX_1
]
1890 : shift_asm_ptr_first
[SHIFT_INDEX_1
]), operands
);
1891 first_shift_emitted
= 1;
1897 asm_output_common(file
, name
, size
, rounded
)
1904 ASM_GLOBALIZE_LABEL (file
, name
);
1905 assemble_name (file
, name
);
1908 fprintf (file
, "%d * int\n", rounded
);
1910 fprintf (file
, "int\n");
1914 asm_output_local(file
, name
, size
, rounded
)
1921 assemble_name (file
, name
);
1924 fprintf (file
, "%d * int\n", rounded
);
1926 fprintf (file
, "int\n");
1930 asm_output_float (file
, fp_const
)
1934 #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
1935 REAL_VALUE_TYPE d
= fp_const
;
1938 REAL_VALUE_TO_TARGET_SINGLE (d
, value
);
1939 fputs ("\tint ", file
);
1940 #ifdef WORDS_BIG_ENDIAN
1941 fprintf (file
, "0x%-4.4x, 0x%-4.4x", (value
>> 16) & 0xffff, (value
& 0xffff));
1943 fprintf (file
, "0x%-4.4x, 0x%-4.4x", (value
& 0xffff), (value
>> 16) & 0xffff);
1947 fatal ("inline float constants not supported on this host");
1952 asm_output_long (file
, value
)
1956 fputs ("\tint ", file
);
1957 #ifdef WORDS_BIG_ENDIAN
1958 fprintf (file
, "0x%-4.4x, 0x%-4.4x", (value
>> 16) & 0xffff, (value
& 0xffff));
1960 fprintf (file
, "0x%-4.4x, 0x%-4.4x", (value
& 0xffff), (value
>> 16) & 0xffff);
1966 dsp16xx_address_cost (addr
)
1969 switch (GET_CODE (addr
))
1979 rtx offset
= const0_rtx
;
1980 addr
= eliminate_constant_term (addr
, &offset
);
1982 if (GET_CODE (addr
) == LABEL_REF
)
1985 if (GET_CODE (addr
) != SYMBOL_REF
)
1988 if (INTVAL (offset
) == 0)
1993 case POST_INC
: case POST_DEC
:
1994 return (GET_MODE (addr
) == QImode
? 1 : 2);
1996 case SYMBOL_REF
: case LABEL_REF
:
2001 register rtx plus0
= XEXP (addr
, 0);
2002 register rtx plus1
= XEXP (addr
, 1);
2004 if (GET_CODE (plus0
) != REG
&& GET_CODE (plus1
) == REG
)
2006 plus0
= XEXP (addr
, 1);
2007 plus1
= XEXP (addr
, 0);
2010 if (GET_CODE (plus0
) != REG
)
2013 switch (GET_CODE (plus1
))
2024 return dsp16xx_address_cost (plus1
) + 1;
2033 /* Determine whether a function argument is passed in a register, and
2036 The arguments are CUM, which summarizes all the previous
2037 arguments; MODE, the machine mode of the argument; TYPE,
2038 the data type of the argument as a tree node or 0 if that is not known
2039 (which happens for C support library functions); and NAMED,
2040 which is 1 for an ordinary argument and 0 for nameless arguments that
2041 correspond to `...' in the called function's prototype.
2043 The value of the expression should either be a `reg' RTX for the
2044 hard register in which to pass the argument, or zero to pass the
2045 argument on the stack.
2047 On the dsp1610 the first four words of args are normally in registers
2048 and the rest are pushed. If we a long or on float mode, the argument
2049 must begin on a even register boundary
2051 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2052 For structures that are passed in memory, but could have been
2053 passed in registers, we first load the structure into the
2054 register, and then when the last argument is passed, we store
2055 the registers into the stack locations. This fixes some bugs
2056 where GCC did not expect to have register arguments, followed */
2060 dsp16xx_function_arg (args_so_far
, mode
, type
, named
)
2061 CUMULATIVE_ARGS args_so_far
;
2062 enum machine_mode mode
;
2068 if ((args_so_far
& 1) != 0
2069 && (mode
== HImode
|| GET_MODE_CLASS(mode
) == MODE_FLOAT
))
2072 if (named
&& args_so_far
< 4 && !MUST_PASS_IN_STACK (mode
,type
))
2073 return gen_rtx (REG
, mode
, args_so_far
+ FIRST_REG_FOR_FUNCTION_ARG
);
2075 return (struct rtx_def
*) 0;
2078 return (struct rtx_def
*) 0;
2081 /* Advance the argument to the next argument position. */
2084 dsp16xx_function_arg_advance (cum
, mode
, type
, named
)
2085 CUMULATIVE_ARGS
*cum
; /* current arg information */
2086 enum machine_mode mode
; /* current arg mode */
2087 tree type
; /* type of the argument or 0 if lib support */
2088 int named
; /* whether or not the argument was named */
2093 && (mode
== HImode
|| GET_MODE_CLASS(mode
) == MODE_FLOAT
))
2096 if (mode
!= BLKmode
)
2097 *cum
+= GET_MODE_SIZE (mode
);
2099 *cum
+= int_size_in_bytes (type
);
2104 dsp16xx_file_start ()
2106 fprintf (asm_out_file
, "#include <%s.h>\n", save_chip_name
);
2109 fprintf (asm_out_file
, "#include <1610.h>\n");
2117 enum machine_mode mode
;
2119 mode
= GET_MODE (x
);
2123 emit_insn (gen_rtx (PARALLEL
, VOIDmode
,
2125 gen_rtx (SET
, VOIDmode
, cc0_rtx
, x
),
2126 gen_rtx (CLOBBER
, VOIDmode
,
2127 gen_rtx (SCRATCH
, QImode
, 0)))));
2129 else if (mode
== HImode
)
2130 emit_insn (gen_rtx (SET
, VOIDmode
, cc0_rtx
, x
));
2132 fatal ("Invalid mode for gen_tst_reg");
2138 gen_compare_reg (code
, x
, y
)
2142 enum machine_mode mode
;
2144 mode
= GET_MODE (x
);
2145 /* For floating point compare insns, a call is generated so don't
2146 do anything here. */
2148 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
2153 if (code
== GTU
|| code
== GEU
||
2154 code
== LTU
|| code
== LEU
)
2156 emit_insn (gen_rtx (PARALLEL
, VOIDmode
,
2158 gen_rtx (SET
, VOIDmode
, cc0_rtx
,
2159 gen_rtx (COMPARE
, mode
, x
, y
)),
2160 gen_rtx (CLOBBER
, VOIDmode
,
2161 gen_rtx (SCRATCH
, QImode
, 0)),
2162 gen_rtx (CLOBBER
, VOIDmode
,
2163 gen_rtx (SCRATCH
, QImode
, 0)))));
2167 emit_insn (gen_rtx (PARALLEL
, VOIDmode
,
2169 gen_rtx (SET
, VOIDmode
, cc0_rtx
,
2170 gen_rtx (COMPARE
, mode
, x
, y
)),
2171 gen_rtx (CLOBBER
, VOIDmode
,
2172 gen_rtx (SCRATCH
, QImode
, 0)),
2173 gen_rtx (CLOBBER
, VOIDmode
,
2174 gen_rtx (SCRATCH
, QImode
, 0)))));
2177 else if (mode
== HImode
)
2179 if (code
== GTU
|| code
== GEU
||
2180 code
== LTU
|| code
== LEU
)
2183 emit_insn (gen_rtx (PARALLEL
, VOIDmode
, gen_rtvec (5,
2184 gen_rtx (SET
, VOIDmode
, cc0_rtx
, gen_rtx (COMPARE
, VOIDmode
, x
, y
)),
2185 gen_rtx (CLOBBER
, VOIDmode
, gen_rtx (SCRATCH
, QImode
, 0)),
2186 gen_rtx (CLOBBER
, VOIDmode
, gen_rtx (SCRATCH
, QImode
, 0)),
2187 gen_rtx (CLOBBER
, VOIDmode
, gen_rtx (SCRATCH
, QImode
, 0)),
2188 gen_rtx (CLOBBER
, VOIDmode
, gen_rtx (SCRATCH
, QImode
, 0)))));
2190 if (!dsp16xx_ucmphi2_libcall
)
2191 dsp16xx_ucmphi2_libcall
= gen_rtx (SYMBOL_REF
, Pmode
, UCMPHI2_LIBCALL
);
2192 emit_library_call (dsp16xx_ucmphi2_libcall
, 1, HImode
, 2,
2193 x
, HImode
, y
, HImode
);
2194 emit_insn (gen_tsthi_1 (copy_to_reg(hard_libcall_value (HImode
))));
2198 emit_insn (gen_rtx (SET
, VOIDmode
, cc0_rtx
,
2199 gen_rtx (COMPARE
, VOIDmode
, force_reg(HImode
, x
),
2200 force_reg(HImode
,y
))));
2203 fatal ("Invalid mode for integer comparison in gen_compare_reg");
2209 output_block_move (operands
)
2212 int loop_count
= INTVAL(operands
[2]);
2215 fprintf (asm_out_file
, "\tdo %d {\n", loop_count
);
2216 xoperands
[0] = operands
[4];
2217 xoperands
[1] = operands
[1];
2218 output_asm_insn ("%0=*%1++", xoperands
);
2220 xoperands
[0] = operands
[0];
2221 xoperands
[1] = operands
[4];
2222 output_asm_insn ("*%0++=%1", xoperands
);
2224 fprintf (asm_out_file
, "\t}\n");