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
);
1696 if (chip_name
== (char *) 0)
1697 chip_name
= DEFAULT_CHIP_NAME
;
1699 if (text_seg_name
== (char *) 0)
1700 text_seg_name
= DEFAULT_TEXT_SEG_NAME
;
1702 if (data_seg_name
== (char *) 0)
1703 data_seg_name
= DEFAULT_DATA_SEG_NAME
;
1705 if (bss_seg_name
== (char *) 0)
1706 bss_seg_name
= DEFAULT_BSS_SEG_NAME
;
1708 if (const_seg_name
== (char *) 0)
1709 const_seg_name
= DEFAULT_CONST_SEG_NAME
;
1711 save_chip_name
= xstrdup (chip_name
);
1713 rsect_text
= tmp
= (char *) xmalloc (strlen(".rsect ") +
1714 strlen(text_seg_name
) + 3);
1715 sprintf (tmp
, ".rsect \"%s\"", text_seg_name
);
1717 rsect_data
= tmp
= (char *) xmalloc (strlen(".rsect ") +
1718 strlen(data_seg_name
) + 3);
1719 sprintf (tmp
, ".rsect \"%s\"", data_seg_name
);
1721 rsect_bss
= tmp
= (char *) xmalloc (strlen(".rsect ") +
1722 strlen(bss_seg_name
) + 3);
1723 sprintf (tmp
, ".rsect \"%s\"", bss_seg_name
);
1725 rsect_const
= tmp
= (char *) xmalloc (strlen(".rsect ") +
1726 strlen(const_seg_name
) + 3);
1727 sprintf (tmp
, ".rsect \"%s\"", const_seg_name
);
1729 /* Mark our global variables for GC. */
1730 ggc_add_rtx_root (&dsp16xx_addhf3_libcall
, 1);
1731 ggc_add_rtx_root (&dsp16xx_subhf3_libcall
, 1);
1732 ggc_add_rtx_root (&dsp16xx_mulhf3_libcall
, 1);
1733 ggc_add_rtx_root (&dsp16xx_divhf3_libcall
, 1);
1734 ggc_add_rtx_root (&dsp16xx_cmphf3_libcall
, 1);
1735 ggc_add_rtx_root (&dsp16xx_fixhfhi2_libcall
, 1);
1736 ggc_add_rtx_root (&dsp16xx_floathihf2_libcall
, 1);
1737 ggc_add_rtx_root (&dsp16xx_neghf2_libcall
, 1);
1738 ggc_add_rtx_root (&dsp16xx_mulhi3_libcall
, 1);
1739 ggc_add_rtx_root (&dsp16xx_udivqi3_libcall
, 1);
1740 ggc_add_rtx_root (&dsp16xx_udivhi3_libcall
, 1);
1741 ggc_add_rtx_root (&dsp16xx_divqi3_libcall
, 1);
1742 ggc_add_rtx_root (&dsp16xx_divhi3_libcall
, 1);
1743 ggc_add_rtx_root (&dsp16xx_modqi3_libcall
, 1);
1744 ggc_add_rtx_root (&dsp16xx_modhi3_libcall
, 1);
1745 ggc_add_rtx_root (&dsp16xx_umodqi3_libcall
, 1);
1746 ggc_add_rtx_root (&dsp16xx_umodhi3_libcall
, 1);
1747 ggc_add_rtx_root (&dsp16xx_ashrhi3_libcall
, 1);
1748 ggc_add_rtx_root (&dsp16xx_ashlhi3_libcall
, 1);
1749 ggc_add_rtx_root (&dsp16xx_ucmphi2_libcall
, 1);
1750 ggc_add_rtx_root (&dsp16xx_lshrhi3_libcall
, 1);
1754 next_cc_user_unsigned (insn
)
1757 switch (next_cc_user_code (insn
))
1770 next_cc_user_code (insn
)
1773 /* If no insn could be found we assume that the jump has been
1774 deleted and the compare will be deleted later. */
1776 if (!(insn
= next_cc0_user (insn
)))
1777 return (enum rtx_code
) 0;
1778 else if (GET_CODE (insn
) == JUMP_INSN
1779 && GET_CODE (PATTERN (insn
)) == SET
1780 && GET_CODE (SET_SRC (PATTERN (insn
))) == IF_THEN_ELSE
)
1781 return GET_CODE (XEXP (SET_SRC (PATTERN (insn
)), 0));
1782 else if (GET_CODE (insn
) == INSN
1783 && GET_CODE (PATTERN (insn
)) == SET
1784 && comparison_operator (SET_SRC (PATTERN (insn
)), VOIDmode
))
1785 return GET_CODE (SET_SRC (PATTERN (insn
)));
1791 print_operand(file
, op
, letter
)
1798 code
= GET_CODE(op
);
1803 code
= reverse_condition (code
);
1812 else if (code
== NE
)
1817 else if (code
== GT
|| code
== GTU
)
1822 else if (code
== LT
|| code
== LTU
)
1827 else if (code
== GE
|| code
== GEU
)
1832 else if (code
== LE
|| code
== LEU
)
1847 /* Print the low half of a 32-bit register pair. */
1849 fprintf (file
, "%s", reg_names
[REGNO (op
) + 1]);
1850 else if (letter
== 'u' || !letter
)
1851 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
1852 else if (letter
== 'b')
1853 fprintf (file
, "%sh", reg_names
[REGNO (op
)]);
1854 else if (letter
== 'm')
1855 fprintf (file
, "%s", himode_reg_name
[REGNO (op
)]);
1857 output_operand_lossage ("bad register extension code");
1859 else if (code
== MEM
)
1860 output_address (XEXP(op
,0));
1861 else if (code
== CONST_INT
)
1863 HOST_WIDE_INT val
= INTVAL (op
);
1866 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, val
& 0xffff);
1867 else if (letter
== 'h')
1868 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, val
);
1869 else if (letter
== 'U')
1870 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, (val
>> 16) & 0xffff);
1872 output_addr_const(file
, op
);
1874 else if (code
== CONST_DOUBLE
&& GET_MODE(op
) != DImode
)
1878 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1879 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1880 fprintf (file
, "0x%x", l
);
1882 else if (code
== CONST
)
1884 rtx addr
= XEXP (op
, 0);
1886 if (GET_CODE (addr
) != PLUS
)
1888 output_addr_const(file
, op
);
1892 if ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
1893 || GET_CODE (XEXP (addr
, 0)) == LABEL_REF
)
1894 && (GET_CODE (XEXP (addr
, 1)) == CONST_INT
))
1896 int n
= INTVAL (XEXP(addr
, 1));
1897 output_addr_const (file
, XEXP (addr
, 0));
1900 fprintf (file
, "+");
1902 n
= (int) (short) n
;
1903 fprintf (file
, "%d", n
);
1905 else if ((GET_CODE (XEXP (addr
, 1)) == SYMBOL_REF
1906 || GET_CODE (XEXP (addr
, 1)) == LABEL_REF
)
1907 && (GET_CODE (XEXP (addr
, 0)) == CONST_INT
))
1909 int n
= INTVAL (XEXP(addr
, 0));
1910 output_addr_const (file
, XEXP (addr
, 1));
1913 fprintf (file
, "+");
1915 n
= (int) (short) n
;
1916 fprintf (file
, "%d", n
);
1919 output_addr_const(file
, op
);
1922 output_addr_const (file
, op
);
1927 print_operand_address(file
, addr
)
1934 switch (GET_CODE (addr
))
1937 fprintf (file
, "*%s", reg_names
[REGNO (addr
)]);
1940 fprintf (file
, "*%s--", reg_names
[REGNO (XEXP (addr
, 0))]);
1943 fprintf (file
, "*%s++", reg_names
[REGNO (XEXP (addr
, 0))]);
1946 if (GET_CODE (XEXP(addr
,0)) == CONST_INT
)
1947 offset
= INTVAL(XEXP(addr
,0)), base
= XEXP(addr
,1);
1948 else if (GET_CODE (XEXP(addr
,1)) == CONST_INT
)
1949 offset
= INTVAL(XEXP(addr
,1)), base
= XEXP(addr
,0);
1952 if (GET_CODE (base
) == REG
&& REGNO(base
) == STACK_POINTER_REGNUM
)
1954 if (offset
>= -31 && offset
<= 0)
1955 offset
= 31 + offset
;
1957 fatal_error ("invalid offset in ybase addressing");
1960 fatal_error ("invalid register in ybase addressing");
1962 fprintf (file
, "*(%d)", offset
);
1966 if (FITS_5_BITS (addr
))
1967 fprintf (file
, "*(0x%x)", (INTVAL (addr
) & 0x20));
1969 output_addr_const (file
, addr
);
1974 output_dsp16xx_float_const (operands
)
1977 rtx src
= operands
[1];
1982 REAL_VALUE_FROM_CONST_DOUBLE (d
, src
);
1983 REAL_VALUE_TO_TARGET_SINGLE (d
, value
);
1985 operands
[1] = GEN_INT (value
);
1986 output_asm_insn ("%u0=%U1\n\t%w0=%H1", operands
);
1992 int reg_save_size
= 0;
1995 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1996 if (dsp16xx_call_saved_register (regno
))
1998 reg_save_size
+= UNITS_PER_WORD
;
2001 /* If the function makes calls we will save need to save the 'pr' register. */
2002 if (current_frame_info
.function_makes_calls
)
2005 return (reg_save_size
);
2010 dsp16xx_starting_frame_offset()
2012 int reg_save_size
= 0;
2015 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
2016 if (dsp16xx_call_saved_register (regno
))
2018 reg_save_size
+= UNITS_PER_WORD
;
2021 return (reg_save_size
);
2026 initial_frame_pointer_offset()
2030 offset
= compute_frame_size (get_frame_size());
2032 #ifdef STACK_GROWS_DOWNWARD
2039 /* Generate the minimum number of 1600 core shift instructions
2040 to shift by 'shift_amount'. */
2044 emit_1600_core_shift (shift_op
, operands
, shift_amount
, mode
)
2045 enum rtx_code shift_op
;
2048 enum machine_mode mode
;
2052 int first_shift_emitted
= 0;
2054 while (shift_amount
!= 0)
2056 if (shift_amount
/16)
2058 quotient
= shift_amount
/16;
2059 shift_amount
= shift_amount
- (quotient
* 16);
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;
2068 else if (shift_amount
/8)
2070 quotient
= shift_amount
/8;
2071 shift_amount
= shift_amount
- (quotient
* 8);
2072 for (i
= 0; i
< quotient
; i
++)
2073 emit_insn (gen_rtx_SET (VOIDmode
, operands
[0],
2074 gen_rtx (shift_op
, mode
,
2076 ? operands
[0] : operands
[1],
2078 first_shift_emitted
= 1;
2080 else if (shift_amount
/4)
2082 quotient
= shift_amount
/4;
2083 shift_amount
= shift_amount
- (quotient
* 4);
2084 for (i
= 0; i
< quotient
; i
++)
2085 emit_insn (gen_rtx_SET (VOIDmode
, operands
[0],
2086 gen_rtx (shift_op
, mode
,
2088 ? operands
[0] : operands
[1],
2090 first_shift_emitted
= 1;
2092 else if (shift_amount
/1)
2094 quotient
= shift_amount
/1;
2095 shift_amount
= shift_amount
- (quotient
* 1);
2096 for (i
= 0; i
< quotient
; i
++)
2097 emit_insn (gen_rtx_SET (VOIDmode
, operands
[0],
2098 gen_rtx (shift_op
, mode
,
2100 ? operands
[0] : operands
[1],
2102 first_shift_emitted
= 1;
2108 emit_1600_core_shift (shift_op
, operands
, shift_amount
)
2109 enum rtx_code shift_op
;
2115 int first_shift_emitted
= 0;
2116 const char * const *shift_asm_ptr
;
2117 const char * const *shift_asm_ptr_first
;
2119 if (shift_op
== ASHIFT
)
2121 shift_asm_ptr
= ashift_left_asm
;
2122 shift_asm_ptr_first
= ashift_left_asm_first
;
2124 else if (shift_op
== ASHIFTRT
)
2126 shift_asm_ptr
= ashift_right_asm
;
2127 shift_asm_ptr_first
= ashift_right_asm_first
;
2129 else if (shift_op
== LSHIFTRT
)
2131 shift_asm_ptr
= lshift_right_asm
;
2132 shift_asm_ptr_first
= lshift_right_asm_first
;
2135 fatal_error ("invalid shift operator in emit_1600_core_shift");
2137 while (shift_amount
!= 0)
2139 if (shift_amount
/16)
2141 quotient
= shift_amount
/16;
2142 shift_amount
= shift_amount
- (quotient
* 16);
2143 for (i
= 0; i
< quotient
; i
++)
2144 output_asm_insn ((first_shift_emitted
? shift_asm_ptr
[SHIFT_INDEX_16
]
2145 : shift_asm_ptr_first
[SHIFT_INDEX_16
]), operands
);
2146 first_shift_emitted
= 1;
2148 else if (shift_amount
/8)
2150 quotient
= shift_amount
/8;
2151 shift_amount
= shift_amount
- (quotient
* 8);
2152 for (i
= 0; i
< quotient
; i
++)
2153 output_asm_insn ((first_shift_emitted
? shift_asm_ptr
[SHIFT_INDEX_8
]
2154 : shift_asm_ptr_first
[SHIFT_INDEX_8
]), operands
);
2155 first_shift_emitted
= 1;
2157 else if (shift_amount
/4)
2159 quotient
= shift_amount
/4;
2160 shift_amount
= shift_amount
- (quotient
* 4);
2161 for (i
= 0; i
< quotient
; i
++)
2162 output_asm_insn ((first_shift_emitted
? shift_asm_ptr
[SHIFT_INDEX_4
]
2163 : shift_asm_ptr_first
[SHIFT_INDEX_4
]), operands
);
2164 first_shift_emitted
= 1;
2166 else if (shift_amount
/1)
2168 quotient
= shift_amount
/1;
2169 shift_amount
= shift_amount
- (quotient
* 1);
2170 for (i
= 0; i
< quotient
; i
++)
2171 output_asm_insn ((first_shift_emitted
? shift_asm_ptr
[SHIFT_INDEX_1
]
2172 : shift_asm_ptr_first
[SHIFT_INDEX_1
]), operands
);
2173 first_shift_emitted
= 1;
2180 num_1600_core_shifts (shift_amount
)
2185 int first_shift_emitted
= 0;
2188 while (shift_amount
!= 0)
2190 if (shift_amount
/16)
2192 quotient
= shift_amount
/16;
2193 shift_amount
= shift_amount
- (quotient
* 16);
2194 for (i
= 0; i
< quotient
; i
++)
2196 first_shift_emitted
= 1;
2198 else if (shift_amount
/8)
2200 quotient
= shift_amount
/8;
2201 shift_amount
= shift_amount
- (quotient
* 8);
2202 for (i
= 0; i
< quotient
; i
++)
2205 first_shift_emitted
= 1;
2207 else if (shift_amount
/4)
2209 quotient
= shift_amount
/4;
2210 shift_amount
= shift_amount
- (quotient
* 4);
2211 for (i
= 0; i
< quotient
; i
++)
2214 first_shift_emitted
= 1;
2216 else if (shift_amount
/1)
2218 quotient
= shift_amount
/1;
2219 shift_amount
= shift_amount
- (quotient
* 1);
2220 for (i
= 0; i
< quotient
; i
++)
2223 first_shift_emitted
= 1;
2230 asm_output_common(file
, name
, size
, rounded
)
2233 int size ATTRIBUTE_UNUSED
;
2237 ASM_GLOBALIZE_LABEL (file
, name
);
2238 assemble_name (file
, name
);
2241 fprintf (file
, "%d * int\n", rounded
);
2243 fprintf (file
, "int\n");
2247 asm_output_local(file
, name
, size
, rounded
)
2250 int size ATTRIBUTE_UNUSED
;
2254 assemble_name (file
, name
);
2257 fprintf (file
, "%d * int\n", rounded
);
2259 fprintf (file
, "int\n");
2263 dsp16xx_address_cost (addr
)
2266 switch (GET_CODE (addr
))
2276 rtx offset
= const0_rtx
;
2277 addr
= eliminate_constant_term (addr
, &offset
);
2279 if (GET_CODE (addr
) == LABEL_REF
)
2282 if (GET_CODE (addr
) != SYMBOL_REF
)
2285 if (INTVAL (offset
) == 0)
2290 case POST_INC
: case POST_DEC
:
2291 return (GET_MODE (addr
) == QImode
? 1 : 2);
2293 case SYMBOL_REF
: case LABEL_REF
:
2298 register rtx plus0
= XEXP (addr
, 0);
2299 register rtx plus1
= XEXP (addr
, 1);
2301 if (GET_CODE (plus0
) != REG
&& GET_CODE (plus1
) == REG
)
2303 plus0
= XEXP (addr
, 1);
2304 plus1
= XEXP (addr
, 0);
2307 if (GET_CODE (plus0
) != REG
)
2310 switch (GET_CODE (plus1
))
2321 return dsp16xx_address_cost (plus1
) + 1;
2330 /* Determine whether a function argument is passed in a register, and
2333 The arguments are CUM, which summarizes all the previous
2334 arguments; MODE, the machine mode of the argument; TYPE,
2335 the data type of the argument as a tree node or 0 if that is not known
2336 (which happens for C support library functions); and NAMED,
2337 which is 1 for an ordinary argument and 0 for nameless arguments that
2338 correspond to `...' in the called function's prototype.
2340 The value of the expression should either be a `reg' RTX for the
2341 hard register in which to pass the argument, or zero to pass the
2342 argument on the stack.
2344 On the dsp1610 the first four words of args are normally in registers
2345 and the rest are pushed. If we a long or on float mode, the argument
2346 must begin on an even register boundary
2348 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2349 For structures that are passed in memory, but could have been
2350 passed in registers, we first load the structure into the
2351 register, and then when the last argument is passed, we store
2352 the registers into the stack locations. This fixes some bugs
2353 where GCC did not expect to have register arguments, followed. */
2356 dsp16xx_function_arg (args_so_far
, mode
, type
, named
)
2357 CUMULATIVE_ARGS args_so_far
;
2358 enum machine_mode mode
;
2364 if ((args_so_far
& 1) != 0
2365 && (mode
== HImode
|| GET_MODE_CLASS(mode
) == MODE_FLOAT
))
2368 if (type
== void_type_node
)
2369 return (struct rtx_def
*) 0;
2371 if (named
&& args_so_far
< 4 && !MUST_PASS_IN_STACK (mode
,type
))
2372 return gen_rtx_REG (mode
, args_so_far
+ FIRST_REG_FOR_FUNCTION_ARG
);
2374 return (struct rtx_def
*) 0;
2377 return (struct rtx_def
*) 0;
2380 /* Advance the argument to the next argument position. */
2383 dsp16xx_function_arg_advance (cum
, mode
, type
, named
)
2384 CUMULATIVE_ARGS
*cum
; /* current arg information */
2385 enum machine_mode mode
; /* current arg mode */
2386 tree type
; /* type of the argument or 0 if lib support */
2387 int named ATTRIBUTE_UNUSED
;/* whether or not the argument was named */
2392 && (mode
== HImode
|| GET_MODE_CLASS(mode
) == MODE_FLOAT
))
2395 if (mode
!= BLKmode
)
2396 *cum
+= GET_MODE_SIZE (mode
);
2398 *cum
+= int_size_in_bytes (type
);
2403 coff_dsp16xx_file_start (file
)
2406 fprintf (file
, "#include <%s.h>\n", save_chip_name
);
2410 luxworks_dsp16xx_file_start (file
)
2413 char *temp_filename
;
2417 fprintf (file
, "\t.debug ");
2418 err_code
= (TARGET_DEBUG
) ? fprintf (file
, "yes, ") : fprintf (file
, "no, ");
2419 err_code
= (TARGET_SAVE_TEMPS
) ? fprintf (file
, "asm, ") : fprintf (file
, "temp, ");
2420 len
= strlen (main_input_filename
);
2421 temp_filename
= (char *) xmalloc (len
+ 2);
2422 strcpy (temp_filename
, main_input_filename
);
2425 while (*p
!= '\0') {
2431 fprintf (file
, "\"%s\"\n", temp_filename
);
2433 fprintf (file
, "#include <%s.h>\n", save_chip_name
);
2436 * Add dummy sections, so that they always exist in the
2437 * object code. These have been created so that the number and
2438 * type of sections remain consistent with and without -g option. Note
2439 * that the .data, .text, .const and .bss are always created when -g
2440 * is provided as an option. */
2441 fprintf (file
, "\t.rsect \".text\" , nodelete\n");
2442 fprintf (file
, "\t.rsect \".data\" , nodelete\n");
2443 fprintf (file
, "\t.rsect \".const\" , nodelete\n");
2444 fprintf (file
, "\t.rsect \".bss\" , nodelete\n");
2451 enum machine_mode mode
;
2453 mode
= GET_MODE (x
);
2456 emit_insn (gen_rtx_PARALLEL
2458 gen_rtvec (2, gen_rtx_SET (VOIDmode
, cc0_rtx
, x
),
2459 gen_rtx_CLOBBER (VOIDmode
,
2460 gen_rtx_SCRATCH (QImode
)))));
2461 else if (mode
== HImode
)
2462 emit_insn (gen_rtx_SET (VOIDmode
, cc0_rtx
, x
));
2464 fatal_error ("invalid mode for gen_tst_reg");
2470 gen_compare_reg (code
, x
, y
)
2474 enum machine_mode mode
;
2476 mode
= GET_MODE (x
);
2477 /* For floating point compare insns, a call is generated so don't
2478 do anything here. */
2480 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
)
2485 if (code
== GTU
|| code
== GEU
2486 || code
== LTU
|| code
== LEU
)
2488 emit_insn (gen_rtx_PARALLEL
2491 gen_rtx_SET (VOIDmode
, cc0_rtx
,
2492 gen_rtx_COMPARE (mode
, x
, y
)),
2493 gen_rtx_CLOBBER (VOIDmode
,
2494 gen_rtx_SCRATCH (QImode
)),
2495 gen_rtx_CLOBBER (VOIDmode
,
2496 gen_rtx_SCRATCH (QImode
)))));
2500 emit_insn (gen_rtx_PARALLEL
2502 gen_rtvec (3, gen_rtx_SET (VOIDmode
, cc0_rtx
,
2503 gen_rtx_COMPARE (mode
, x
, y
)),
2504 gen_rtx_CLOBBER (VOIDmode
,
2505 gen_rtx_SCRATCH (QImode
)),
2506 gen_rtx_CLOBBER (VOIDmode
,
2507 gen_rtx_SCRATCH (QImode
)))));
2510 else if (mode
== HImode
)
2512 if (code
== GTU
|| code
== GEU
2513 || code
== LTU
|| code
== LEU
)
2515 emit_insn (gen_rtx_PARALLEL
2518 gen_rtx_SET (VOIDmode
, cc0_rtx
,
2519 gen_rtx_COMPARE (VOIDmode
, x
, y
)),
2520 gen_rtx_CLOBBER (VOIDmode
,
2521 gen_rtx_SCRATCH (QImode
)),
2522 gen_rtx_CLOBBER (VOIDmode
,
2523 gen_rtx_SCRATCH (QImode
)),
2524 gen_rtx_CLOBBER (VOIDmode
,
2525 gen_rtx_SCRATCH (QImode
)),
2526 gen_rtx_CLOBBER (VOIDmode
,
2527 gen_rtx_SCRATCH (QImode
)))));
2530 emit_insn (gen_rtx_SET (VOIDmode
, cc0_rtx
,
2531 gen_rtx_COMPARE (VOIDmode
,
2532 force_reg (HImode
, x
),
2533 force_reg (HImode
,y
))));
2536 fatal_error ("invalid mode for integer comparison in gen_compare_reg");
2542 output_block_move (operands
)
2545 int loop_count
= INTVAL(operands
[2]);
2548 fprintf (asm_out_file
, "\tdo %d {\n", loop_count
);
2549 xoperands
[0] = operands
[4];
2550 xoperands
[1] = operands
[1];
2551 output_asm_insn ("%0=*%1++", xoperands
);
2553 xoperands
[0] = operands
[0];
2554 xoperands
[1] = operands
[4];
2555 output_asm_insn ("*%0++=%1", xoperands
);
2557 fprintf (asm_out_file
, "\t}\n");
2562 uns_comparison_operator (op
, mode
)
2564 enum machine_mode mode
;
2566 if (mode
== VOIDmode
|| GET_MODE (op
) == mode
)
2570 code
= GET_CODE(op
);
2572 if (code
== LEU
|| code
== LTU
|| code
== GEU
2585 signed_comparison_operator (op
, mode
)
2587 enum machine_mode mode
;
2589 if (mode
== VOIDmode
|| GET_MODE (op
) == mode
)
2593 code
= GET_CODE(op
);
2595 if (!(code
== LEU
|| code
== LTU
|| code
== GEU