1 /* Subroutines used for code generation on Vitesse IQ2000 processors
2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to
18 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
23 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
34 #include "insn-attr.h"
47 #include "target-def.h"
48 #include "langhooks.h"
50 /* Enumeration for all of the relational tests, so that we can build
51 arrays indexed by the test type, and not worry about the order
72 /* Structure to be filled in by compute_frame_size with register
73 save masks, and offsets for the current function. */
75 struct iq2000_frame_info
77 long total_size
; /* # bytes that the entire frame takes up. */
78 long var_size
; /* # bytes that variables take up. */
79 long args_size
; /* # bytes that outgoing arguments take up. */
80 long extra_size
; /* # bytes of extra gunk. */
81 int gp_reg_size
; /* # bytes needed to store gp regs. */
82 int fp_reg_size
; /* # bytes needed to store fp regs. */
83 long mask
; /* Mask of saved gp registers. */
84 long gp_save_offset
; /* Offset from vfp to store gp registers. */
85 long fp_save_offset
; /* Offset from vfp to store fp registers. */
86 long gp_sp_offset
; /* Offset from new sp to store gp registers. */
87 long fp_sp_offset
; /* Offset from new sp to store fp registers. */
88 int initialized
; /* != 0 if frame size already calculated. */
89 int num_gp
; /* Number of gp registers saved. */
92 struct machine_function
GTY(())
94 /* Current frame information, calculated by compute_frame_size. */
95 long total_size
; /* # bytes that the entire frame takes up. */
96 long var_size
; /* # bytes that variables take up. */
97 long args_size
; /* # bytes that outgoing arguments take up. */
98 long extra_size
; /* # bytes of extra gunk. */
99 int gp_reg_size
; /* # bytes needed to store gp regs. */
100 int fp_reg_size
; /* # bytes needed to store fp regs. */
101 long mask
; /* Mask of saved gp registers. */
102 long gp_save_offset
; /* Offset from vfp to store gp registers. */
103 long fp_save_offset
; /* Offset from vfp to store fp registers. */
104 long gp_sp_offset
; /* Offset from new sp to store gp registers. */
105 long fp_sp_offset
; /* Offset from new sp to store fp registers. */
106 int initialized
; /* != 0 if frame size already calculated. */
107 int num_gp
; /* Number of gp registers saved. */
110 /* Global variables for machine-dependent things. */
112 /* List of all IQ2000 punctuation characters used by print_operand. */
113 char iq2000_print_operand_punct
[256];
115 /* The target cpu for optimization and scheduling. */
116 enum processor_type iq2000_tune
;
118 /* Which instruction set architecture to use. */
121 /* Cached operands, and operator to compare for use in set/branch/trap
122 on condition codes. */
125 /* What type of branch to use. */
126 enum cmp_type branch_type
;
128 /* Local variables. */
130 /* The next branch instruction is a branch likely, not branch normal. */
131 static int iq2000_branch_likely
;
133 /* Count of delay slots and how many are filled. */
134 static int dslots_load_total
;
135 static int dslots_load_filled
;
136 static int dslots_jump_total
;
138 /* # of nops needed by previous insn. */
139 static int dslots_number_nops
;
141 /* Number of 1/2/3 word references to data items (i.e., not jal's). */
142 static int num_refs
[3];
144 /* Registers to check for load delay. */
145 static rtx iq2000_load_reg
;
146 static rtx iq2000_load_reg2
;
147 static rtx iq2000_load_reg3
;
148 static rtx iq2000_load_reg4
;
150 /* Mode used for saving/restoring general purpose registers. */
151 static enum machine_mode gpr_mode
;
154 /* Initialize the GCC target structure. */
155 static struct machine_function
* iq2000_init_machine_status (void);
156 static bool iq2000_handle_option (size_t, const char *, int);
157 static section
*iq2000_select_rtx_section (enum machine_mode
, rtx
,
158 unsigned HOST_WIDE_INT
);
159 static void iq2000_init_builtins (void);
160 static rtx
iq2000_expand_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
161 static bool iq2000_return_in_memory (tree
, tree
);
162 static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS
*,
163 enum machine_mode
, tree
, int *,
165 static bool iq2000_rtx_costs (rtx
, int, int, int *);
166 static int iq2000_address_cost (rtx
);
167 static section
*iq2000_select_section (tree
, int, unsigned HOST_WIDE_INT
);
168 static bool iq2000_return_in_memory (tree
, tree
);
169 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS
*, enum machine_mode
,
171 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS
*, enum machine_mode
,
174 #undef TARGET_INIT_BUILTINS
175 #define TARGET_INIT_BUILTINS iq2000_init_builtins
176 #undef TARGET_EXPAND_BUILTIN
177 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin
178 #undef TARGET_ASM_SELECT_RTX_SECTION
179 #define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section
180 #undef TARGET_HANDLE_OPTION
181 #define TARGET_HANDLE_OPTION iq2000_handle_option
182 #undef TARGET_RTX_COSTS
183 #define TARGET_RTX_COSTS iq2000_rtx_costs
184 #undef TARGET_ADDRESS_COST
185 #define TARGET_ADDRESS_COST iq2000_address_cost
186 #undef TARGET_ASM_SELECT_SECTION
187 #define TARGET_ASM_SELECT_SECTION iq2000_select_section
189 #undef TARGET_PROMOTE_FUNCTION_ARGS
190 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
191 #undef TARGET_PROMOTE_FUNCTION_RETURN
192 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
193 #undef TARGET_PROMOTE_PROTOTYPES
194 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
196 #undef TARGET_RETURN_IN_MEMORY
197 #define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
198 #undef TARGET_PASS_BY_REFERENCE
199 #define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference
200 #undef TARGET_CALLEE_COPIES
201 #define TARGET_CALLEE_COPIES hook_callee_copies_named
202 #undef TARGET_ARG_PARTIAL_BYTES
203 #define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes
205 #undef TARGET_SETUP_INCOMING_VARARGS
206 #define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs
207 #undef TARGET_STRICT_ARGUMENT_NAMING
208 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
210 struct gcc_target targetm
= TARGET_INITIALIZER
;
212 /* Return nonzero if we split the address into high and low parts. */
215 iq2000_check_split (rtx address
, enum machine_mode mode
)
217 /* This is the same check used in simple_memory_operand.
218 We use it here because LO_SUM is not offsettable. */
219 if (GET_MODE_SIZE (mode
) > (unsigned) UNITS_PER_WORD
)
222 if ((GET_CODE (address
) == SYMBOL_REF
)
223 || (GET_CODE (address
) == CONST
224 && GET_CODE (XEXP (XEXP (address
, 0), 0)) == SYMBOL_REF
)
225 || GET_CODE (address
) == LABEL_REF
)
231 /* Return nonzero if REG is valid for MODE. */
234 iq2000_reg_mode_ok_for_base_p (rtx reg
,
235 enum machine_mode mode ATTRIBUTE_UNUSED
,
239 ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg
), mode
)
240 : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg
), mode
));
243 /* Return a nonzero value if XINSN is a legitimate address for a
244 memory operand of the indicated MODE. STRICT is nonzero if this
245 function is called during reload. */
248 iq2000_legitimate_address_p (enum machine_mode mode
, rtx xinsn
, int strict
)
250 if (TARGET_DEBUG_A_MODE
)
252 GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
253 strict
? "" : "not ");
254 GO_DEBUG_RTX (xinsn
);
257 /* Check for constant before stripping off SUBREG, so that we don't
258 accept (subreg (const_int)) which will fail to reload. */
259 if (CONSTANT_ADDRESS_P (xinsn
)
260 && ! (iq2000_check_split (xinsn
, mode
))
261 && ! (GET_CODE (xinsn
) == CONST_INT
&& ! SMALL_INT (xinsn
)))
264 while (GET_CODE (xinsn
) == SUBREG
)
265 xinsn
= SUBREG_REG (xinsn
);
267 if (GET_CODE (xinsn
) == REG
268 && iq2000_reg_mode_ok_for_base_p (xinsn
, mode
, strict
))
271 if (GET_CODE (xinsn
) == LO_SUM
)
273 rtx xlow0
= XEXP (xinsn
, 0);
274 rtx xlow1
= XEXP (xinsn
, 1);
276 while (GET_CODE (xlow0
) == SUBREG
)
277 xlow0
= SUBREG_REG (xlow0
);
278 if (GET_CODE (xlow0
) == REG
279 && iq2000_reg_mode_ok_for_base_p (xlow0
, mode
, strict
)
280 && iq2000_check_split (xlow1
, mode
))
284 if (GET_CODE (xinsn
) == PLUS
)
286 rtx xplus0
= XEXP (xinsn
, 0);
287 rtx xplus1
= XEXP (xinsn
, 1);
291 while (GET_CODE (xplus0
) == SUBREG
)
292 xplus0
= SUBREG_REG (xplus0
);
293 code0
= GET_CODE (xplus0
);
295 while (GET_CODE (xplus1
) == SUBREG
)
296 xplus1
= SUBREG_REG (xplus1
);
297 code1
= GET_CODE (xplus1
);
300 && iq2000_reg_mode_ok_for_base_p (xplus0
, mode
, strict
))
302 if (code1
== CONST_INT
&& SMALL_INT (xplus1
)
303 && SMALL_INT_UNSIGNED (xplus1
) /* No negative offsets */)
308 if (TARGET_DEBUG_A_MODE
)
309 GO_PRINTF ("Not a legitimate address\n");
311 /* The address was not legitimate. */
315 /* Returns an operand string for the given instruction's delay slot,
316 after updating filled delay slot statistics.
318 We assume that operands[0] is the target register that is set.
320 In order to check the next insn, most of this functionality is moved
321 to FINAL_PRESCAN_INSN, and we just set the global variables that
325 iq2000_fill_delay_slot (const char *ret
, enum delay_type type
, rtx operands
[],
329 enum machine_mode mode
;
330 rtx next_insn
= cur_insn
? NEXT_INSN (cur_insn
) : NULL_RTX
;
333 if (type
== DELAY_LOAD
|| type
== DELAY_FCMP
)
339 /* Make sure that we don't put nop's after labels. */
340 next_insn
= NEXT_INSN (cur_insn
);
341 while (next_insn
!= 0
342 && (GET_CODE (next_insn
) == NOTE
343 || GET_CODE (next_insn
) == CODE_LABEL
))
344 next_insn
= NEXT_INSN (next_insn
);
346 dslots_load_total
+= num_nops
;
347 if (TARGET_DEBUG_C_MODE
348 || type
== DELAY_NONE
352 || GET_CODE (next_insn
) == CODE_LABEL
353 || (set_reg
= operands
[0]) == 0)
355 dslots_number_nops
= 0;
357 iq2000_load_reg2
= 0;
358 iq2000_load_reg3
= 0;
359 iq2000_load_reg4
= 0;
364 set_reg
= operands
[0];
368 while (GET_CODE (set_reg
) == SUBREG
)
369 set_reg
= SUBREG_REG (set_reg
);
371 mode
= GET_MODE (set_reg
);
372 dslots_number_nops
= num_nops
;
373 iq2000_load_reg
= set_reg
;
374 if (GET_MODE_SIZE (mode
)
375 > (unsigned) (UNITS_PER_WORD
))
376 iq2000_load_reg2
= gen_rtx_REG (SImode
, REGNO (set_reg
) + 1);
378 iq2000_load_reg2
= 0;
383 /* Determine whether a memory reference takes one (based off of the GP
384 pointer), two (normal), or three (label + reg) instructions, and bump the
385 appropriate counter for -mstats. */
388 iq2000_count_memory_refs (rtx op
, int num
)
392 rtx addr
, plus0
, plus1
;
393 enum rtx_code code0
, code1
;
396 if (TARGET_DEBUG_B_MODE
)
398 fprintf (stderr
, "\n========== iq2000_count_memory_refs:\n");
402 /* Skip MEM if passed, otherwise handle movsi of address. */
403 addr
= (GET_CODE (op
) != MEM
) ? op
: XEXP (op
, 0);
405 /* Loop, going through the address RTL. */
409 switch (GET_CODE (addr
))
417 plus0
= XEXP (addr
, 0);
418 plus1
= XEXP (addr
, 1);
419 code0
= GET_CODE (plus0
);
420 code1
= GET_CODE (plus1
);
430 if (code0
== CONST_INT
)
445 if (code1
== CONST_INT
)
452 if (code0
== SYMBOL_REF
|| code0
== LABEL_REF
|| code0
== CONST
)
459 if (code1
== SYMBOL_REF
|| code1
== LABEL_REF
|| code1
== CONST
)
469 n_words
= 2; /* Always 2 words. */
473 addr
= XEXP (addr
, 0);
478 n_words
= SYMBOL_REF_FLAG (addr
) ? 1 : 2;
490 n_words
+= additional
;
494 num_refs
[n_words
-1] += num
;
497 /* Abort after printing out a specific insn. */
500 abort_with_insn (rtx insn
, const char * reason
)
504 fancy_abort (__FILE__
, __LINE__
, __FUNCTION__
);
507 /* Return the appropriate instructions to move one operand to another. */
510 iq2000_move_1word (rtx operands
[], rtx insn
, int unsignedp
)
513 rtx op0
= operands
[0];
514 rtx op1
= operands
[1];
515 enum rtx_code code0
= GET_CODE (op0
);
516 enum rtx_code code1
= GET_CODE (op1
);
517 enum machine_mode mode
= GET_MODE (op0
);
518 int subreg_offset0
= 0;
519 int subreg_offset1
= 0;
520 enum delay_type delay
= DELAY_NONE
;
522 while (code0
== SUBREG
)
524 subreg_offset0
+= subreg_regno_offset (REGNO (SUBREG_REG (op0
)),
525 GET_MODE (SUBREG_REG (op0
)),
528 op0
= SUBREG_REG (op0
);
529 code0
= GET_CODE (op0
);
532 while (code1
== SUBREG
)
534 subreg_offset1
+= subreg_regno_offset (REGNO (SUBREG_REG (op1
)),
535 GET_MODE (SUBREG_REG (op1
)),
538 op1
= SUBREG_REG (op1
);
539 code1
= GET_CODE (op1
);
542 /* For our purposes, a condition code mode is the same as SImode. */
548 int regno0
= REGNO (op0
) + subreg_offset0
;
552 int regno1
= REGNO (op1
) + subreg_offset1
;
554 /* Do not do anything for assigning a register to itself */
555 if (regno0
== regno1
)
558 else if (GP_REG_P (regno0
))
560 if (GP_REG_P (regno1
))
561 ret
= "or\t%0,%%0,%1";
566 else if (code1
== MEM
)
571 iq2000_count_memory_refs (op1
, 1);
573 if (GP_REG_P (regno0
))
575 /* For loads, use the mode of the memory item, instead of the
576 target, so zero/sign extend can use this code as well. */
577 switch (GET_MODE (op1
))
589 ret
= (unsignedp
) ? "lhu\t%0,%1" : "lh\t%0,%1";
592 ret
= (unsignedp
) ? "lbu\t%0,%1" : "lb\t%0,%1";
598 else if (code1
== CONST_INT
599 || (code1
== CONST_DOUBLE
600 && GET_MODE (op1
) == VOIDmode
))
602 if (code1
== CONST_DOUBLE
)
604 /* This can happen when storing constants into long long
605 bitfields. Just store the least significant word of
607 operands
[1] = op1
= GEN_INT (CONST_DOUBLE_LOW (op1
));
610 if (INTVAL (op1
) == 0)
612 if (GP_REG_P (regno0
))
613 ret
= "or\t%0,%%0,%z1";
615 else if (GP_REG_P (regno0
))
617 if (SMALL_INT_UNSIGNED (op1
))
618 ret
= "ori\t%0,%%0,%x1\t\t\t# %1";
619 else if (SMALL_INT (op1
))
620 ret
= "addiu\t%0,%%0,%1\t\t\t# %1";
622 ret
= "lui\t%0,%X1\t\t\t# %1\n\tori\t%0,%0,%x1";
626 else if (code1
== CONST_DOUBLE
&& mode
== SFmode
)
628 if (op1
== CONST0_RTX (SFmode
))
630 if (GP_REG_P (regno0
))
631 ret
= "or\t%0,%%0,%.";
641 else if (code1
== LABEL_REF
)
644 iq2000_count_memory_refs (op1
, 1);
649 else if (code1
== SYMBOL_REF
|| code1
== CONST
)
652 iq2000_count_memory_refs (op1
, 1);
657 else if (code1
== PLUS
)
659 rtx add_op0
= XEXP (op1
, 0);
660 rtx add_op1
= XEXP (op1
, 1);
662 if (GET_CODE (XEXP (op1
, 1)) == REG
663 && GET_CODE (XEXP (op1
, 0)) == CONST_INT
)
664 add_op0
= XEXP (op1
, 1), add_op1
= XEXP (op1
, 0);
666 operands
[2] = add_op0
;
667 operands
[3] = add_op1
;
668 ret
= "add%:\t%0,%2,%3";
671 else if (code1
== HIGH
)
673 operands
[1] = XEXP (op1
, 0);
674 ret
= "lui\t%0,%%hi(%1)";
678 else if (code0
== MEM
)
681 iq2000_count_memory_refs (op0
, 1);
685 int regno1
= REGNO (op1
) + subreg_offset1
;
687 if (GP_REG_P (regno1
))
691 case SFmode
: ret
= "sw\t%1,%0"; break;
692 case SImode
: ret
= "sw\t%1,%0"; break;
693 case HImode
: ret
= "sh\t%1,%0"; break;
694 case QImode
: ret
= "sb\t%1,%0"; break;
700 else if (code1
== CONST_INT
&& INTVAL (op1
) == 0)
704 case SFmode
: ret
= "sw\t%z1,%0"; break;
705 case SImode
: ret
= "sw\t%z1,%0"; break;
706 case HImode
: ret
= "sh\t%z1,%0"; break;
707 case QImode
: ret
= "sb\t%z1,%0"; break;
712 else if (code1
== CONST_DOUBLE
&& op1
== CONST0_RTX (mode
))
716 case SFmode
: ret
= "sw\t%.,%0"; break;
717 case SImode
: ret
= "sw\t%.,%0"; break;
718 case HImode
: ret
= "sh\t%.,%0"; break;
719 case QImode
: ret
= "sb\t%.,%0"; break;
727 abort_with_insn (insn
, "Bad move");
731 if (delay
!= DELAY_NONE
)
732 return iq2000_fill_delay_slot (ret
, delay
, operands
, insn
);
737 /* Provide the costs of an addressing mode that contains ADDR. */
740 iq2000_address_cost (rtx addr
)
742 switch (GET_CODE (addr
))
752 rtx offset
= const0_rtx
;
754 addr
= eliminate_constant_term (XEXP (addr
, 0), & offset
);
755 if (GET_CODE (addr
) == LABEL_REF
)
758 if (GET_CODE (addr
) != SYMBOL_REF
)
761 if (! SMALL_INT (offset
))
768 return SYMBOL_REF_FLAG (addr
) ? 1 : 2;
772 rtx plus0
= XEXP (addr
, 0);
773 rtx plus1
= XEXP (addr
, 1);
775 if (GET_CODE (plus0
) != REG
&& GET_CODE (plus1
) == REG
)
776 plus0
= XEXP (addr
, 1), plus1
= XEXP (addr
, 0);
778 if (GET_CODE (plus0
) != REG
)
781 switch (GET_CODE (plus1
))
784 return SMALL_INT (plus1
) ? 1 : 2;
791 return iq2000_address_cost (plus1
) + 1;
805 /* Make normal rtx_code into something we can index from an array. */
807 static enum internal_test
808 map_test_to_internal_test (enum rtx_code test_code
)
810 enum internal_test test
= ITEST_MAX
;
814 case EQ
: test
= ITEST_EQ
; break;
815 case NE
: test
= ITEST_NE
; break;
816 case GT
: test
= ITEST_GT
; break;
817 case GE
: test
= ITEST_GE
; break;
818 case LT
: test
= ITEST_LT
; break;
819 case LE
: test
= ITEST_LE
; break;
820 case GTU
: test
= ITEST_GTU
; break;
821 case GEU
: test
= ITEST_GEU
; break;
822 case LTU
: test
= ITEST_LTU
; break;
823 case LEU
: test
= ITEST_LEU
; break;
830 /* Generate the code to do a TEST_CODE comparison on two integer values CMP0
831 and CMP1. P_INVERT is NULL or ptr if branch needs to reverse its test.
832 The return value RESULT is:
833 (reg:SI xx) The pseudo register the comparison is in
834 0 No register, generate a simple branch. */
837 gen_int_relational (enum rtx_code test_code
, rtx result
, rtx cmp0
, rtx cmp1
,
842 enum rtx_code test_code
; /* Code to use in instruction (LT vs. LTU). */
843 int const_low
; /* Low bound of constant we can accept. */
844 int const_high
; /* High bound of constant we can accept. */
845 int const_add
; /* Constant to add (convert LE -> LT). */
846 int reverse_regs
; /* Reverse registers in test. */
847 int invert_const
; /* != 0 if invert value if cmp1 is constant. */
848 int invert_reg
; /* != 0 if invert value if cmp1 is register. */
849 int unsignedp
; /* != 0 for unsigned comparisons. */
852 static struct cmp_info info
[ (int)ITEST_MAX
] =
854 { XOR
, 0, 65535, 0, 0, 0, 0, 0 }, /* EQ */
855 { XOR
, 0, 65535, 0, 0, 1, 1, 0 }, /* NE */
856 { LT
, -32769, 32766, 1, 1, 1, 0, 0 }, /* GT */
857 { LT
, -32768, 32767, 0, 0, 1, 1, 0 }, /* GE */
858 { LT
, -32768, 32767, 0, 0, 0, 0, 0 }, /* LT */
859 { LT
, -32769, 32766, 1, 1, 0, 1, 0 }, /* LE */
860 { LTU
, -32769, 32766, 1, 1, 1, 0, 1 }, /* GTU */
861 { LTU
, -32768, 32767, 0, 0, 1, 1, 1 }, /* GEU */
862 { LTU
, -32768, 32767, 0, 0, 0, 0, 1 }, /* LTU */
863 { LTU
, -32769, 32766, 1, 1, 0, 1, 1 }, /* LEU */
866 enum internal_test test
;
867 enum machine_mode mode
;
868 struct cmp_info
*p_info
;
875 test
= map_test_to_internal_test (test_code
);
876 gcc_assert (test
!= ITEST_MAX
);
878 p_info
= &info
[(int) test
];
879 eqne_p
= (p_info
->test_code
== XOR
);
881 mode
= GET_MODE (cmp0
);
882 if (mode
== VOIDmode
)
883 mode
= GET_MODE (cmp1
);
885 /* Eliminate simple branches. */
886 branch_p
= (result
== 0);
889 if (GET_CODE (cmp0
) == REG
|| GET_CODE (cmp0
) == SUBREG
)
891 /* Comparisons against zero are simple branches. */
892 if (GET_CODE (cmp1
) == CONST_INT
&& INTVAL (cmp1
) == 0)
895 /* Test for beq/bne. */
900 /* Allocate a pseudo to calculate the value in. */
901 result
= gen_reg_rtx (mode
);
904 /* Make sure we can handle any constants given to us. */
905 if (GET_CODE (cmp0
) == CONST_INT
)
906 cmp0
= force_reg (mode
, cmp0
);
908 if (GET_CODE (cmp1
) == CONST_INT
)
910 HOST_WIDE_INT value
= INTVAL (cmp1
);
912 if (value
< p_info
->const_low
913 || value
> p_info
->const_high
)
914 cmp1
= force_reg (mode
, cmp1
);
917 /* See if we need to invert the result. */
918 invert
= (GET_CODE (cmp1
) == CONST_INT
919 ? p_info
->invert_const
: p_info
->invert_reg
);
921 if (p_invert
!= (int *)0)
927 /* Comparison to constants, may involve adding 1 to change a LT into LE.
928 Comparison between two registers, may involve switching operands. */
929 if (GET_CODE (cmp1
) == CONST_INT
)
931 if (p_info
->const_add
!= 0)
933 HOST_WIDE_INT
new = INTVAL (cmp1
) + p_info
->const_add
;
935 /* If modification of cmp1 caused overflow,
936 we would get the wrong answer if we follow the usual path;
937 thus, x > 0xffffffffU would turn into x > 0U. */
938 if ((p_info
->unsignedp
939 ? (unsigned HOST_WIDE_INT
) new >
940 (unsigned HOST_WIDE_INT
) INTVAL (cmp1
)
941 : new > INTVAL (cmp1
))
942 != (p_info
->const_add
> 0))
944 /* This test is always true, but if INVERT is true then
945 the result of the test needs to be inverted so 0 should
946 be returned instead. */
947 emit_move_insn (result
, invert
? const0_rtx
: const_true_rtx
);
951 cmp1
= GEN_INT (new);
955 else if (p_info
->reverse_regs
)
962 if (test
== ITEST_NE
&& GET_CODE (cmp1
) == CONST_INT
&& INTVAL (cmp1
) == 0)
966 reg
= (invert
|| eqne_p
) ? gen_reg_rtx (mode
) : result
;
967 convert_move (reg
, gen_rtx_fmt_ee (p_info
->test_code
, mode
, cmp0
, cmp1
), 0);
970 if (test
== ITEST_NE
)
972 convert_move (result
, gen_rtx_GTU (mode
, reg
, const0_rtx
), 0);
973 if (p_invert
!= NULL
)
978 else if (test
== ITEST_EQ
)
980 reg2
= invert
? gen_reg_rtx (mode
) : result
;
981 convert_move (reg2
, gen_rtx_LTU (mode
, reg
, const1_rtx
), 0);
990 convert_move (result
, gen_rtx_XOR (mode
, reg
, one
), 0);
996 /* Emit the common code for doing conditional branches.
997 operand[0] is the label to jump to.
998 The comparison operands are saved away by cmp{si,di,sf,df}. */
1001 gen_conditional_branch (rtx operands
[], enum rtx_code test_code
)
1003 enum cmp_type type
= branch_type
;
1004 rtx cmp0
= branch_cmp
[0];
1005 rtx cmp1
= branch_cmp
[1];
1006 enum machine_mode mode
;
1015 mode
= type
== CMP_SI
? SImode
: DImode
;
1017 reg
= gen_int_relational (test_code
, NULL_RTX
, cmp0
, cmp1
, &invert
);
1025 else if (GET_CODE (cmp1
) == CONST_INT
&& INTVAL (cmp1
) != 0)
1026 /* We don't want to build a comparison against a nonzero
1028 cmp1
= force_reg (mode
, cmp1
);
1034 reg
= gen_reg_rtx (CCmode
);
1036 /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */
1037 emit_insn (gen_rtx_SET (VOIDmode
, reg
,
1038 gen_rtx_fmt_ee (test_code
== NE
? EQ
: test_code
,
1039 CCmode
, cmp0
, cmp1
)));
1041 test_code
= test_code
== NE
? EQ
: NE
;
1049 abort_with_insn (gen_rtx_fmt_ee (test_code
, VOIDmode
, cmp0
, cmp1
),
1053 /* Generate the branch. */
1054 label1
= gen_rtx_LABEL_REF (VOIDmode
, operands
[0]);
1063 emit_jump_insn (gen_rtx_SET (VOIDmode
, pc_rtx
,
1064 gen_rtx_IF_THEN_ELSE (VOIDmode
,
1065 gen_rtx_fmt_ee (test_code
,
1071 /* Initialize CUM for a function FNTYPE. */
1074 init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
,
1075 rtx libname ATTRIBUTE_UNUSED
)
1077 static CUMULATIVE_ARGS zero_cum
;
1081 if (TARGET_DEBUG_D_MODE
)
1084 "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype
);
1087 fputc ('\n', stderr
);
1091 tree ret_type
= TREE_TYPE (fntype
);
1093 fprintf (stderr
, ", fntype code = %s, ret code = %s\n",
1094 tree_code_name
[(int)TREE_CODE (fntype
)],
1095 tree_code_name
[(int)TREE_CODE (ret_type
)]);
1101 /* Determine if this function has variable arguments. This is
1102 indicated by the last argument being 'void_type_mode' if there
1103 are no variable arguments. The standard IQ2000 calling sequence
1104 passes all arguments in the general purpose registers in this case. */
1106 for (param
= fntype
? TYPE_ARG_TYPES (fntype
) : 0;
1107 param
!= 0; param
= next_param
)
1109 next_param
= TREE_CHAIN (param
);
1110 if (next_param
== 0 && TREE_VALUE (param
) != void_type_node
)
1111 cum
->gp_reg_found
= 1;
1115 /* Advance the argument of type TYPE and mode MODE to the next argument
1119 function_arg_advance (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1122 if (TARGET_DEBUG_D_MODE
)
1125 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1126 cum
->gp_reg_found
, cum
->arg_number
, cum
->arg_words
,
1127 GET_MODE_NAME (mode
));
1128 fprintf (stderr
, "%p", (void *) type
);
1129 fprintf (stderr
, ", %d )\n\n", named
);
1139 gcc_assert (GET_MODE_CLASS (mode
) == MODE_COMPLEX_INT
1140 || GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
);
1142 cum
->gp_reg_found
= 1;
1143 cum
->arg_words
+= ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
1148 cum
->gp_reg_found
= 1;
1149 cum
->arg_words
+= ((int_size_in_bytes (type
) + UNITS_PER_WORD
- 1)
1155 if (! cum
->gp_reg_found
&& cum
->arg_number
<= 2)
1156 cum
->fp_code
+= 1 << ((cum
->arg_number
- 1) * 2);
1160 cum
->arg_words
+= 2;
1161 if (! cum
->gp_reg_found
&& cum
->arg_number
<= 2)
1162 cum
->fp_code
+= 2 << ((cum
->arg_number
- 1) * 2);
1166 cum
->gp_reg_found
= 1;
1167 cum
->arg_words
+= 2;
1173 cum
->gp_reg_found
= 1;
1179 /* Return an RTL expression containing the register for the given mode MODE
1180 and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */
1183 function_arg (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1189 unsigned int *arg_words
= &cum
->arg_words
;
1190 int struct_p
= (type
!= 0
1191 && (TREE_CODE (type
) == RECORD_TYPE
1192 || TREE_CODE (type
) == UNION_TYPE
1193 || TREE_CODE (type
) == QUAL_UNION_TYPE
));
1195 if (TARGET_DEBUG_D_MODE
)
1198 "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1199 cum
->gp_reg_found
, cum
->arg_number
, cum
->arg_words
,
1200 GET_MODE_NAME (mode
));
1201 fprintf (stderr
, "%p", (void *) type
);
1202 fprintf (stderr
, ", %d ) = ", named
);
1206 cum
->last_arg_fp
= 0;
1210 regbase
= GP_ARG_FIRST
;
1214 cum
->arg_words
+= cum
->arg_words
& 1;
1216 regbase
= GP_ARG_FIRST
;
1220 gcc_assert (GET_MODE_CLASS (mode
) == MODE_COMPLEX_INT
1221 || GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
);
1223 /* Drops through. */
1225 if (type
!= NULL_TREE
&& TYPE_ALIGN (type
) > (unsigned) BITS_PER_WORD
)
1226 cum
->arg_words
+= (cum
->arg_words
& 1);
1227 regbase
= GP_ARG_FIRST
;
1234 regbase
= GP_ARG_FIRST
;
1238 cum
->arg_words
+= (cum
->arg_words
& 1);
1239 regbase
= GP_ARG_FIRST
;
1242 if (*arg_words
>= (unsigned) MAX_ARGS_IN_REGISTERS
)
1244 if (TARGET_DEBUG_D_MODE
)
1245 fprintf (stderr
, "<stack>%s\n", struct_p
? ", [struct]" : "");
1251 gcc_assert (regbase
!= -1);
1253 if (! type
|| TREE_CODE (type
) != RECORD_TYPE
1254 || ! named
|| ! TYPE_SIZE_UNIT (type
)
1255 || ! host_integerp (TYPE_SIZE_UNIT (type
), 1))
1256 ret
= gen_rtx_REG (mode
, regbase
+ *arg_words
+ bias
);
1261 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
1262 if (TREE_CODE (field
) == FIELD_DECL
1263 && TREE_CODE (TREE_TYPE (field
)) == REAL_TYPE
1264 && TYPE_PRECISION (TREE_TYPE (field
)) == BITS_PER_WORD
1265 && host_integerp (bit_position (field
), 0)
1266 && int_bit_position (field
) % BITS_PER_WORD
== 0)
1269 /* If the whole struct fits a DFmode register,
1270 we don't need the PARALLEL. */
1271 if (! field
|| mode
== DFmode
)
1272 ret
= gen_rtx_REG (mode
, regbase
+ *arg_words
+ bias
);
1275 unsigned int chunks
;
1276 HOST_WIDE_INT bitpos
;
1280 /* ??? If this is a packed structure, then the last hunk won't
1283 = tree_low_cst (TYPE_SIZE_UNIT (type
), 1) / UNITS_PER_WORD
;
1284 if (chunks
+ *arg_words
+ bias
> (unsigned) MAX_ARGS_IN_REGISTERS
)
1285 chunks
= MAX_ARGS_IN_REGISTERS
- *arg_words
- bias
;
1287 /* Assign_parms checks the mode of ENTRY_PARM, so we must
1288 use the actual mode here. */
1289 ret
= gen_rtx_PARALLEL (mode
, rtvec_alloc (chunks
));
1292 regno
= regbase
+ *arg_words
+ bias
;
1293 field
= TYPE_FIELDS (type
);
1294 for (i
= 0; i
< chunks
; i
++)
1298 for (; field
; field
= TREE_CHAIN (field
))
1299 if (TREE_CODE (field
) == FIELD_DECL
1300 && int_bit_position (field
) >= bitpos
)
1304 && int_bit_position (field
) == bitpos
1305 && TREE_CODE (TREE_TYPE (field
)) == REAL_TYPE
1306 && TYPE_PRECISION (TREE_TYPE (field
)) == BITS_PER_WORD
)
1307 reg
= gen_rtx_REG (DFmode
, regno
++);
1309 reg
= gen_rtx_REG (word_mode
, regno
);
1312 = gen_rtx_EXPR_LIST (VOIDmode
, reg
,
1313 GEN_INT (bitpos
/ BITS_PER_UNIT
));
1321 if (TARGET_DEBUG_D_MODE
)
1322 fprintf (stderr
, "%s%s\n", reg_names
[regbase
+ *arg_words
+ bias
],
1323 struct_p
? ", [struct]" : "");
1326 /* We will be called with a mode of VOIDmode after the last argument
1327 has been seen. Whatever we return will be passed to the call
1328 insn. If we need any shifts for small structures, return them in
1330 if (mode
== VOIDmode
)
1332 if (cum
->num_adjusts
> 0)
1333 ret
= gen_rtx_PARALLEL ((enum machine_mode
) cum
->fp_code
,
1334 gen_rtvec_v (cum
->num_adjusts
, cum
->adjust
));
1341 iq2000_arg_partial_bytes (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
,
1342 tree type ATTRIBUTE_UNUSED
,
1343 bool named ATTRIBUTE_UNUSED
)
1345 if (mode
== DImode
&& cum
->arg_words
== MAX_ARGS_IN_REGISTERS
- 1)
1347 if (TARGET_DEBUG_D_MODE
)
1348 fprintf (stderr
, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD
);
1349 return UNITS_PER_WORD
;
1355 /* Implement va_start. */
1358 iq2000_va_start (tree valist
, rtx nextarg
)
1361 /* Find out how many non-float named formals. */
1362 int gpr_save_area_size
;
1363 /* Note UNITS_PER_WORD is 4 bytes. */
1364 int_arg_words
= current_function_args_info
.arg_words
;
1366 if (int_arg_words
< 8 )
1367 /* Adjust for the prologue's economy measure. */
1368 gpr_save_area_size
= (8 - int_arg_words
) * UNITS_PER_WORD
;
1370 gpr_save_area_size
= 0;
1372 /* Everything is in the GPR save area, or in the overflow
1373 area which is contiguous with it. */
1374 nextarg
= plus_constant (nextarg
, - gpr_save_area_size
);
1375 std_expand_builtin_va_start (valist
, nextarg
);
1378 /* Allocate a chunk of memory for per-function machine-dependent data. */
1380 static struct machine_function
*
1381 iq2000_init_machine_status (void)
1383 struct machine_function
*f
;
1385 f
= ggc_alloc_cleared (sizeof (struct machine_function
));
1390 /* Implement TARGET_HANDLE_OPTION. */
1393 iq2000_handle_option (size_t code
, const char *arg
, int value ATTRIBUTE_UNUSED
)
1398 if (strcmp (arg
, "iq10") == 0)
1399 iq2000_tune
= PROCESSOR_IQ10
;
1400 else if (strcmp (arg
, "iq2000") == 0)
1401 iq2000_tune
= PROCESSOR_IQ2000
;
1407 /* This option has no effect at the moment. */
1408 return (strcmp (arg
, "default") == 0
1409 || strcmp (arg
, "DEFAULT") == 0
1410 || strcmp (arg
, "iq2000") == 0);
1417 /* Detect any conflicts in the switches. */
1420 override_options (void)
1422 target_flags
&= ~MASK_GPOPT
;
1424 iq2000_isa
= IQ2000_ISA_DEFAULT
;
1426 /* Identify the processor type. */
1428 iq2000_print_operand_punct
['?'] = 1;
1429 iq2000_print_operand_punct
['#'] = 1;
1430 iq2000_print_operand_punct
['&'] = 1;
1431 iq2000_print_operand_punct
['!'] = 1;
1432 iq2000_print_operand_punct
['*'] = 1;
1433 iq2000_print_operand_punct
['@'] = 1;
1434 iq2000_print_operand_punct
['.'] = 1;
1435 iq2000_print_operand_punct
['('] = 1;
1436 iq2000_print_operand_punct
[')'] = 1;
1437 iq2000_print_operand_punct
['['] = 1;
1438 iq2000_print_operand_punct
[']'] = 1;
1439 iq2000_print_operand_punct
['<'] = 1;
1440 iq2000_print_operand_punct
['>'] = 1;
1441 iq2000_print_operand_punct
['{'] = 1;
1442 iq2000_print_operand_punct
['}'] = 1;
1443 iq2000_print_operand_punct
['^'] = 1;
1444 iq2000_print_operand_punct
['$'] = 1;
1445 iq2000_print_operand_punct
['+'] = 1;
1446 iq2000_print_operand_punct
['~'] = 1;
1448 /* Save GPR registers in word_mode sized hunks. word_mode hasn't been
1449 initialized yet, so we can't use that here. */
1452 /* Function to allocate machine-dependent function status. */
1453 init_machine_status
= iq2000_init_machine_status
;
1456 /* The arg pointer (which is eliminated) points to the virtual frame pointer,
1457 while the frame pointer (which may be eliminated) points to the stack
1458 pointer after the initial adjustments. */
1461 iq2000_debugger_offset (rtx addr
, HOST_WIDE_INT offset
)
1463 rtx offset2
= const0_rtx
;
1464 rtx reg
= eliminate_constant_term (addr
, & offset2
);
1467 offset
= INTVAL (offset2
);
1469 if (reg
== stack_pointer_rtx
|| reg
== frame_pointer_rtx
1470 || reg
== hard_frame_pointer_rtx
)
1472 HOST_WIDE_INT frame_size
= (!cfun
->machine
->initialized
)
1473 ? compute_frame_size (get_frame_size ())
1474 : cfun
->machine
->total_size
;
1476 offset
= offset
- frame_size
;
1482 /* If defined, a C statement to be executed just prior to the output of
1483 assembler code for INSN, to modify the extracted operands so they will be
1486 Here the argument OPVEC is the vector containing the operands extracted
1487 from INSN, and NOPERANDS is the number of elements of the vector which
1488 contain meaningful data for this insn. The contents of this vector are
1489 what will be used to convert the insn template into assembler code, so you
1490 can change the assembler output by changing the contents of the vector.
1492 We use it to check if the current insn needs a nop in front of it because
1493 of load delays, and also to update the delay slot statistics. */
1496 final_prescan_insn (rtx insn
, rtx opvec
[] ATTRIBUTE_UNUSED
,
1497 int noperands ATTRIBUTE_UNUSED
)
1499 if (dslots_number_nops
> 0)
1501 rtx pattern
= PATTERN (insn
);
1502 int length
= get_attr_length (insn
);
1504 /* Do we need to emit a NOP? */
1506 || (iq2000_load_reg
!= 0 && reg_mentioned_p (iq2000_load_reg
, pattern
))
1507 || (iq2000_load_reg2
!= 0 && reg_mentioned_p (iq2000_load_reg2
, pattern
))
1508 || (iq2000_load_reg3
!= 0 && reg_mentioned_p (iq2000_load_reg3
, pattern
))
1509 || (iq2000_load_reg4
!= 0
1510 && reg_mentioned_p (iq2000_load_reg4
, pattern
)))
1511 fputs ("\tnop\n", asm_out_file
);
1514 dslots_load_filled
++;
1516 while (--dslots_number_nops
> 0)
1517 fputs ("\tnop\n", asm_out_file
);
1519 iq2000_load_reg
= 0;
1520 iq2000_load_reg2
= 0;
1521 iq2000_load_reg3
= 0;
1522 iq2000_load_reg4
= 0;
1525 if ( (GET_CODE (insn
) == JUMP_INSN
1526 || GET_CODE (insn
) == CALL_INSN
1527 || (GET_CODE (PATTERN (insn
)) == RETURN
))
1528 && NEXT_INSN (PREV_INSN (insn
)) == insn
)
1530 rtx nop_insn
= emit_insn_after (gen_nop (), insn
);
1532 INSN_ADDRESSES_NEW (nop_insn
, -1);
1536 && (GET_CODE (insn
) == JUMP_INSN
|| GET_CODE (insn
) == CALL_INSN
))
1537 dslots_jump_total
++;
1540 /* Return the bytes needed to compute the frame pointer from the current
1541 stack pointer where SIZE is the # of var. bytes allocated.
1543 IQ2000 stack frames look like:
1545 Before call After call
1546 +-----------------------+ +-----------------------+
1549 | caller's temps. | | caller's temps. |
1551 +-----------------------+ +-----------------------+
1553 | arguments on stack. | | arguments on stack. |
1555 +-----------------------+ +-----------------------+
1556 | 4 words to save | | 4 words to save |
1557 | arguments passed | | arguments passed |
1558 | in registers, even | | in registers, even |
1559 SP->| if not passed. | VFP->| if not passed. |
1560 +-----------------------+ +-----------------------+
1562 | fp register save |
1564 +-----------------------+
1566 | gp register save |
1568 +-----------------------+
1572 +-----------------------+
1574 | alloca allocations |
1576 +-----------------------+
1578 | GP save for V.4 abi |
1580 +-----------------------+
1582 | arguments on stack |
1584 +-----------------------+
1586 | arguments passed |
1587 | in registers, even |
1588 low SP->| if not passed. |
1589 memory +-----------------------+ */
1592 compute_frame_size (HOST_WIDE_INT size
)
1595 HOST_WIDE_INT total_size
; /* # bytes that the entire frame takes up. */
1596 HOST_WIDE_INT var_size
; /* # bytes that variables take up. */
1597 HOST_WIDE_INT args_size
; /* # bytes that outgoing arguments take up. */
1598 HOST_WIDE_INT extra_size
; /* # extra bytes. */
1599 HOST_WIDE_INT gp_reg_rounded
; /* # bytes needed to store gp after rounding. */
1600 HOST_WIDE_INT gp_reg_size
; /* # bytes needed to store gp regs. */
1601 HOST_WIDE_INT fp_reg_size
; /* # bytes needed to store fp regs. */
1602 long mask
; /* mask of saved gp registers. */
1603 int fp_inc
; /* 1 or 2 depending on the size of fp regs. */
1604 long fp_bits
; /* bitmask to use for each fp register. */
1609 extra_size
= IQ2000_STACK_ALIGN ((0));
1610 var_size
= IQ2000_STACK_ALIGN (size
);
1611 args_size
= IQ2000_STACK_ALIGN (current_function_outgoing_args_size
);
1613 /* If a function dynamically allocates the stack and
1614 has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space. */
1615 if (args_size
== 0 && current_function_calls_alloca
)
1616 args_size
= 4 * UNITS_PER_WORD
;
1618 total_size
= var_size
+ args_size
+ extra_size
;
1620 /* Calculate space needed for gp registers. */
1621 for (regno
= GP_REG_FIRST
; regno
<= GP_REG_LAST
; regno
++)
1623 if (MUST_SAVE_REGISTER (regno
))
1625 gp_reg_size
+= GET_MODE_SIZE (gpr_mode
);
1626 mask
|= 1L << (regno
- GP_REG_FIRST
);
1630 /* We need to restore these for the handler. */
1631 if (current_function_calls_eh_return
)
1637 regno
= EH_RETURN_DATA_REGNO (i
);
1638 if (regno
== (int) INVALID_REGNUM
)
1640 gp_reg_size
+= GET_MODE_SIZE (gpr_mode
);
1641 mask
|= 1L << (regno
- GP_REG_FIRST
);
1647 gp_reg_rounded
= IQ2000_STACK_ALIGN (gp_reg_size
);
1648 total_size
+= gp_reg_rounded
+ IQ2000_STACK_ALIGN (fp_reg_size
);
1650 /* The gp reg is caller saved, so there is no need for leaf routines
1651 (total_size == extra_size) to save the gp reg. */
1652 if (total_size
== extra_size
1654 total_size
= extra_size
= 0;
1656 total_size
+= IQ2000_STACK_ALIGN (current_function_pretend_args_size
);
1658 /* Save other computed information. */
1659 cfun
->machine
->total_size
= total_size
;
1660 cfun
->machine
->var_size
= var_size
;
1661 cfun
->machine
->args_size
= args_size
;
1662 cfun
->machine
->extra_size
= extra_size
;
1663 cfun
->machine
->gp_reg_size
= gp_reg_size
;
1664 cfun
->machine
->fp_reg_size
= fp_reg_size
;
1665 cfun
->machine
->mask
= mask
;
1666 cfun
->machine
->initialized
= reload_completed
;
1667 cfun
->machine
->num_gp
= gp_reg_size
/ UNITS_PER_WORD
;
1671 unsigned long offset
;
1673 offset
= (args_size
+ extra_size
+ var_size
1674 + gp_reg_size
- GET_MODE_SIZE (gpr_mode
));
1676 cfun
->machine
->gp_sp_offset
= offset
;
1677 cfun
->machine
->gp_save_offset
= offset
- total_size
;
1681 cfun
->machine
->gp_sp_offset
= 0;
1682 cfun
->machine
->gp_save_offset
= 0;
1685 cfun
->machine
->fp_sp_offset
= 0;
1686 cfun
->machine
->fp_save_offset
= 0;
1688 /* Ok, we're done. */
1692 /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
1693 pointer, argument pointer, or return address pointer. TO is either
1694 the stack pointer or hard frame pointer. */
1697 iq2000_initial_elimination_offset (int from
, int to ATTRIBUTE_UNUSED
)
1701 compute_frame_size (get_frame_size ());
1702 if ((from
) == FRAME_POINTER_REGNUM
)
1704 else if ((from
) == ARG_POINTER_REGNUM
)
1705 (offset
) = (cfun
->machine
->total_size
);
1706 else if ((from
) == RETURN_ADDRESS_POINTER_REGNUM
)
1708 if (leaf_function_p ())
1710 else (offset
) = cfun
->machine
->gp_sp_offset
1711 + ((UNITS_PER_WORD
- (POINTER_SIZE
/ BITS_PER_UNIT
))
1712 * (BYTES_BIG_ENDIAN
!= 0));
1718 /* Common code to emit the insns (or to write the instructions to a file)
1719 to save/restore registers.
1720 Other parts of the code assume that IQ2000_TEMP1_REGNUM (aka large_reg)
1721 is not modified within save_restore_insns. */
1723 #define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
1725 /* Emit instructions to load the value (SP + OFFSET) into IQ2000_TEMP2_REGNUM
1726 and return an rtl expression for the register. Write the assembly
1727 instructions directly to FILE if it is not null, otherwise emit them as
1730 This function is a subroutine of save_restore_insns. It is used when
1731 OFFSET is too large to add in a single instruction. */
1734 iq2000_add_large_offset_to_sp (HOST_WIDE_INT offset
)
1736 rtx reg
= gen_rtx_REG (Pmode
, IQ2000_TEMP2_REGNUM
);
1737 rtx offset_rtx
= GEN_INT (offset
);
1739 emit_move_insn (reg
, offset_rtx
);
1740 emit_insn (gen_addsi3 (reg
, reg
, stack_pointer_rtx
));
1744 /* Make INSN frame related and note that it performs the frame-related
1745 operation DWARF_PATTERN. */
1748 iq2000_annotate_frame_insn (rtx insn
, rtx dwarf_pattern
)
1750 RTX_FRAME_RELATED_P (insn
) = 1;
1751 REG_NOTES (insn
) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
1756 /* Emit a move instruction that stores REG in MEM. Make the instruction
1757 frame related and note that it stores REG at (SP + OFFSET). */
1760 iq2000_emit_frame_related_store (rtx mem
, rtx reg
, HOST_WIDE_INT offset
)
1762 rtx dwarf_address
= plus_constant (stack_pointer_rtx
, offset
);
1763 rtx dwarf_mem
= gen_rtx_MEM (GET_MODE (reg
), dwarf_address
);
1765 iq2000_annotate_frame_insn (emit_move_insn (mem
, reg
),
1766 gen_rtx_SET (GET_MODE (reg
), dwarf_mem
, reg
));
1769 /* Emit instructions to save/restore registers, as determined by STORE_P. */
1772 save_restore_insns (int store_p
)
1774 long mask
= cfun
->machine
->mask
;
1777 HOST_WIDE_INT base_offset
;
1778 HOST_WIDE_INT gp_offset
;
1779 HOST_WIDE_INT end_offset
;
1781 gcc_assert (!frame_pointer_needed
1782 || BITSET_P (mask
, HARD_FRAME_POINTER_REGNUM
- GP_REG_FIRST
));
1786 base_reg_rtx
= 0, base_offset
= 0;
1790 /* Save registers starting from high to low. The debuggers prefer at least
1791 the return register be stored at func+4, and also it allows us not to
1792 need a nop in the epilog if at least one register is reloaded in
1793 addition to return address. */
1795 /* Save GP registers if needed. */
1796 /* Pick which pointer to use as a base register. For small frames, just
1797 use the stack pointer. Otherwise, use a temporary register. Save 2
1798 cycles if the save area is near the end of a large frame, by reusing
1799 the constant created in the prologue/epilogue to adjust the stack
1802 gp_offset
= cfun
->machine
->gp_sp_offset
;
1804 = gp_offset
- (cfun
->machine
->gp_reg_size
1805 - GET_MODE_SIZE (gpr_mode
));
1807 if (gp_offset
< 0 || end_offset
< 0)
1809 ("gp_offset (%ld) or end_offset (%ld) is less than zero",
1810 (long) gp_offset
, (long) end_offset
);
1812 else if (gp_offset
< 32768)
1813 base_reg_rtx
= stack_pointer_rtx
, base_offset
= 0;
1817 int reg_save_count
= 0;
1819 for (regno
= GP_REG_LAST
; regno
>= GP_REG_FIRST
; regno
--)
1820 if (BITSET_P (mask
, regno
- GP_REG_FIRST
)) reg_save_count
+= 1;
1821 base_offset
= gp_offset
- ((reg_save_count
- 1) * 4);
1822 base_reg_rtx
= iq2000_add_large_offset_to_sp (base_offset
);
1825 for (regno
= GP_REG_LAST
; regno
>= GP_REG_FIRST
; regno
--)
1827 if (BITSET_P (mask
, regno
- GP_REG_FIRST
))
1831 = gen_rtx_MEM (gpr_mode
,
1832 gen_rtx_PLUS (Pmode
, base_reg_rtx
,
1833 GEN_INT (gp_offset
- base_offset
)));
1835 reg_rtx
= gen_rtx_REG (gpr_mode
, regno
);
1838 iq2000_emit_frame_related_store (mem_rtx
, reg_rtx
, gp_offset
);
1841 emit_move_insn (reg_rtx
, mem_rtx
);
1843 gp_offset
-= GET_MODE_SIZE (gpr_mode
);
1848 /* Expand the prologue into a bunch of separate insns. */
1851 iq2000_expand_prologue (void)
1854 HOST_WIDE_INT tsize
;
1855 int last_arg_is_vararg_marker
= 0;
1856 tree fndecl
= current_function_decl
;
1857 tree fntype
= TREE_TYPE (fndecl
);
1858 tree fnargs
= DECL_ARGUMENTS (fndecl
);
1863 CUMULATIVE_ARGS args_so_far
;
1864 int store_args_on_stack
= (iq2000_can_use_return_insn ());
1866 /* If struct value address is treated as the first argument. */
1867 if (aggregate_value_p (DECL_RESULT (fndecl
), fndecl
)
1868 && ! current_function_returns_pcc_struct
1869 && targetm
.calls
.struct_value_rtx (TREE_TYPE (fndecl
), 1) == 0)
1871 tree type
= build_pointer_type (fntype
);
1872 tree function_result_decl
= build_decl (PARM_DECL
, NULL_TREE
, type
);
1874 DECL_ARG_TYPE (function_result_decl
) = type
;
1875 TREE_CHAIN (function_result_decl
) = fnargs
;
1876 fnargs
= function_result_decl
;
1879 /* For arguments passed in registers, find the register number
1880 of the first argument in the variable part of the argument list,
1881 otherwise GP_ARG_LAST+1. Note also if the last argument is
1882 the varargs special argument, and treat it as part of the
1885 This is only needed if store_args_on_stack is true. */
1886 INIT_CUMULATIVE_ARGS (args_so_far
, fntype
, NULL_RTX
, 0, 0);
1887 regno
= GP_ARG_FIRST
;
1889 for (cur_arg
= fnargs
; cur_arg
!= 0; cur_arg
= next_arg
)
1891 tree passed_type
= DECL_ARG_TYPE (cur_arg
);
1892 enum machine_mode passed_mode
= TYPE_MODE (passed_type
);
1895 if (TREE_ADDRESSABLE (passed_type
))
1897 passed_type
= build_pointer_type (passed_type
);
1898 passed_mode
= Pmode
;
1901 entry_parm
= FUNCTION_ARG (args_so_far
, passed_mode
, passed_type
, 1);
1903 FUNCTION_ARG_ADVANCE (args_so_far
, passed_mode
, passed_type
, 1);
1904 next_arg
= TREE_CHAIN (cur_arg
);
1906 if (entry_parm
&& store_args_on_stack
)
1909 && DECL_NAME (cur_arg
)
1910 && ((0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg
)),
1911 "__builtin_va_alist"))
1912 || (0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg
)),
1915 last_arg_is_vararg_marker
= 1;
1922 gcc_assert (GET_CODE (entry_parm
) == REG
);
1924 /* Passed in a register, so will get homed automatically. */
1925 if (GET_MODE (entry_parm
) == BLKmode
)
1926 words
= (int_size_in_bytes (passed_type
) + 3) / 4;
1928 words
= (GET_MODE_SIZE (GET_MODE (entry_parm
)) + 3) / 4;
1930 regno
= REGNO (entry_parm
) + words
- 1;
1935 regno
= GP_ARG_LAST
+1;
1940 /* In order to pass small structures by value in registers we need to
1941 shift the value into the high part of the register.
1942 Function_arg has encoded a PARALLEL rtx, holding a vector of
1943 adjustments to be made as the next_arg_reg variable, so we split up the
1944 insns, and emit them separately. */
1945 next_arg_reg
= FUNCTION_ARG (args_so_far
, VOIDmode
, void_type_node
, 1);
1946 if (next_arg_reg
!= 0 && GET_CODE (next_arg_reg
) == PARALLEL
)
1948 rtvec adjust
= XVEC (next_arg_reg
, 0);
1949 int num
= GET_NUM_ELEM (adjust
);
1951 for (i
= 0; i
< num
; i
++)
1955 pattern
= RTVEC_ELT (adjust
, i
);
1956 if (GET_CODE (pattern
) != SET
1957 || GET_CODE (SET_SRC (pattern
)) != ASHIFT
)
1958 abort_with_insn (pattern
, "Insn is not a shift");
1959 PUT_CODE (SET_SRC (pattern
), ASHIFTRT
);
1961 insn
= emit_insn (pattern
);
1963 /* Global life information isn't valid at this point, so we
1964 can't check whether these shifts are actually used. Mark
1965 them MAYBE_DEAD so that flow2 will remove them, and not
1966 complain about dead code in the prologue. */
1967 REG_NOTES(insn
) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD
, NULL_RTX
,
1972 tsize
= compute_frame_size (get_frame_size ());
1974 /* If this function is a varargs function, store any registers that
1975 would normally hold arguments ($4 - $7) on the stack. */
1976 if (store_args_on_stack
1977 && ((TYPE_ARG_TYPES (fntype
) != 0
1978 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1980 || last_arg_is_vararg_marker
))
1982 int offset
= (regno
- GP_ARG_FIRST
) * UNITS_PER_WORD
;
1983 rtx ptr
= stack_pointer_rtx
;
1985 for (; regno
<= GP_ARG_LAST
; regno
++)
1988 ptr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, GEN_INT (offset
));
1989 emit_move_insn (gen_rtx_MEM (gpr_mode
, ptr
),
1990 gen_rtx_REG (gpr_mode
, regno
));
1992 offset
+= GET_MODE_SIZE (gpr_mode
);
1998 rtx tsize_rtx
= GEN_INT (tsize
);
1999 rtx adjustment_rtx
, insn
, dwarf_pattern
;
2003 adjustment_rtx
= gen_rtx_REG (Pmode
, IQ2000_TEMP1_REGNUM
);
2004 emit_move_insn (adjustment_rtx
, tsize_rtx
);
2007 adjustment_rtx
= tsize_rtx
;
2009 insn
= emit_insn (gen_subsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
2012 dwarf_pattern
= gen_rtx_SET (Pmode
, stack_pointer_rtx
,
2013 plus_constant (stack_pointer_rtx
, -tsize
));
2015 iq2000_annotate_frame_insn (insn
, dwarf_pattern
);
2017 save_restore_insns (1);
2019 if (frame_pointer_needed
)
2023 insn
= emit_insn (gen_movsi (hard_frame_pointer_rtx
,
2024 stack_pointer_rtx
));
2027 RTX_FRAME_RELATED_P (insn
) = 1;
2031 emit_insn (gen_blockage ());
2034 /* Expand the epilogue into a bunch of separate insns. */
2037 iq2000_expand_epilogue (void)
2039 HOST_WIDE_INT tsize
= cfun
->machine
->total_size
;
2040 rtx tsize_rtx
= GEN_INT (tsize
);
2041 rtx tmp_rtx
= (rtx
)0;
2043 if (iq2000_can_use_return_insn ())
2045 emit_jump_insn (gen_return ());
2051 tmp_rtx
= gen_rtx_REG (Pmode
, IQ2000_TEMP1_REGNUM
);
2052 emit_move_insn (tmp_rtx
, tsize_rtx
);
2053 tsize_rtx
= tmp_rtx
;
2058 if (frame_pointer_needed
)
2060 emit_insn (gen_blockage ());
2062 emit_insn (gen_movsi (stack_pointer_rtx
, hard_frame_pointer_rtx
));
2065 save_restore_insns (0);
2067 if (current_function_calls_eh_return
)
2069 rtx eh_ofs
= EH_RETURN_STACKADJ_RTX
;
2070 emit_insn (gen_addsi3 (eh_ofs
, eh_ofs
, tsize_rtx
));
2074 emit_insn (gen_blockage ());
2076 if (tsize
!= 0 || current_function_calls_eh_return
)
2078 emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
2083 if (current_function_calls_eh_return
)
2085 /* Perform the additional bump for __throw. */
2086 emit_move_insn (gen_rtx_REG (Pmode
, HARD_FRAME_POINTER_REGNUM
),
2088 emit_insn (gen_rtx_USE (VOIDmode
, gen_rtx_REG (Pmode
,
2089 HARD_FRAME_POINTER_REGNUM
)));
2090 emit_jump_insn (gen_eh_return_internal ());
2093 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode
,
2094 GP_REG_FIRST
+ 31)));
2098 iq2000_expand_eh_return (rtx address
)
2100 HOST_WIDE_INT gp_offset
= cfun
->machine
->gp_sp_offset
;
2103 scratch
= plus_constant (stack_pointer_rtx
, gp_offset
);
2104 emit_move_insn (gen_rtx_MEM (GET_MODE (address
), scratch
), address
);
2107 /* Return nonzero if this function is known to have a null epilogue.
2108 This allows the optimizer to omit jumps to jumps if no stack
2112 iq2000_can_use_return_insn (void)
2114 if (! reload_completed
)
2117 if (regs_ever_live
[31] || profile_flag
)
2120 if (cfun
->machine
->initialized
)
2121 return cfun
->machine
->total_size
== 0;
2123 return compute_frame_size (get_frame_size ()) == 0;
2126 /* Returns nonzero if X contains a SYMBOL_REF. */
2129 symbolic_expression_p (rtx x
)
2131 if (GET_CODE (x
) == SYMBOL_REF
)
2134 if (GET_CODE (x
) == CONST
)
2135 return symbolic_expression_p (XEXP (x
, 0));
2138 return symbolic_expression_p (XEXP (x
, 0));
2140 if (ARITHMETIC_P (x
))
2141 return (symbolic_expression_p (XEXP (x
, 0))
2142 || symbolic_expression_p (XEXP (x
, 1)));
2147 /* Choose the section to use for the constant rtx expression X that has
2151 iq2000_select_rtx_section (enum machine_mode mode
, rtx x ATTRIBUTE_UNUSED
,
2152 unsigned HOST_WIDE_INT align
)
2154 /* For embedded applications, always put constants in read-only data,
2155 in order to reduce RAM usage. */
2156 return mergeable_constant_section (mode
, align
, 0);
2159 /* Choose the section to use for DECL. RELOC is true if its value contains
2160 any relocatable expression.
2162 Some of the logic used here needs to be replicated in
2163 ENCODE_SECTION_INFO in iq2000.h so that references to these symbols
2164 are done correctly. */
2167 iq2000_select_section (tree decl
, int reloc ATTRIBUTE_UNUSED
,
2168 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
)
2170 if (TARGET_EMBEDDED_DATA
)
2172 /* For embedded applications, always put an object in read-only data
2173 if possible, in order to reduce RAM usage. */
2174 if ((TREE_CODE (decl
) == VAR_DECL
2175 && TREE_READONLY (decl
) && !TREE_SIDE_EFFECTS (decl
)
2176 && DECL_INITIAL (decl
)
2177 && (DECL_INITIAL (decl
) == error_mark_node
2178 || TREE_CONSTANT (DECL_INITIAL (decl
))))
2179 /* Deal with calls from output_constant_def_contents. */
2180 || TREE_CODE (decl
) != VAR_DECL
)
2181 return readonly_data_section
;
2183 return data_section
;
2187 /* For hosted applications, always put an object in small data if
2188 possible, as this gives the best performance. */
2189 if ((TREE_CODE (decl
) == VAR_DECL
2190 && TREE_READONLY (decl
) && !TREE_SIDE_EFFECTS (decl
)
2191 && DECL_INITIAL (decl
)
2192 && (DECL_INITIAL (decl
) == error_mark_node
2193 || TREE_CONSTANT (DECL_INITIAL (decl
))))
2194 /* Deal with calls from output_constant_def_contents. */
2195 || TREE_CODE (decl
) != VAR_DECL
)
2196 return readonly_data_section
;
2198 return data_section
;
2201 /* Return register to use for a function return value with VALTYPE for function
2205 iq2000_function_value (tree valtype
, tree func ATTRIBUTE_UNUSED
)
2207 int reg
= GP_RETURN
;
2208 enum machine_mode mode
= TYPE_MODE (valtype
);
2209 int unsignedp
= TYPE_UNSIGNED (valtype
);
2211 /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns true,
2212 we must promote the mode just as PROMOTE_MODE does. */
2213 mode
= promote_mode (valtype
, mode
, &unsignedp
, 1);
2215 return gen_rtx_REG (mode
, reg
);
2218 /* Return true when an argument must be passed by reference. */
2221 iq2000_pass_by_reference (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
,
2222 tree type
, bool named ATTRIBUTE_UNUSED
)
2226 /* We must pass by reference if we would be both passing in registers
2227 and the stack. This is because any subsequent partial arg would be
2228 handled incorrectly in this case. */
2229 if (cum
&& targetm
.calls
.must_pass_in_stack (mode
, type
))
2231 /* Don't pass the actual CUM to FUNCTION_ARG, because we would
2232 get double copies of any offsets generated for small structs
2233 passed in registers. */
2234 CUMULATIVE_ARGS temp
;
2237 if (FUNCTION_ARG (temp
, mode
, type
, named
) != 0)
2241 if (type
== NULL_TREE
|| mode
== DImode
|| mode
== DFmode
)
2244 size
= int_size_in_bytes (type
);
2245 return size
== -1 || size
> UNITS_PER_WORD
;
2248 /* Return the length of INSN. LENGTH is the initial length computed by
2249 attributes in the machine-description file. */
2252 iq2000_adjust_insn_length (rtx insn
, int length
)
2254 /* A unconditional jump has an unfilled delay slot if it is not part
2255 of a sequence. A conditional jump normally has a delay slot. */
2256 if (simplejump_p (insn
)
2257 || ( (GET_CODE (insn
) == JUMP_INSN
2258 || GET_CODE (insn
) == CALL_INSN
)))
2264 /* Output assembly instructions to perform a conditional branch.
2266 INSN is the branch instruction. OPERANDS[0] is the condition.
2267 OPERANDS[1] is the target of the branch. OPERANDS[2] is the target
2268 of the first operand to the condition. If TWO_OPERANDS_P is
2269 nonzero the comparison takes two operands; OPERANDS[3] will be the
2272 If INVERTED_P is nonzero we are to branch if the condition does
2273 not hold. If FLOAT_P is nonzero this is a floating-point comparison.
2275 LENGTH is the length (in bytes) of the sequence we are to generate.
2276 That tells us whether to generate a simple conditional branch, or a
2277 reversed conditional branch around a `jr' instruction. */
2280 iq2000_output_conditional_branch (rtx insn
, rtx
* operands
, int two_operands_p
,
2281 int float_p
, int inverted_p
, int length
)
2283 static char buffer
[200];
2284 /* The kind of comparison we are doing. */
2285 enum rtx_code code
= GET_CODE (operands
[0]);
2286 /* Nonzero if the opcode for the comparison needs a `z' indicating
2287 that it is a comparison against zero. */
2289 /* A string to use in the assembly output to represent the first
2291 const char *op1
= "%z2";
2292 /* A string to use in the assembly output to represent the second
2293 operand. Use the hard-wired zero register if there's no second
2295 const char *op2
= (two_operands_p
? ",%z3" : ",%.");
2296 /* The operand-printing string for the comparison. */
2297 const char *comp
= (float_p
? "%F0" : "%C0");
2298 /* The operand-printing string for the inverted comparison. */
2299 const char *inverted_comp
= (float_p
? "%W0" : "%N0");
2301 /* Likely variants of each branch instruction annul the instruction
2302 in the delay slot if the branch is not taken. */
2303 iq2000_branch_likely
= (final_sequence
&& INSN_ANNULLED_BRANCH_P (insn
));
2305 if (!two_operands_p
)
2307 /* To compute whether than A > B, for example, we normally
2308 subtract B from A and then look at the sign bit. But, if we
2309 are doing an unsigned comparison, and B is zero, we don't
2310 have to do the subtraction. Instead, we can just check to
2311 see if A is nonzero. Thus, we change the CODE here to
2312 reflect the simpler comparison operation. */
2324 /* A condition which will always be true. */
2330 /* A condition which will always be false. */
2336 /* Not a special case. */
2341 /* Relative comparisons are always done against zero. But
2342 equality comparisons are done between two operands, and therefore
2343 do not require a `z' in the assembly language output. */
2344 need_z_p
= (!float_p
&& code
!= EQ
&& code
!= NE
);
2345 /* For comparisons against zero, the zero is not provided
2350 /* Begin by terminating the buffer. That way we can always use
2351 strcat to add to it. */
2358 /* Just a simple conditional branch. */
2360 sprintf (buffer
, "b%s%%?\t%%Z2%%1",
2361 inverted_p
? inverted_comp
: comp
);
2363 sprintf (buffer
, "b%s%s%%?\t%s%s,%%1",
2364 inverted_p
? inverted_comp
: comp
,
2365 need_z_p
? "z" : "",
2373 /* Generate a reversed conditional branch around ` j'
2385 Because we have to jump four bytes *past* the following
2386 instruction if this branch was annulled, we can't just use
2387 a label, as in the picture above; there's no way to put the
2388 label after the next instruction, as the assembler does not
2389 accept `.L+4' as the target of a branch. (We can't just
2390 wait until the next instruction is output; it might be a
2391 macro and take up more than four bytes. Once again, we see
2392 why we want to eliminate macros.)
2394 If the branch is annulled, we jump four more bytes that we
2395 would otherwise; that way we skip the annulled instruction
2396 in the delay slot. */
2399 = ((iq2000_branch_likely
|| length
== 16) ? ".+16" : ".+12");
2402 c
= strchr (buffer
, '\0');
2403 /* Generate the reversed comparison. This takes four
2406 sprintf (c
, "b%s\t%%Z2%s",
2407 inverted_p
? comp
: inverted_comp
,
2410 sprintf (c
, "b%s%s\t%s%s,%s",
2411 inverted_p
? comp
: inverted_comp
,
2412 need_z_p
? "z" : "",
2416 strcat (c
, "\n\tnop\n\tj\t%1");
2418 /* The delay slot was unfilled. Since we're inside
2419 .noreorder, the assembler will not fill in the NOP for
2420 us, so we must do it ourselves. */
2421 strcat (buffer
, "\n\tnop");
2433 #define def_builtin(NAME, TYPE, CODE) \
2434 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
2438 iq2000_init_builtins (void)
2440 tree endlink
= void_list_node
;
2441 tree void_ftype
, void_ftype_int
, void_ftype_int_int
;
2442 tree void_ftype_int_int_int
;
2443 tree int_ftype_int
, int_ftype_int_int
, int_ftype_int_int_int
;
2444 tree int_ftype_int_int_int_int
;
2448 = build_function_type (void_type_node
,
2449 tree_cons (NULL_TREE
, void_type_node
, endlink
));
2453 = build_function_type (void_type_node
,
2454 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
2456 /* void func (int, int) */
2458 = build_function_type (void_type_node
,
2459 tree_cons (NULL_TREE
, integer_type_node
,
2460 tree_cons (NULL_TREE
, integer_type_node
,
2463 /* int func (int) */
2465 = build_function_type (integer_type_node
,
2466 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
2468 /* int func (int, int) */
2470 = build_function_type (integer_type_node
,
2471 tree_cons (NULL_TREE
, integer_type_node
,
2472 tree_cons (NULL_TREE
, integer_type_node
,
2475 /* void func (int, int, int) */
2476 void_ftype_int_int_int
2477 = build_function_type
2479 tree_cons (NULL_TREE
, integer_type_node
,
2480 tree_cons (NULL_TREE
, integer_type_node
,
2481 tree_cons (NULL_TREE
,
2485 /* int func (int, int, int, int) */
2486 int_ftype_int_int_int_int
2487 = build_function_type
2489 tree_cons (NULL_TREE
, integer_type_node
,
2490 tree_cons (NULL_TREE
, integer_type_node
,
2491 tree_cons (NULL_TREE
,
2493 tree_cons (NULL_TREE
,
2497 /* int func (int, int, int) */
2498 int_ftype_int_int_int
2499 = build_function_type
2501 tree_cons (NULL_TREE
, integer_type_node
,
2502 tree_cons (NULL_TREE
, integer_type_node
,
2503 tree_cons (NULL_TREE
,
2507 /* int func (int, int, int, int) */
2508 int_ftype_int_int_int_int
2509 = build_function_type
2511 tree_cons (NULL_TREE
, integer_type_node
,
2512 tree_cons (NULL_TREE
, integer_type_node
,
2513 tree_cons (NULL_TREE
,
2515 tree_cons (NULL_TREE
,
2519 def_builtin ("__builtin_ado16", int_ftype_int_int
, IQ2000_BUILTIN_ADO16
);
2520 def_builtin ("__builtin_ram", int_ftype_int_int_int_int
, IQ2000_BUILTIN_RAM
);
2521 def_builtin ("__builtin_chkhdr", void_ftype_int_int
, IQ2000_BUILTIN_CHKHDR
);
2522 def_builtin ("__builtin_pkrl", void_ftype_int_int
, IQ2000_BUILTIN_PKRL
);
2523 def_builtin ("__builtin_cfc0", int_ftype_int
, IQ2000_BUILTIN_CFC0
);
2524 def_builtin ("__builtin_cfc1", int_ftype_int
, IQ2000_BUILTIN_CFC1
);
2525 def_builtin ("__builtin_cfc2", int_ftype_int
, IQ2000_BUILTIN_CFC2
);
2526 def_builtin ("__builtin_cfc3", int_ftype_int
, IQ2000_BUILTIN_CFC3
);
2527 def_builtin ("__builtin_ctc0", void_ftype_int_int
, IQ2000_BUILTIN_CTC0
);
2528 def_builtin ("__builtin_ctc1", void_ftype_int_int
, IQ2000_BUILTIN_CTC1
);
2529 def_builtin ("__builtin_ctc2", void_ftype_int_int
, IQ2000_BUILTIN_CTC2
);
2530 def_builtin ("__builtin_ctc3", void_ftype_int_int
, IQ2000_BUILTIN_CTC3
);
2531 def_builtin ("__builtin_mfc0", int_ftype_int
, IQ2000_BUILTIN_MFC0
);
2532 def_builtin ("__builtin_mfc1", int_ftype_int
, IQ2000_BUILTIN_MFC1
);
2533 def_builtin ("__builtin_mfc2", int_ftype_int
, IQ2000_BUILTIN_MFC2
);
2534 def_builtin ("__builtin_mfc3", int_ftype_int
, IQ2000_BUILTIN_MFC3
);
2535 def_builtin ("__builtin_mtc0", void_ftype_int_int
, IQ2000_BUILTIN_MTC0
);
2536 def_builtin ("__builtin_mtc1", void_ftype_int_int
, IQ2000_BUILTIN_MTC1
);
2537 def_builtin ("__builtin_mtc2", void_ftype_int_int
, IQ2000_BUILTIN_MTC2
);
2538 def_builtin ("__builtin_mtc3", void_ftype_int_int
, IQ2000_BUILTIN_MTC3
);
2539 def_builtin ("__builtin_lur", void_ftype_int_int
, IQ2000_BUILTIN_LUR
);
2540 def_builtin ("__builtin_rb", void_ftype_int_int
, IQ2000_BUILTIN_RB
);
2541 def_builtin ("__builtin_rx", void_ftype_int_int
, IQ2000_BUILTIN_RX
);
2542 def_builtin ("__builtin_srrd", void_ftype_int
, IQ2000_BUILTIN_SRRD
);
2543 def_builtin ("__builtin_srwr", void_ftype_int_int
, IQ2000_BUILTIN_SRWR
);
2544 def_builtin ("__builtin_wb", void_ftype_int_int
, IQ2000_BUILTIN_WB
);
2545 def_builtin ("__builtin_wx", void_ftype_int_int
, IQ2000_BUILTIN_WX
);
2546 def_builtin ("__builtin_luc32l", void_ftype_int_int
, IQ2000_BUILTIN_LUC32L
);
2547 def_builtin ("__builtin_luc64", void_ftype_int_int
, IQ2000_BUILTIN_LUC64
);
2548 def_builtin ("__builtin_luc64l", void_ftype_int_int
, IQ2000_BUILTIN_LUC64L
);
2549 def_builtin ("__builtin_luk", void_ftype_int_int
, IQ2000_BUILTIN_LUK
);
2550 def_builtin ("__builtin_lulck", void_ftype_int
, IQ2000_BUILTIN_LULCK
);
2551 def_builtin ("__builtin_lum32", void_ftype_int_int
, IQ2000_BUILTIN_LUM32
);
2552 def_builtin ("__builtin_lum32l", void_ftype_int_int
, IQ2000_BUILTIN_LUM32L
);
2553 def_builtin ("__builtin_lum64", void_ftype_int_int
, IQ2000_BUILTIN_LUM64
);
2554 def_builtin ("__builtin_lum64l", void_ftype_int_int
, IQ2000_BUILTIN_LUM64L
);
2555 def_builtin ("__builtin_lurl", void_ftype_int_int
, IQ2000_BUILTIN_LURL
);
2556 def_builtin ("__builtin_mrgb", int_ftype_int_int_int
, IQ2000_BUILTIN_MRGB
);
2557 def_builtin ("__builtin_srrdl", void_ftype_int
, IQ2000_BUILTIN_SRRDL
);
2558 def_builtin ("__builtin_srulck", void_ftype_int
, IQ2000_BUILTIN_SRULCK
);
2559 def_builtin ("__builtin_srwru", void_ftype_int_int
, IQ2000_BUILTIN_SRWRU
);
2560 def_builtin ("__builtin_trapqfl", void_ftype
, IQ2000_BUILTIN_TRAPQFL
);
2561 def_builtin ("__builtin_trapqne", void_ftype
, IQ2000_BUILTIN_TRAPQNE
);
2562 def_builtin ("__builtin_traprel", void_ftype_int
, IQ2000_BUILTIN_TRAPREL
);
2563 def_builtin ("__builtin_wbu", void_ftype_int_int_int
, IQ2000_BUILTIN_WBU
);
2564 def_builtin ("__builtin_syscall", void_ftype
, IQ2000_BUILTIN_SYSCALL
);
2567 /* Builtin for ICODE having ARGCOUNT args in ARGLIST where each arg
2571 expand_one_builtin (enum insn_code icode
, rtx target
, tree arglist
,
2572 enum rtx_code
*code
, int argcount
)
2577 enum machine_mode mode
[5];
2580 mode
[0] = insn_data
[icode
].operand
[0].mode
;
2581 for (i
= 0; i
< argcount
; i
++)
2583 arg
[i
] = TREE_VALUE (arglist
);
2584 arglist
= TREE_CHAIN (arglist
);
2585 op
[i
] = expand_expr (arg
[i
], NULL_RTX
, VOIDmode
, 0);
2586 mode
[i
] = insn_data
[icode
].operand
[i
].mode
;
2587 if (code
[i
] == CONST_INT
&& GET_CODE (op
[i
]) != CONST_INT
)
2588 error ("argument %qd is not a constant", i
+ 1);
2590 && ! (*insn_data
[icode
].operand
[i
].predicate
) (op
[i
], mode
[i
]))
2591 op
[i
] = copy_to_mode_reg (mode
[i
], op
[i
]);
2594 if (insn_data
[icode
].operand
[0].constraint
[0] == '=')
2597 || GET_MODE (target
) != mode
[0]
2598 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, mode
[0]))
2599 target
= gen_reg_rtx (mode
[0]);
2607 pat
= GEN_FCN (icode
) (target
);
2610 pat
= GEN_FCN (icode
) (target
, op
[0]);
2612 pat
= GEN_FCN (icode
) (op
[0]);
2616 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1]);
2618 pat
= GEN_FCN (icode
) (op
[0], op
[1]);
2622 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2]);
2624 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2]);
2628 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2], op
[3]);
2630 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3]);
2642 /* Expand an expression EXP that calls a built-in function,
2643 with result going to TARGET if that's convenient
2644 (and in mode MODE if that's convenient).
2645 SUBTARGET may be used as the target for computing one of EXP's operands.
2646 IGNORE is nonzero if the value is to be ignored. */
2649 iq2000_expand_builtin (tree exp
, rtx target
, rtx subtarget ATTRIBUTE_UNUSED
,
2650 enum machine_mode mode ATTRIBUTE_UNUSED
,
2651 int ignore ATTRIBUTE_UNUSED
)
2653 tree fndecl
= TREE_OPERAND (TREE_OPERAND (exp
, 0), 0);
2654 tree arglist
= TREE_OPERAND (exp
, 1);
2655 int fcode
= DECL_FUNCTION_CODE (fndecl
);
2656 enum rtx_code code
[5];
2668 case IQ2000_BUILTIN_ADO16
:
2669 return expand_one_builtin (CODE_FOR_ado16
, target
, arglist
, code
, 2);
2671 case IQ2000_BUILTIN_RAM
:
2672 code
[1] = CONST_INT
;
2673 code
[2] = CONST_INT
;
2674 code
[3] = CONST_INT
;
2675 return expand_one_builtin (CODE_FOR_ram
, target
, arglist
, code
, 4);
2677 case IQ2000_BUILTIN_CHKHDR
:
2678 return expand_one_builtin (CODE_FOR_chkhdr
, target
, arglist
, code
, 2);
2680 case IQ2000_BUILTIN_PKRL
:
2681 return expand_one_builtin (CODE_FOR_pkrl
, target
, arglist
, code
, 2);
2683 case IQ2000_BUILTIN_CFC0
:
2684 code
[0] = CONST_INT
;
2685 return expand_one_builtin (CODE_FOR_cfc0
, target
, arglist
, code
, 1);
2687 case IQ2000_BUILTIN_CFC1
:
2688 code
[0] = CONST_INT
;
2689 return expand_one_builtin (CODE_FOR_cfc1
, target
, arglist
, code
, 1);
2691 case IQ2000_BUILTIN_CFC2
:
2692 code
[0] = CONST_INT
;
2693 return expand_one_builtin (CODE_FOR_cfc2
, target
, arglist
, code
, 1);
2695 case IQ2000_BUILTIN_CFC3
:
2696 code
[0] = CONST_INT
;
2697 return expand_one_builtin (CODE_FOR_cfc3
, target
, arglist
, code
, 1);
2699 case IQ2000_BUILTIN_CTC0
:
2700 code
[1] = CONST_INT
;
2701 return expand_one_builtin (CODE_FOR_ctc0
, target
, arglist
, code
, 2);
2703 case IQ2000_BUILTIN_CTC1
:
2704 code
[1] = CONST_INT
;
2705 return expand_one_builtin (CODE_FOR_ctc1
, target
, arglist
, code
, 2);
2707 case IQ2000_BUILTIN_CTC2
:
2708 code
[1] = CONST_INT
;
2709 return expand_one_builtin (CODE_FOR_ctc2
, target
, arglist
, code
, 2);
2711 case IQ2000_BUILTIN_CTC3
:
2712 code
[1] = CONST_INT
;
2713 return expand_one_builtin (CODE_FOR_ctc3
, target
, arglist
, code
, 2);
2715 case IQ2000_BUILTIN_MFC0
:
2716 code
[0] = CONST_INT
;
2717 return expand_one_builtin (CODE_FOR_mfc0
, target
, arglist
, code
, 1);
2719 case IQ2000_BUILTIN_MFC1
:
2720 code
[0] = CONST_INT
;
2721 return expand_one_builtin (CODE_FOR_mfc1
, target
, arglist
, code
, 1);
2723 case IQ2000_BUILTIN_MFC2
:
2724 code
[0] = CONST_INT
;
2725 return expand_one_builtin (CODE_FOR_mfc2
, target
, arglist
, code
, 1);
2727 case IQ2000_BUILTIN_MFC3
:
2728 code
[0] = CONST_INT
;
2729 return expand_one_builtin (CODE_FOR_mfc3
, target
, arglist
, code
, 1);
2731 case IQ2000_BUILTIN_MTC0
:
2732 code
[1] = CONST_INT
;
2733 return expand_one_builtin (CODE_FOR_mtc0
, target
, arglist
, code
, 2);
2735 case IQ2000_BUILTIN_MTC1
:
2736 code
[1] = CONST_INT
;
2737 return expand_one_builtin (CODE_FOR_mtc1
, target
, arglist
, code
, 2);
2739 case IQ2000_BUILTIN_MTC2
:
2740 code
[1] = CONST_INT
;
2741 return expand_one_builtin (CODE_FOR_mtc2
, target
, arglist
, code
, 2);
2743 case IQ2000_BUILTIN_MTC3
:
2744 code
[1] = CONST_INT
;
2745 return expand_one_builtin (CODE_FOR_mtc3
, target
, arglist
, code
, 2);
2747 case IQ2000_BUILTIN_LUR
:
2748 return expand_one_builtin (CODE_FOR_lur
, target
, arglist
, code
, 2);
2750 case IQ2000_BUILTIN_RB
:
2751 return expand_one_builtin (CODE_FOR_rb
, target
, arglist
, code
, 2);
2753 case IQ2000_BUILTIN_RX
:
2754 return expand_one_builtin (CODE_FOR_rx
, target
, arglist
, code
, 2);
2756 case IQ2000_BUILTIN_SRRD
:
2757 return expand_one_builtin (CODE_FOR_srrd
, target
, arglist
, code
, 1);
2759 case IQ2000_BUILTIN_SRWR
:
2760 return expand_one_builtin (CODE_FOR_srwr
, target
, arglist
, code
, 2);
2762 case IQ2000_BUILTIN_WB
:
2763 return expand_one_builtin (CODE_FOR_wb
, target
, arglist
, code
, 2);
2765 case IQ2000_BUILTIN_WX
:
2766 return expand_one_builtin (CODE_FOR_wx
, target
, arglist
, code
, 2);
2768 case IQ2000_BUILTIN_LUC32L
:
2769 return expand_one_builtin (CODE_FOR_luc32l
, target
, arglist
, code
, 2);
2771 case IQ2000_BUILTIN_LUC64
:
2772 return expand_one_builtin (CODE_FOR_luc64
, target
, arglist
, code
, 2);
2774 case IQ2000_BUILTIN_LUC64L
:
2775 return expand_one_builtin (CODE_FOR_luc64l
, target
, arglist
, code
, 2);
2777 case IQ2000_BUILTIN_LUK
:
2778 return expand_one_builtin (CODE_FOR_luk
, target
, arglist
, code
, 2);
2780 case IQ2000_BUILTIN_LULCK
:
2781 return expand_one_builtin (CODE_FOR_lulck
, target
, arglist
, code
, 1);
2783 case IQ2000_BUILTIN_LUM32
:
2784 return expand_one_builtin (CODE_FOR_lum32
, target
, arglist
, code
, 2);
2786 case IQ2000_BUILTIN_LUM32L
:
2787 return expand_one_builtin (CODE_FOR_lum32l
, target
, arglist
, code
, 2);
2789 case IQ2000_BUILTIN_LUM64
:
2790 return expand_one_builtin (CODE_FOR_lum64
, target
, arglist
, code
, 2);
2792 case IQ2000_BUILTIN_LUM64L
:
2793 return expand_one_builtin (CODE_FOR_lum64l
, target
, arglist
, code
, 2);
2795 case IQ2000_BUILTIN_LURL
:
2796 return expand_one_builtin (CODE_FOR_lurl
, target
, arglist
, code
, 2);
2798 case IQ2000_BUILTIN_MRGB
:
2799 code
[2] = CONST_INT
;
2800 return expand_one_builtin (CODE_FOR_mrgb
, target
, arglist
, code
, 3);
2802 case IQ2000_BUILTIN_SRRDL
:
2803 return expand_one_builtin (CODE_FOR_srrdl
, target
, arglist
, code
, 1);
2805 case IQ2000_BUILTIN_SRULCK
:
2806 return expand_one_builtin (CODE_FOR_srulck
, target
, arglist
, code
, 1);
2808 case IQ2000_BUILTIN_SRWRU
:
2809 return expand_one_builtin (CODE_FOR_srwru
, target
, arglist
, code
, 2);
2811 case IQ2000_BUILTIN_TRAPQFL
:
2812 return expand_one_builtin (CODE_FOR_trapqfl
, target
, arglist
, code
, 0);
2814 case IQ2000_BUILTIN_TRAPQNE
:
2815 return expand_one_builtin (CODE_FOR_trapqne
, target
, arglist
, code
, 0);
2817 case IQ2000_BUILTIN_TRAPREL
:
2818 return expand_one_builtin (CODE_FOR_traprel
, target
, arglist
, code
, 1);
2820 case IQ2000_BUILTIN_WBU
:
2821 return expand_one_builtin (CODE_FOR_wbu
, target
, arglist
, code
, 3);
2823 case IQ2000_BUILTIN_SYSCALL
:
2824 return expand_one_builtin (CODE_FOR_syscall
, target
, arglist
, code
, 0);
2830 /* Worker function for TARGET_RETURN_IN_MEMORY. */
2833 iq2000_return_in_memory (tree type
, tree fntype ATTRIBUTE_UNUSED
)
2835 return ((int_size_in_bytes (type
) > (2 * UNITS_PER_WORD
))
2836 || (int_size_in_bytes (type
) == -1));
2839 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
2842 iq2000_setup_incoming_varargs (CUMULATIVE_ARGS
*cum
,
2843 enum machine_mode mode ATTRIBUTE_UNUSED
,
2844 tree type ATTRIBUTE_UNUSED
, int * pretend_size
,
2847 unsigned int iq2000_off
= ! cum
->last_arg_fp
;
2848 unsigned int iq2000_fp_off
= cum
->last_arg_fp
;
2850 if ((cum
->arg_words
< MAX_ARGS_IN_REGISTERS
- iq2000_off
))
2852 int iq2000_save_gp_regs
2853 = MAX_ARGS_IN_REGISTERS
- cum
->arg_words
- iq2000_off
;
2854 int iq2000_save_fp_regs
2855 = (MAX_ARGS_IN_REGISTERS
- cum
->fp_arg_words
- iq2000_fp_off
);
2857 if (iq2000_save_gp_regs
< 0)
2858 iq2000_save_gp_regs
= 0;
2859 if (iq2000_save_fp_regs
< 0)
2860 iq2000_save_fp_regs
= 0;
2862 *pretend_size
= ((iq2000_save_gp_regs
* UNITS_PER_WORD
)
2863 + (iq2000_save_fp_regs
* UNITS_PER_FPREG
));
2867 if (cum
->arg_words
< MAX_ARGS_IN_REGISTERS
- iq2000_off
)
2870 ptr
= plus_constant (virtual_incoming_args_rtx
,
2871 - (iq2000_save_gp_regs
2873 mem
= gen_rtx_MEM (BLKmode
, ptr
);
2875 (cum
->arg_words
+ GP_ARG_FIRST
+ iq2000_off
,
2877 iq2000_save_gp_regs
);
2883 /* A C compound statement to output to stdio stream STREAM the
2884 assembler syntax for an instruction operand that is a memory
2885 reference whose address is ADDR. ADDR is an RTL expression. */
2888 print_operand_address (FILE * file
, rtx addr
)
2891 error ("PRINT_OPERAND_ADDRESS, null pointer");
2894 switch (GET_CODE (addr
))
2897 if (REGNO (addr
) == ARG_POINTER_REGNUM
)
2898 abort_with_insn (addr
, "Arg pointer not eliminated.");
2900 fprintf (file
, "0(%s)", reg_names
[REGNO (addr
)]);
2905 rtx arg0
= XEXP (addr
, 0);
2906 rtx arg1
= XEXP (addr
, 1);
2908 if (GET_CODE (arg0
) != REG
)
2909 abort_with_insn (addr
,
2910 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG.");
2912 fprintf (file
, "%%lo(");
2913 print_operand_address (file
, arg1
);
2914 fprintf (file
, ")(%s)", reg_names
[REGNO (arg0
)]);
2922 rtx arg0
= XEXP (addr
, 0);
2923 rtx arg1
= XEXP (addr
, 1);
2925 if (GET_CODE (arg0
) == REG
)
2929 if (GET_CODE (offset
) == REG
)
2930 abort_with_insn (addr
, "PRINT_OPERAND_ADDRESS, 2 regs");
2933 else if (GET_CODE (arg1
) == REG
)
2934 reg
= arg1
, offset
= arg0
;
2935 else if (CONSTANT_P (arg0
) && CONSTANT_P (arg1
))
2937 output_addr_const (file
, addr
);
2941 abort_with_insn (addr
, "PRINT_OPERAND_ADDRESS, no regs");
2943 if (! CONSTANT_P (offset
))
2944 abort_with_insn (addr
, "PRINT_OPERAND_ADDRESS, invalid insn #2");
2946 if (REGNO (reg
) == ARG_POINTER_REGNUM
)
2947 abort_with_insn (addr
, "Arg pointer not eliminated.");
2949 output_addr_const (file
, offset
);
2950 fprintf (file
, "(%s)", reg_names
[REGNO (reg
)]);
2958 output_addr_const (file
, addr
);
2959 if (GET_CODE (addr
) == CONST_INT
)
2960 fprintf (file
, "(%s)", reg_names
[0]);
2964 abort_with_insn (addr
, "PRINT_OPERAND_ADDRESS, invalid insn #1");
2969 /* A C compound statement to output to stdio stream FILE the
2970 assembler syntax for an instruction operand OP.
2972 LETTER is a value that can be used to specify one of several ways
2973 of printing the operand. It is used when identical operands
2974 must be printed differently depending on the context. LETTER
2975 comes from the `%' specification that was used to request
2976 printing of the operand. If the specification was just `%DIGIT'
2977 then LETTER is 0; if the specification was `%LTR DIGIT' then LETTER
2978 is the ASCII code for LTR.
2980 If OP is a register, this macro should print the register's name.
2981 The names can be found in an array `reg_names' whose type is
2982 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2984 When the machine description has a specification `%PUNCT' (a `%'
2985 followed by a punctuation character), this macro is called with
2986 a null pointer for X and the punctuation character for LETTER.
2988 The IQ2000 specific codes are:
2990 'X' X is CONST_INT, prints upper 16 bits in hexadecimal format = "0x%04x",
2991 'x' X is CONST_INT, prints lower 16 bits in hexadecimal format = "0x%04x",
2992 'd' output integer constant in decimal,
2993 'z' if the operand is 0, use $0 instead of normal operand.
2994 'D' print second part of double-word register or memory operand.
2995 'L' print low-order register of double-word register operand.
2996 'M' print high-order register of double-word register operand.
2997 'C' print part of opcode for a branch condition.
2998 'F' print part of opcode for a floating-point branch condition.
2999 'N' print part of opcode for a branch condition, inverted.
3000 'W' print part of opcode for a floating-point branch condition, inverted.
3001 'A' Print part of opcode for a bit test condition.
3002 'P' Print label for a bit test.
3003 'p' Print log for a bit test.
3004 'B' print 'z' for EQ, 'n' for NE
3005 'b' print 'n' for EQ, 'z' for NE
3006 'T' print 'f' for EQ, 't' for NE
3007 't' print 't' for EQ, 'f' for NE
3008 'Z' print register and a comma, but print nothing for $fcc0
3009 '?' Print 'l' if we are to use a branch likely instead of normal branch.
3010 '@' Print the name of the assembler temporary register (at or $1).
3011 '.' Print the name of the register with a hard-wired zero (zero or $0).
3012 '$' Print the name of the stack pointer register (sp or $29).
3013 '+' Print the name of the gp register (gp or $28). */
3016 print_operand (FILE *file
, rtx op
, int letter
)
3020 if (PRINT_OPERAND_PUNCT_VALID_P (letter
))
3025 if (iq2000_branch_likely
)
3030 fputs (reg_names
[GP_REG_FIRST
+ 1], file
);
3034 fputs (reg_names
[GP_REG_FIRST
+ 0], file
);
3038 fputs (reg_names
[STACK_POINTER_REGNUM
], file
);
3042 fputs (reg_names
[GP_REG_FIRST
+ 28], file
);
3046 error ("PRINT_OPERAND: Unknown punctuation '%c'", letter
);
3055 error ("PRINT_OPERAND null pointer");
3059 code
= GET_CODE (op
);
3061 if (code
== SIGN_EXTEND
)
3062 op
= XEXP (op
, 0), code
= GET_CODE (op
);
3067 case EQ
: fputs ("eq", file
); break;
3068 case NE
: fputs ("ne", file
); break;
3069 case GT
: fputs ("gt", file
); break;
3070 case GE
: fputs ("ge", file
); break;
3071 case LT
: fputs ("lt", file
); break;
3072 case LE
: fputs ("le", file
); break;
3073 case GTU
: fputs ("ne", file
); break;
3074 case GEU
: fputs ("geu", file
); break;
3075 case LTU
: fputs ("ltu", file
); break;
3076 case LEU
: fputs ("eq", file
); break;
3078 abort_with_insn (op
, "PRINT_OPERAND, invalid insn for %%C");
3081 else if (letter
== 'N')
3084 case EQ
: fputs ("ne", file
); break;
3085 case NE
: fputs ("eq", file
); break;
3086 case GT
: fputs ("le", file
); break;
3087 case GE
: fputs ("lt", file
); break;
3088 case LT
: fputs ("ge", file
); break;
3089 case LE
: fputs ("gt", file
); break;
3090 case GTU
: fputs ("leu", file
); break;
3091 case GEU
: fputs ("ltu", file
); break;
3092 case LTU
: fputs ("geu", file
); break;
3093 case LEU
: fputs ("gtu", file
); break;
3095 abort_with_insn (op
, "PRINT_OPERAND, invalid insn for %%N");
3098 else if (letter
== 'F')
3101 case EQ
: fputs ("c1f", file
); break;
3102 case NE
: fputs ("c1t", file
); break;
3104 abort_with_insn (op
, "PRINT_OPERAND, invalid insn for %%F");
3107 else if (letter
== 'W')
3110 case EQ
: fputs ("c1t", file
); break;
3111 case NE
: fputs ("c1f", file
); break;
3113 abort_with_insn (op
, "PRINT_OPERAND, invalid insn for %%W");
3116 else if (letter
== 'A')
3117 fputs (code
== LABEL_REF
? "i" : "in", file
);
3119 else if (letter
== 'P')
3121 if (code
== LABEL_REF
)
3122 output_addr_const (file
, op
);
3123 else if (code
!= PC
)
3124 output_operand_lossage ("invalid %%P operand");
3127 else if (letter
== 'p')
3130 if (code
!= CONST_INT
3131 || (value
= exact_log2 (INTVAL (op
))) < 0)
3132 output_operand_lossage ("invalid %%p value");
3133 fprintf (file
, "%d", value
);
3136 else if (letter
== 'Z')
3141 else if (code
== REG
|| code
== SUBREG
)
3146 regnum
= REGNO (op
);
3148 regnum
= true_regnum (op
);
3150 if ((letter
== 'M' && ! WORDS_BIG_ENDIAN
)
3151 || (letter
== 'L' && WORDS_BIG_ENDIAN
)
3155 fprintf (file
, "%s", reg_names
[regnum
]);
3158 else if (code
== MEM
)
3161 output_address (plus_constant (XEXP (op
, 0), 4));
3163 output_address (XEXP (op
, 0));
3166 else if (code
== CONST_DOUBLE
3167 && GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
3171 real_to_decimal (s
, CONST_DOUBLE_REAL_VALUE (op
), sizeof (s
), 0, 1);
3175 else if (letter
== 'x' && GET_CODE (op
) == CONST_INT
)
3176 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, 0xffff & INTVAL(op
));
3178 else if (letter
== 'X' && GET_CODE(op
) == CONST_INT
)
3179 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, 0xffff & (INTVAL (op
) >> 16));
3181 else if (letter
== 'd' && GET_CODE(op
) == CONST_INT
)
3182 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, (INTVAL(op
)));
3184 else if (letter
== 'z' && GET_CODE (op
) == CONST_INT
&& INTVAL (op
) == 0)
3185 fputs (reg_names
[GP_REG_FIRST
], file
);
3187 else if (letter
== 'd' || letter
== 'x' || letter
== 'X')
3188 output_operand_lossage ("invalid use of %%d, %%x, or %%X");
3190 else if (letter
== 'B')
3191 fputs (code
== EQ
? "z" : "n", file
);
3192 else if (letter
== 'b')
3193 fputs (code
== EQ
? "n" : "z", file
);
3194 else if (letter
== 'T')
3195 fputs (code
== EQ
? "f" : "t", file
);
3196 else if (letter
== 't')
3197 fputs (code
== EQ
? "t" : "f", file
);
3199 else if (code
== CONST
&& GET_CODE (XEXP (op
, 0)) == REG
)
3201 print_operand (file
, XEXP (op
, 0), letter
);
3205 output_addr_const (file
, op
);
3209 iq2000_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
, int * total
)
3211 enum machine_mode mode
= GET_MODE (x
);
3217 int num_words
= (GET_MODE_SIZE (mode
) > UNITS_PER_WORD
) ? 2 : 1;
3219 if (simple_memory_operand (x
, mode
))
3220 return COSTS_N_INSNS (num_words
);
3222 * total
= COSTS_N_INSNS (2 * num_words
);
3227 * total
= COSTS_N_INSNS (6);
3234 * total
= COSTS_N_INSNS (mode
== DImode
? 2 : 1);
3241 * total
= COSTS_N_INSNS ((GET_CODE (XEXP (x
, 1)) == CONST_INT
) ? 4 : 12);
3243 * total
= COSTS_N_INSNS (1);
3247 if (mode
== SFmode
|| mode
== DFmode
)
3248 * total
= COSTS_N_INSNS (1);
3250 * total
= COSTS_N_INSNS (4);
3255 if (mode
== SFmode
|| mode
== DFmode
)
3256 * total
= COSTS_N_INSNS (6);
3257 else if (mode
== DImode
)
3258 * total
= COSTS_N_INSNS (4);
3260 * total
= COSTS_N_INSNS (1);
3264 * total
= (mode
== DImode
) ? 4 : 1;
3269 * total
= COSTS_N_INSNS (7);
3270 else if (mode
== DFmode
)
3271 * total
= COSTS_N_INSNS (8);
3273 * total
= COSTS_N_INSNS (10);
3279 * total
= COSTS_N_INSNS (23);
3280 else if (mode
== DFmode
)
3281 * total
= COSTS_N_INSNS (36);
3283 * total
= COSTS_N_INSNS (69);
3288 * total
= COSTS_N_INSNS (69);
3292 * total
= COSTS_N_INSNS (2);
3296 * total
= COSTS_N_INSNS (1);
3304 * total
= COSTS_N_INSNS (2);
3309 rtx offset
= const0_rtx
;
3310 rtx symref
= eliminate_constant_term (XEXP (x
, 0), & offset
);
3312 if (GET_CODE (symref
) == LABEL_REF
)
3313 * total
= COSTS_N_INSNS (2);
3314 else if (GET_CODE (symref
) != SYMBOL_REF
)
3315 * total
= COSTS_N_INSNS (4);
3316 /* Let's be paranoid.... */
3317 else if (INTVAL (offset
) < -32768 || INTVAL (offset
) > 32767)
3318 * total
= COSTS_N_INSNS (2);
3320 * total
= COSTS_N_INSNS (SYMBOL_REF_FLAG (symref
) ? 1 : 2);
3325 * total
= COSTS_N_INSNS (SYMBOL_REF_FLAG (x
) ? 1 : 2);
3332 split_double (x
, & high
, & low
);
3334 * total
= COSTS_N_INSNS ( (high
== CONST0_RTX (GET_MODE (high
))
3335 || low
== CONST0_RTX (GET_MODE (low
)))
3346 #include "gt-iq2000.h"