1 /* Subroutines used for code generation on Vitesse IQ2000 processors
2 Copyright (C) 2003, 2004, 2005, 2006, 2007 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 3, 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 COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
33 #include "insn-attr.h"
46 #include "target-def.h"
47 #include "langhooks.h"
49 /* Enumeration for all of the relational tests, so that we can build
50 arrays indexed by the test type, and not worry about the order
71 /* Structure to be filled in by compute_frame_size with register
72 save masks, and offsets for the current function. */
74 struct iq2000_frame_info
76 long total_size
; /* # bytes that the entire frame takes up. */
77 long var_size
; /* # bytes that variables take up. */
78 long args_size
; /* # bytes that outgoing arguments take up. */
79 long extra_size
; /* # bytes of extra gunk. */
80 int gp_reg_size
; /* # bytes needed to store gp regs. */
81 int fp_reg_size
; /* # bytes needed to store fp regs. */
82 long mask
; /* Mask of saved gp registers. */
83 long gp_save_offset
; /* Offset from vfp to store gp registers. */
84 long fp_save_offset
; /* Offset from vfp to store fp registers. */
85 long gp_sp_offset
; /* Offset from new sp to store gp registers. */
86 long fp_sp_offset
; /* Offset from new sp to store fp registers. */
87 int initialized
; /* != 0 if frame size already calculated. */
88 int num_gp
; /* Number of gp registers saved. */
91 struct machine_function
GTY(())
93 /* Current frame information, calculated by compute_frame_size. */
94 long total_size
; /* # bytes that the entire frame takes up. */
95 long var_size
; /* # bytes that variables take up. */
96 long args_size
; /* # bytes that outgoing arguments take up. */
97 long extra_size
; /* # bytes of extra gunk. */
98 int gp_reg_size
; /* # bytes needed to store gp regs. */
99 int fp_reg_size
; /* # bytes needed to store fp regs. */
100 long mask
; /* Mask of saved gp registers. */
101 long gp_save_offset
; /* Offset from vfp to store gp registers. */
102 long fp_save_offset
; /* Offset from vfp to store fp registers. */
103 long gp_sp_offset
; /* Offset from new sp to store gp registers. */
104 long fp_sp_offset
; /* Offset from new sp to store fp registers. */
105 int initialized
; /* != 0 if frame size already calculated. */
106 int num_gp
; /* Number of gp registers saved. */
109 /* Global variables for machine-dependent things. */
111 /* List of all IQ2000 punctuation characters used by print_operand. */
112 char iq2000_print_operand_punct
[256];
114 /* The target cpu for optimization and scheduling. */
115 enum processor_type iq2000_tune
;
117 /* Which instruction set architecture to use. */
120 /* Cached operands, and operator to compare for use in set/branch/trap
121 on condition codes. */
124 /* What type of branch to use. */
125 enum cmp_type branch_type
;
127 /* Local variables. */
129 /* The next branch instruction is a branch likely, not branch normal. */
130 static int iq2000_branch_likely
;
132 /* Count of delay slots and how many are filled. */
133 static int dslots_load_total
;
134 static int dslots_load_filled
;
135 static int dslots_jump_total
;
137 /* # of nops needed by previous insn. */
138 static int dslots_number_nops
;
140 /* Number of 1/2/3 word references to data items (i.e., not jal's). */
141 static int num_refs
[3];
143 /* Registers to check for load delay. */
144 static rtx iq2000_load_reg
;
145 static rtx iq2000_load_reg2
;
146 static rtx iq2000_load_reg3
;
147 static rtx iq2000_load_reg4
;
149 /* Mode used for saving/restoring general purpose registers. */
150 static enum machine_mode gpr_mode
;
153 /* Initialize the GCC target structure. */
154 static struct machine_function
* iq2000_init_machine_status (void);
155 static bool iq2000_handle_option (size_t, const char *, int);
156 static section
*iq2000_select_rtx_section (enum machine_mode
, rtx
,
157 unsigned HOST_WIDE_INT
);
158 static void iq2000_init_builtins (void);
159 static rtx
iq2000_expand_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
160 static bool iq2000_return_in_memory (const_tree
, const_tree
);
161 static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS
*,
162 enum machine_mode
, tree
, int *,
164 static bool iq2000_rtx_costs (rtx
, int, int, int *);
165 static int iq2000_address_cost (rtx
);
166 static section
*iq2000_select_section (tree
, int, unsigned HOST_WIDE_INT
);
167 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS
*, enum machine_mode
,
169 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS
*, enum machine_mode
,
172 #undef TARGET_INIT_BUILTINS
173 #define TARGET_INIT_BUILTINS iq2000_init_builtins
174 #undef TARGET_EXPAND_BUILTIN
175 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin
176 #undef TARGET_ASM_SELECT_RTX_SECTION
177 #define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section
178 #undef TARGET_HANDLE_OPTION
179 #define TARGET_HANDLE_OPTION iq2000_handle_option
180 #undef TARGET_RTX_COSTS
181 #define TARGET_RTX_COSTS iq2000_rtx_costs
182 #undef TARGET_ADDRESS_COST
183 #define TARGET_ADDRESS_COST iq2000_address_cost
184 #undef TARGET_ASM_SELECT_SECTION
185 #define TARGET_ASM_SELECT_SECTION iq2000_select_section
187 /* The assembler supports switchable .bss sections, but
188 iq2000_select_section doesn't yet make use of them. */
189 #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
190 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false
192 #undef TARGET_PROMOTE_FUNCTION_ARGS
193 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
194 #undef TARGET_PROMOTE_FUNCTION_RETURN
195 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
196 #undef TARGET_PROMOTE_PROTOTYPES
197 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
199 #undef TARGET_RETURN_IN_MEMORY
200 #define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
201 #undef TARGET_PASS_BY_REFERENCE
202 #define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference
203 #undef TARGET_CALLEE_COPIES
204 #define TARGET_CALLEE_COPIES hook_callee_copies_named
205 #undef TARGET_ARG_PARTIAL_BYTES
206 #define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes
208 #undef TARGET_SETUP_INCOMING_VARARGS
209 #define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs
210 #undef TARGET_STRICT_ARGUMENT_NAMING
211 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
213 struct gcc_target targetm
= TARGET_INITIALIZER
;
215 /* Return nonzero if we split the address into high and low parts. */
218 iq2000_check_split (rtx address
, enum machine_mode mode
)
220 /* This is the same check used in simple_memory_operand.
221 We use it here because LO_SUM is not offsettable. */
222 if (GET_MODE_SIZE (mode
) > (unsigned) UNITS_PER_WORD
)
225 if ((GET_CODE (address
) == SYMBOL_REF
)
226 || (GET_CODE (address
) == CONST
227 && GET_CODE (XEXP (XEXP (address
, 0), 0)) == SYMBOL_REF
)
228 || GET_CODE (address
) == LABEL_REF
)
234 /* Return nonzero if REG is valid for MODE. */
237 iq2000_reg_mode_ok_for_base_p (rtx reg
,
238 enum machine_mode mode ATTRIBUTE_UNUSED
,
242 ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg
), mode
)
243 : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg
), mode
));
246 /* Return a nonzero value if XINSN is a legitimate address for a
247 memory operand of the indicated MODE. STRICT is nonzero if this
248 function is called during reload. */
251 iq2000_legitimate_address_p (enum machine_mode mode
, rtx xinsn
, int strict
)
253 if (TARGET_DEBUG_A_MODE
)
255 GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
256 strict
? "" : "not ");
257 GO_DEBUG_RTX (xinsn
);
260 /* Check for constant before stripping off SUBREG, so that we don't
261 accept (subreg (const_int)) which will fail to reload. */
262 if (CONSTANT_ADDRESS_P (xinsn
)
263 && ! (iq2000_check_split (xinsn
, mode
))
264 && ! (GET_CODE (xinsn
) == CONST_INT
&& ! SMALL_INT (xinsn
)))
267 while (GET_CODE (xinsn
) == SUBREG
)
268 xinsn
= SUBREG_REG (xinsn
);
270 if (GET_CODE (xinsn
) == REG
271 && iq2000_reg_mode_ok_for_base_p (xinsn
, mode
, strict
))
274 if (GET_CODE (xinsn
) == LO_SUM
)
276 rtx xlow0
= XEXP (xinsn
, 0);
277 rtx xlow1
= XEXP (xinsn
, 1);
279 while (GET_CODE (xlow0
) == SUBREG
)
280 xlow0
= SUBREG_REG (xlow0
);
281 if (GET_CODE (xlow0
) == REG
282 && iq2000_reg_mode_ok_for_base_p (xlow0
, mode
, strict
)
283 && iq2000_check_split (xlow1
, mode
))
287 if (GET_CODE (xinsn
) == PLUS
)
289 rtx xplus0
= XEXP (xinsn
, 0);
290 rtx xplus1
= XEXP (xinsn
, 1);
294 while (GET_CODE (xplus0
) == SUBREG
)
295 xplus0
= SUBREG_REG (xplus0
);
296 code0
= GET_CODE (xplus0
);
298 while (GET_CODE (xplus1
) == SUBREG
)
299 xplus1
= SUBREG_REG (xplus1
);
300 code1
= GET_CODE (xplus1
);
303 && iq2000_reg_mode_ok_for_base_p (xplus0
, mode
, strict
))
305 if (code1
== CONST_INT
&& SMALL_INT (xplus1
)
306 && SMALL_INT_UNSIGNED (xplus1
) /* No negative offsets */)
311 if (TARGET_DEBUG_A_MODE
)
312 GO_PRINTF ("Not a legitimate address\n");
314 /* The address was not legitimate. */
318 /* Returns an operand string for the given instruction's delay slot,
319 after updating filled delay slot statistics.
321 We assume that operands[0] is the target register that is set.
323 In order to check the next insn, most of this functionality is moved
324 to FINAL_PRESCAN_INSN, and we just set the global variables that
328 iq2000_fill_delay_slot (const char *ret
, enum delay_type type
, rtx operands
[],
332 enum machine_mode mode
;
333 rtx next_insn
= cur_insn
? NEXT_INSN (cur_insn
) : NULL_RTX
;
336 if (type
== DELAY_LOAD
|| type
== DELAY_FCMP
)
342 /* Make sure that we don't put nop's after labels. */
343 next_insn
= NEXT_INSN (cur_insn
);
344 while (next_insn
!= 0
345 && (GET_CODE (next_insn
) == NOTE
346 || GET_CODE (next_insn
) == CODE_LABEL
))
347 next_insn
= NEXT_INSN (next_insn
);
349 dslots_load_total
+= num_nops
;
350 if (TARGET_DEBUG_C_MODE
351 || type
== DELAY_NONE
355 || GET_CODE (next_insn
) == CODE_LABEL
356 || (set_reg
= operands
[0]) == 0)
358 dslots_number_nops
= 0;
360 iq2000_load_reg2
= 0;
361 iq2000_load_reg3
= 0;
362 iq2000_load_reg4
= 0;
367 set_reg
= operands
[0];
371 while (GET_CODE (set_reg
) == SUBREG
)
372 set_reg
= SUBREG_REG (set_reg
);
374 mode
= GET_MODE (set_reg
);
375 dslots_number_nops
= num_nops
;
376 iq2000_load_reg
= set_reg
;
377 if (GET_MODE_SIZE (mode
)
378 > (unsigned) (UNITS_PER_WORD
))
379 iq2000_load_reg2
= gen_rtx_REG (SImode
, REGNO (set_reg
) + 1);
381 iq2000_load_reg2
= 0;
386 /* Determine whether a memory reference takes one (based off of the GP
387 pointer), two (normal), or three (label + reg) instructions, and bump the
388 appropriate counter for -mstats. */
391 iq2000_count_memory_refs (rtx op
, int num
)
395 rtx addr
, plus0
, plus1
;
396 enum rtx_code code0
, code1
;
399 if (TARGET_DEBUG_B_MODE
)
401 fprintf (stderr
, "\n========== iq2000_count_memory_refs:\n");
405 /* Skip MEM if passed, otherwise handle movsi of address. */
406 addr
= (GET_CODE (op
) != MEM
) ? op
: XEXP (op
, 0);
408 /* Loop, going through the address RTL. */
412 switch (GET_CODE (addr
))
420 plus0
= XEXP (addr
, 0);
421 plus1
= XEXP (addr
, 1);
422 code0
= GET_CODE (plus0
);
423 code1
= GET_CODE (plus1
);
433 if (code0
== CONST_INT
)
448 if (code1
== CONST_INT
)
455 if (code0
== SYMBOL_REF
|| code0
== LABEL_REF
|| code0
== CONST
)
462 if (code1
== SYMBOL_REF
|| code1
== LABEL_REF
|| code1
== CONST
)
472 n_words
= 2; /* Always 2 words. */
476 addr
= XEXP (addr
, 0);
481 n_words
= SYMBOL_REF_FLAG (addr
) ? 1 : 2;
493 n_words
+= additional
;
497 num_refs
[n_words
-1] += num
;
500 /* Abort after printing out a specific insn. */
503 abort_with_insn (rtx insn
, const char * reason
)
507 fancy_abort (__FILE__
, __LINE__
, __FUNCTION__
);
510 /* Return the appropriate instructions to move one operand to another. */
513 iq2000_move_1word (rtx operands
[], rtx insn
, int unsignedp
)
516 rtx op0
= operands
[0];
517 rtx op1
= operands
[1];
518 enum rtx_code code0
= GET_CODE (op0
);
519 enum rtx_code code1
= GET_CODE (op1
);
520 enum machine_mode mode
= GET_MODE (op0
);
521 int subreg_offset0
= 0;
522 int subreg_offset1
= 0;
523 enum delay_type delay
= DELAY_NONE
;
525 while (code0
== SUBREG
)
527 subreg_offset0
+= subreg_regno_offset (REGNO (SUBREG_REG (op0
)),
528 GET_MODE (SUBREG_REG (op0
)),
531 op0
= SUBREG_REG (op0
);
532 code0
= GET_CODE (op0
);
535 while (code1
== SUBREG
)
537 subreg_offset1
+= subreg_regno_offset (REGNO (SUBREG_REG (op1
)),
538 GET_MODE (SUBREG_REG (op1
)),
541 op1
= SUBREG_REG (op1
);
542 code1
= GET_CODE (op1
);
545 /* For our purposes, a condition code mode is the same as SImode. */
551 int regno0
= REGNO (op0
) + subreg_offset0
;
555 int regno1
= REGNO (op1
) + subreg_offset1
;
557 /* Do not do anything for assigning a register to itself */
558 if (regno0
== regno1
)
561 else if (GP_REG_P (regno0
))
563 if (GP_REG_P (regno1
))
564 ret
= "or\t%0,%%0,%1";
569 else if (code1
== MEM
)
574 iq2000_count_memory_refs (op1
, 1);
576 if (GP_REG_P (regno0
))
578 /* For loads, use the mode of the memory item, instead of the
579 target, so zero/sign extend can use this code as well. */
580 switch (GET_MODE (op1
))
592 ret
= (unsignedp
) ? "lhu\t%0,%1" : "lh\t%0,%1";
595 ret
= (unsignedp
) ? "lbu\t%0,%1" : "lb\t%0,%1";
601 else if (code1
== CONST_INT
602 || (code1
== CONST_DOUBLE
603 && GET_MODE (op1
) == VOIDmode
))
605 if (code1
== CONST_DOUBLE
)
607 /* This can happen when storing constants into long long
608 bitfields. Just store the least significant word of
610 operands
[1] = op1
= GEN_INT (CONST_DOUBLE_LOW (op1
));
613 if (INTVAL (op1
) == 0)
615 if (GP_REG_P (regno0
))
616 ret
= "or\t%0,%%0,%z1";
618 else if (GP_REG_P (regno0
))
620 if (SMALL_INT_UNSIGNED (op1
))
621 ret
= "ori\t%0,%%0,%x1\t\t\t# %1";
622 else if (SMALL_INT (op1
))
623 ret
= "addiu\t%0,%%0,%1\t\t\t# %1";
625 ret
= "lui\t%0,%X1\t\t\t# %1\n\tori\t%0,%0,%x1";
629 else if (code1
== CONST_DOUBLE
&& mode
== SFmode
)
631 if (op1
== CONST0_RTX (SFmode
))
633 if (GP_REG_P (regno0
))
634 ret
= "or\t%0,%%0,%.";
644 else if (code1
== LABEL_REF
)
647 iq2000_count_memory_refs (op1
, 1);
652 else if (code1
== SYMBOL_REF
|| code1
== CONST
)
655 iq2000_count_memory_refs (op1
, 1);
660 else if (code1
== PLUS
)
662 rtx add_op0
= XEXP (op1
, 0);
663 rtx add_op1
= XEXP (op1
, 1);
665 if (GET_CODE (XEXP (op1
, 1)) == REG
666 && GET_CODE (XEXP (op1
, 0)) == CONST_INT
)
667 add_op0
= XEXP (op1
, 1), add_op1
= XEXP (op1
, 0);
669 operands
[2] = add_op0
;
670 operands
[3] = add_op1
;
671 ret
= "add%:\t%0,%2,%3";
674 else if (code1
== HIGH
)
676 operands
[1] = XEXP (op1
, 0);
677 ret
= "lui\t%0,%%hi(%1)";
681 else if (code0
== MEM
)
684 iq2000_count_memory_refs (op0
, 1);
688 int regno1
= REGNO (op1
) + subreg_offset1
;
690 if (GP_REG_P (regno1
))
694 case SFmode
: ret
= "sw\t%1,%0"; break;
695 case SImode
: ret
= "sw\t%1,%0"; break;
696 case HImode
: ret
= "sh\t%1,%0"; break;
697 case QImode
: ret
= "sb\t%1,%0"; break;
703 else if (code1
== CONST_INT
&& INTVAL (op1
) == 0)
707 case SFmode
: ret
= "sw\t%z1,%0"; break;
708 case SImode
: ret
= "sw\t%z1,%0"; break;
709 case HImode
: ret
= "sh\t%z1,%0"; break;
710 case QImode
: ret
= "sb\t%z1,%0"; break;
715 else if (code1
== CONST_DOUBLE
&& op1
== CONST0_RTX (mode
))
719 case SFmode
: ret
= "sw\t%.,%0"; break;
720 case SImode
: ret
= "sw\t%.,%0"; break;
721 case HImode
: ret
= "sh\t%.,%0"; break;
722 case QImode
: ret
= "sb\t%.,%0"; break;
730 abort_with_insn (insn
, "Bad move");
734 if (delay
!= DELAY_NONE
)
735 return iq2000_fill_delay_slot (ret
, delay
, operands
, insn
);
740 /* Provide the costs of an addressing mode that contains ADDR. */
743 iq2000_address_cost (rtx addr
)
745 switch (GET_CODE (addr
))
755 rtx offset
= const0_rtx
;
757 addr
= eliminate_constant_term (XEXP (addr
, 0), & offset
);
758 if (GET_CODE (addr
) == LABEL_REF
)
761 if (GET_CODE (addr
) != SYMBOL_REF
)
764 if (! SMALL_INT (offset
))
771 return SYMBOL_REF_FLAG (addr
) ? 1 : 2;
775 rtx plus0
= XEXP (addr
, 0);
776 rtx plus1
= XEXP (addr
, 1);
778 if (GET_CODE (plus0
) != REG
&& GET_CODE (plus1
) == REG
)
779 plus0
= XEXP (addr
, 1), plus1
= XEXP (addr
, 0);
781 if (GET_CODE (plus0
) != REG
)
784 switch (GET_CODE (plus1
))
787 return SMALL_INT (plus1
) ? 1 : 2;
794 return iq2000_address_cost (plus1
) + 1;
808 /* Make normal rtx_code into something we can index from an array. */
810 static enum internal_test
811 map_test_to_internal_test (enum rtx_code test_code
)
813 enum internal_test test
= ITEST_MAX
;
817 case EQ
: test
= ITEST_EQ
; break;
818 case NE
: test
= ITEST_NE
; break;
819 case GT
: test
= ITEST_GT
; break;
820 case GE
: test
= ITEST_GE
; break;
821 case LT
: test
= ITEST_LT
; break;
822 case LE
: test
= ITEST_LE
; break;
823 case GTU
: test
= ITEST_GTU
; break;
824 case GEU
: test
= ITEST_GEU
; break;
825 case LTU
: test
= ITEST_LTU
; break;
826 case LEU
: test
= ITEST_LEU
; break;
833 /* Generate the code to do a TEST_CODE comparison on two integer values CMP0
834 and CMP1. P_INVERT is NULL or ptr if branch needs to reverse its test.
835 The return value RESULT is:
836 (reg:SI xx) The pseudo register the comparison is in
837 0 No register, generate a simple branch. */
840 gen_int_relational (enum rtx_code test_code
, rtx result
, rtx cmp0
, rtx cmp1
,
845 enum rtx_code test_code
; /* Code to use in instruction (LT vs. LTU). */
846 int const_low
; /* Low bound of constant we can accept. */
847 int const_high
; /* High bound of constant we can accept. */
848 int const_add
; /* Constant to add (convert LE -> LT). */
849 int reverse_regs
; /* Reverse registers in test. */
850 int invert_const
; /* != 0 if invert value if cmp1 is constant. */
851 int invert_reg
; /* != 0 if invert value if cmp1 is register. */
852 int unsignedp
; /* != 0 for unsigned comparisons. */
855 static struct cmp_info info
[ (int)ITEST_MAX
] =
857 { XOR
, 0, 65535, 0, 0, 0, 0, 0 }, /* EQ */
858 { XOR
, 0, 65535, 0, 0, 1, 1, 0 }, /* NE */
859 { LT
, -32769, 32766, 1, 1, 1, 0, 0 }, /* GT */
860 { LT
, -32768, 32767, 0, 0, 1, 1, 0 }, /* GE */
861 { LT
, -32768, 32767, 0, 0, 0, 0, 0 }, /* LT */
862 { LT
, -32769, 32766, 1, 1, 0, 1, 0 }, /* LE */
863 { LTU
, -32769, 32766, 1, 1, 1, 0, 1 }, /* GTU */
864 { LTU
, -32768, 32767, 0, 0, 1, 1, 1 }, /* GEU */
865 { LTU
, -32768, 32767, 0, 0, 0, 0, 1 }, /* LTU */
866 { LTU
, -32769, 32766, 1, 1, 0, 1, 1 }, /* LEU */
869 enum internal_test test
;
870 enum machine_mode mode
;
871 struct cmp_info
*p_info
;
878 test
= map_test_to_internal_test (test_code
);
879 gcc_assert (test
!= ITEST_MAX
);
881 p_info
= &info
[(int) test
];
882 eqne_p
= (p_info
->test_code
== XOR
);
884 mode
= GET_MODE (cmp0
);
885 if (mode
== VOIDmode
)
886 mode
= GET_MODE (cmp1
);
888 /* Eliminate simple branches. */
889 branch_p
= (result
== 0);
892 if (GET_CODE (cmp0
) == REG
|| GET_CODE (cmp0
) == SUBREG
)
894 /* Comparisons against zero are simple branches. */
895 if (GET_CODE (cmp1
) == CONST_INT
&& INTVAL (cmp1
) == 0)
898 /* Test for beq/bne. */
903 /* Allocate a pseudo to calculate the value in. */
904 result
= gen_reg_rtx (mode
);
907 /* Make sure we can handle any constants given to us. */
908 if (GET_CODE (cmp0
) == CONST_INT
)
909 cmp0
= force_reg (mode
, cmp0
);
911 if (GET_CODE (cmp1
) == CONST_INT
)
913 HOST_WIDE_INT value
= INTVAL (cmp1
);
915 if (value
< p_info
->const_low
916 || value
> p_info
->const_high
)
917 cmp1
= force_reg (mode
, cmp1
);
920 /* See if we need to invert the result. */
921 invert
= (GET_CODE (cmp1
) == CONST_INT
922 ? p_info
->invert_const
: p_info
->invert_reg
);
924 if (p_invert
!= (int *)0)
930 /* Comparison to constants, may involve adding 1 to change a LT into LE.
931 Comparison between two registers, may involve switching operands. */
932 if (GET_CODE (cmp1
) == CONST_INT
)
934 if (p_info
->const_add
!= 0)
936 HOST_WIDE_INT
new = INTVAL (cmp1
) + p_info
->const_add
;
938 /* If modification of cmp1 caused overflow,
939 we would get the wrong answer if we follow the usual path;
940 thus, x > 0xffffffffU would turn into x > 0U. */
941 if ((p_info
->unsignedp
942 ? (unsigned HOST_WIDE_INT
) new >
943 (unsigned HOST_WIDE_INT
) INTVAL (cmp1
)
944 : new > INTVAL (cmp1
))
945 != (p_info
->const_add
> 0))
947 /* This test is always true, but if INVERT is true then
948 the result of the test needs to be inverted so 0 should
949 be returned instead. */
950 emit_move_insn (result
, invert
? const0_rtx
: const_true_rtx
);
954 cmp1
= GEN_INT (new);
958 else if (p_info
->reverse_regs
)
965 if (test
== ITEST_NE
&& GET_CODE (cmp1
) == CONST_INT
&& INTVAL (cmp1
) == 0)
969 reg
= (invert
|| eqne_p
) ? gen_reg_rtx (mode
) : result
;
970 convert_move (reg
, gen_rtx_fmt_ee (p_info
->test_code
, mode
, cmp0
, cmp1
), 0);
973 if (test
== ITEST_NE
)
975 convert_move (result
, gen_rtx_GTU (mode
, reg
, const0_rtx
), 0);
976 if (p_invert
!= NULL
)
981 else if (test
== ITEST_EQ
)
983 reg2
= invert
? gen_reg_rtx (mode
) : result
;
984 convert_move (reg2
, gen_rtx_LTU (mode
, reg
, const1_rtx
), 0);
993 convert_move (result
, gen_rtx_XOR (mode
, reg
, one
), 0);
999 /* Emit the common code for doing conditional branches.
1000 operand[0] is the label to jump to.
1001 The comparison operands are saved away by cmp{si,di,sf,df}. */
1004 gen_conditional_branch (rtx operands
[], enum rtx_code test_code
)
1006 enum cmp_type type
= branch_type
;
1007 rtx cmp0
= branch_cmp
[0];
1008 rtx cmp1
= branch_cmp
[1];
1009 enum machine_mode mode
;
1018 mode
= type
== CMP_SI
? SImode
: DImode
;
1020 reg
= gen_int_relational (test_code
, NULL_RTX
, cmp0
, cmp1
, &invert
);
1028 else if (GET_CODE (cmp1
) == CONST_INT
&& INTVAL (cmp1
) != 0)
1029 /* We don't want to build a comparison against a nonzero
1031 cmp1
= force_reg (mode
, cmp1
);
1037 reg
= gen_reg_rtx (CCmode
);
1039 /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */
1040 emit_insn (gen_rtx_SET (VOIDmode
, reg
,
1041 gen_rtx_fmt_ee (test_code
== NE
? EQ
: test_code
,
1042 CCmode
, cmp0
, cmp1
)));
1044 test_code
= test_code
== NE
? EQ
: NE
;
1052 abort_with_insn (gen_rtx_fmt_ee (test_code
, VOIDmode
, cmp0
, cmp1
),
1056 /* Generate the branch. */
1057 label1
= gen_rtx_LABEL_REF (VOIDmode
, operands
[0]);
1066 emit_jump_insn (gen_rtx_SET (VOIDmode
, pc_rtx
,
1067 gen_rtx_IF_THEN_ELSE (VOIDmode
,
1068 gen_rtx_fmt_ee (test_code
,
1074 /* Initialize CUM for a function FNTYPE. */
1077 init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
,
1078 rtx libname ATTRIBUTE_UNUSED
)
1080 static CUMULATIVE_ARGS zero_cum
;
1084 if (TARGET_DEBUG_D_MODE
)
1087 "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype
);
1090 fputc ('\n', stderr
);
1094 tree ret_type
= TREE_TYPE (fntype
);
1096 fprintf (stderr
, ", fntype code = %s, ret code = %s\n",
1097 tree_code_name
[(int)TREE_CODE (fntype
)],
1098 tree_code_name
[(int)TREE_CODE (ret_type
)]);
1104 /* Determine if this function has variable arguments. This is
1105 indicated by the last argument being 'void_type_mode' if there
1106 are no variable arguments. The standard IQ2000 calling sequence
1107 passes all arguments in the general purpose registers in this case. */
1109 for (param
= fntype
? TYPE_ARG_TYPES (fntype
) : 0;
1110 param
!= 0; param
= next_param
)
1112 next_param
= TREE_CHAIN (param
);
1113 if (next_param
== 0 && TREE_VALUE (param
) != void_type_node
)
1114 cum
->gp_reg_found
= 1;
1118 /* Advance the argument of type TYPE and mode MODE to the next argument
1122 function_arg_advance (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1125 if (TARGET_DEBUG_D_MODE
)
1128 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1129 cum
->gp_reg_found
, cum
->arg_number
, cum
->arg_words
,
1130 GET_MODE_NAME (mode
));
1131 fprintf (stderr
, "%p", (void *) type
);
1132 fprintf (stderr
, ", %d )\n\n", named
);
1142 gcc_assert (GET_MODE_CLASS (mode
) == MODE_COMPLEX_INT
1143 || GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
);
1145 cum
->gp_reg_found
= 1;
1146 cum
->arg_words
+= ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
1151 cum
->gp_reg_found
= 1;
1152 cum
->arg_words
+= ((int_size_in_bytes (type
) + UNITS_PER_WORD
- 1)
1158 if (! cum
->gp_reg_found
&& cum
->arg_number
<= 2)
1159 cum
->fp_code
+= 1 << ((cum
->arg_number
- 1) * 2);
1163 cum
->arg_words
+= 2;
1164 if (! cum
->gp_reg_found
&& cum
->arg_number
<= 2)
1165 cum
->fp_code
+= 2 << ((cum
->arg_number
- 1) * 2);
1169 cum
->gp_reg_found
= 1;
1170 cum
->arg_words
+= 2;
1176 cum
->gp_reg_found
= 1;
1182 /* Return an RTL expression containing the register for the given mode MODE
1183 and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */
1186 function_arg (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, const_tree type
,
1192 unsigned int *arg_words
= &cum
->arg_words
;
1193 int struct_p
= (type
!= 0
1194 && (TREE_CODE (type
) == RECORD_TYPE
1195 || TREE_CODE (type
) == UNION_TYPE
1196 || TREE_CODE (type
) == QUAL_UNION_TYPE
));
1198 if (TARGET_DEBUG_D_MODE
)
1201 "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1202 cum
->gp_reg_found
, cum
->arg_number
, cum
->arg_words
,
1203 GET_MODE_NAME (mode
));
1204 fprintf (stderr
, "%p", (const void *) type
);
1205 fprintf (stderr
, ", %d ) = ", named
);
1209 cum
->last_arg_fp
= 0;
1213 regbase
= GP_ARG_FIRST
;
1217 cum
->arg_words
+= cum
->arg_words
& 1;
1219 regbase
= GP_ARG_FIRST
;
1223 gcc_assert (GET_MODE_CLASS (mode
) == MODE_COMPLEX_INT
1224 || GET_MODE_CLASS (mode
) == MODE_COMPLEX_FLOAT
);
1226 /* Drops through. */
1228 if (type
!= NULL_TREE
&& TYPE_ALIGN (type
) > (unsigned) BITS_PER_WORD
)
1229 cum
->arg_words
+= (cum
->arg_words
& 1);
1230 regbase
= GP_ARG_FIRST
;
1237 regbase
= GP_ARG_FIRST
;
1241 cum
->arg_words
+= (cum
->arg_words
& 1);
1242 regbase
= GP_ARG_FIRST
;
1245 if (*arg_words
>= (unsigned) MAX_ARGS_IN_REGISTERS
)
1247 if (TARGET_DEBUG_D_MODE
)
1248 fprintf (stderr
, "<stack>%s\n", struct_p
? ", [struct]" : "");
1254 gcc_assert (regbase
!= -1);
1256 if (! type
|| TREE_CODE (type
) != RECORD_TYPE
1257 || ! named
|| ! TYPE_SIZE_UNIT (type
)
1258 || ! host_integerp (TYPE_SIZE_UNIT (type
), 1))
1259 ret
= gen_rtx_REG (mode
, regbase
+ *arg_words
+ bias
);
1264 for (field
= TYPE_FIELDS (type
); field
; field
= TREE_CHAIN (field
))
1265 if (TREE_CODE (field
) == FIELD_DECL
1266 && TREE_CODE (TREE_TYPE (field
)) == REAL_TYPE
1267 && TYPE_PRECISION (TREE_TYPE (field
)) == BITS_PER_WORD
1268 && host_integerp (bit_position (field
), 0)
1269 && int_bit_position (field
) % BITS_PER_WORD
== 0)
1272 /* If the whole struct fits a DFmode register,
1273 we don't need the PARALLEL. */
1274 if (! field
|| mode
== DFmode
)
1275 ret
= gen_rtx_REG (mode
, regbase
+ *arg_words
+ bias
);
1278 unsigned int chunks
;
1279 HOST_WIDE_INT bitpos
;
1283 /* ??? If this is a packed structure, then the last hunk won't
1286 = tree_low_cst (TYPE_SIZE_UNIT (type
), 1) / UNITS_PER_WORD
;
1287 if (chunks
+ *arg_words
+ bias
> (unsigned) MAX_ARGS_IN_REGISTERS
)
1288 chunks
= MAX_ARGS_IN_REGISTERS
- *arg_words
- bias
;
1290 /* Assign_parms checks the mode of ENTRY_PARM, so we must
1291 use the actual mode here. */
1292 ret
= gen_rtx_PARALLEL (mode
, rtvec_alloc (chunks
));
1295 regno
= regbase
+ *arg_words
+ bias
;
1296 field
= TYPE_FIELDS (type
);
1297 for (i
= 0; i
< chunks
; i
++)
1301 for (; field
; field
= TREE_CHAIN (field
))
1302 if (TREE_CODE (field
) == FIELD_DECL
1303 && int_bit_position (field
) >= bitpos
)
1307 && int_bit_position (field
) == bitpos
1308 && TREE_CODE (TREE_TYPE (field
)) == REAL_TYPE
1309 && TYPE_PRECISION (TREE_TYPE (field
)) == BITS_PER_WORD
)
1310 reg
= gen_rtx_REG (DFmode
, regno
++);
1312 reg
= gen_rtx_REG (word_mode
, regno
);
1315 = gen_rtx_EXPR_LIST (VOIDmode
, reg
,
1316 GEN_INT (bitpos
/ BITS_PER_UNIT
));
1324 if (TARGET_DEBUG_D_MODE
)
1325 fprintf (stderr
, "%s%s\n", reg_names
[regbase
+ *arg_words
+ bias
],
1326 struct_p
? ", [struct]" : "");
1329 /* We will be called with a mode of VOIDmode after the last argument
1330 has been seen. Whatever we return will be passed to the call
1331 insn. If we need any shifts for small structures, return them in
1333 if (mode
== VOIDmode
)
1335 if (cum
->num_adjusts
> 0)
1336 ret
= gen_rtx_PARALLEL ((enum machine_mode
) cum
->fp_code
,
1337 gen_rtvec_v (cum
->num_adjusts
, cum
->adjust
));
1344 iq2000_arg_partial_bytes (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
,
1345 tree type ATTRIBUTE_UNUSED
,
1346 bool named ATTRIBUTE_UNUSED
)
1348 if (mode
== DImode
&& cum
->arg_words
== MAX_ARGS_IN_REGISTERS
- 1)
1350 if (TARGET_DEBUG_D_MODE
)
1351 fprintf (stderr
, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD
);
1352 return UNITS_PER_WORD
;
1358 /* Implement va_start. */
1361 iq2000_va_start (tree valist
, rtx nextarg
)
1364 /* Find out how many non-float named formals. */
1365 int gpr_save_area_size
;
1366 /* Note UNITS_PER_WORD is 4 bytes. */
1367 int_arg_words
= current_function_args_info
.arg_words
;
1369 if (int_arg_words
< 8 )
1370 /* Adjust for the prologue's economy measure. */
1371 gpr_save_area_size
= (8 - int_arg_words
) * UNITS_PER_WORD
;
1373 gpr_save_area_size
= 0;
1375 /* Everything is in the GPR save area, or in the overflow
1376 area which is contiguous with it. */
1377 nextarg
= plus_constant (nextarg
, - gpr_save_area_size
);
1378 std_expand_builtin_va_start (valist
, nextarg
);
1381 /* Allocate a chunk of memory for per-function machine-dependent data. */
1383 static struct machine_function
*
1384 iq2000_init_machine_status (void)
1386 struct machine_function
*f
;
1388 f
= ggc_alloc_cleared (sizeof (struct machine_function
));
1393 /* Implement TARGET_HANDLE_OPTION. */
1396 iq2000_handle_option (size_t code
, const char *arg
, int value ATTRIBUTE_UNUSED
)
1401 if (strcmp (arg
, "iq10") == 0)
1402 iq2000_tune
= PROCESSOR_IQ10
;
1403 else if (strcmp (arg
, "iq2000") == 0)
1404 iq2000_tune
= PROCESSOR_IQ2000
;
1410 /* This option has no effect at the moment. */
1411 return (strcmp (arg
, "default") == 0
1412 || strcmp (arg
, "DEFAULT") == 0
1413 || strcmp (arg
, "iq2000") == 0);
1420 /* Detect any conflicts in the switches. */
1423 override_options (void)
1425 target_flags
&= ~MASK_GPOPT
;
1427 iq2000_isa
= IQ2000_ISA_DEFAULT
;
1429 /* Identify the processor type. */
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;
1447 iq2000_print_operand_punct
['$'] = 1;
1448 iq2000_print_operand_punct
['+'] = 1;
1449 iq2000_print_operand_punct
['~'] = 1;
1451 /* Save GPR registers in word_mode sized hunks. word_mode hasn't been
1452 initialized yet, so we can't use that here. */
1455 /* Function to allocate machine-dependent function status. */
1456 init_machine_status
= iq2000_init_machine_status
;
1459 /* The arg pointer (which is eliminated) points to the virtual frame pointer,
1460 while the frame pointer (which may be eliminated) points to the stack
1461 pointer after the initial adjustments. */
1464 iq2000_debugger_offset (rtx addr
, HOST_WIDE_INT offset
)
1466 rtx offset2
= const0_rtx
;
1467 rtx reg
= eliminate_constant_term (addr
, & offset2
);
1470 offset
= INTVAL (offset2
);
1472 if (reg
== stack_pointer_rtx
|| reg
== frame_pointer_rtx
1473 || reg
== hard_frame_pointer_rtx
)
1475 HOST_WIDE_INT frame_size
= (!cfun
->machine
->initialized
)
1476 ? compute_frame_size (get_frame_size ())
1477 : cfun
->machine
->total_size
;
1479 offset
= offset
- frame_size
;
1485 /* If defined, a C statement to be executed just prior to the output of
1486 assembler code for INSN, to modify the extracted operands so they will be
1489 Here the argument OPVEC is the vector containing the operands extracted
1490 from INSN, and NOPERANDS is the number of elements of the vector which
1491 contain meaningful data for this insn. The contents of this vector are
1492 what will be used to convert the insn template into assembler code, so you
1493 can change the assembler output by changing the contents of the vector.
1495 We use it to check if the current insn needs a nop in front of it because
1496 of load delays, and also to update the delay slot statistics. */
1499 final_prescan_insn (rtx insn
, rtx opvec
[] ATTRIBUTE_UNUSED
,
1500 int noperands ATTRIBUTE_UNUSED
)
1502 if (dslots_number_nops
> 0)
1504 rtx pattern
= PATTERN (insn
);
1505 int length
= get_attr_length (insn
);
1507 /* Do we need to emit a NOP? */
1509 || (iq2000_load_reg
!= 0 && reg_mentioned_p (iq2000_load_reg
, pattern
))
1510 || (iq2000_load_reg2
!= 0 && reg_mentioned_p (iq2000_load_reg2
, pattern
))
1511 || (iq2000_load_reg3
!= 0 && reg_mentioned_p (iq2000_load_reg3
, pattern
))
1512 || (iq2000_load_reg4
!= 0
1513 && reg_mentioned_p (iq2000_load_reg4
, pattern
)))
1514 fputs ("\tnop\n", asm_out_file
);
1517 dslots_load_filled
++;
1519 while (--dslots_number_nops
> 0)
1520 fputs ("\tnop\n", asm_out_file
);
1522 iq2000_load_reg
= 0;
1523 iq2000_load_reg2
= 0;
1524 iq2000_load_reg3
= 0;
1525 iq2000_load_reg4
= 0;
1528 if ( (GET_CODE (insn
) == JUMP_INSN
1529 || GET_CODE (insn
) == CALL_INSN
1530 || (GET_CODE (PATTERN (insn
)) == RETURN
))
1531 && NEXT_INSN (PREV_INSN (insn
)) == insn
)
1533 rtx nop_insn
= emit_insn_after (gen_nop (), insn
);
1535 INSN_ADDRESSES_NEW (nop_insn
, -1);
1539 && (GET_CODE (insn
) == JUMP_INSN
|| GET_CODE (insn
) == CALL_INSN
))
1540 dslots_jump_total
++;
1543 /* Return the bytes needed to compute the frame pointer from the current
1544 stack pointer where SIZE is the # of var. bytes allocated.
1546 IQ2000 stack frames look like:
1548 Before call After call
1549 +-----------------------+ +-----------------------+
1552 | caller's temps. | | caller's temps. |
1554 +-----------------------+ +-----------------------+
1556 | arguments on stack. | | arguments on stack. |
1558 +-----------------------+ +-----------------------+
1559 | 4 words to save | | 4 words to save |
1560 | arguments passed | | arguments passed |
1561 | in registers, even | | in registers, even |
1562 SP->| if not passed. | VFP->| if not passed. |
1563 +-----------------------+ +-----------------------+
1565 | fp register save |
1567 +-----------------------+
1569 | gp register save |
1571 +-----------------------+
1575 +-----------------------+
1577 | alloca allocations |
1579 +-----------------------+
1581 | GP save for V.4 abi |
1583 +-----------------------+
1585 | arguments on stack |
1587 +-----------------------+
1589 | arguments passed |
1590 | in registers, even |
1591 low SP->| if not passed. |
1592 memory +-----------------------+ */
1595 compute_frame_size (HOST_WIDE_INT size
)
1598 HOST_WIDE_INT total_size
; /* # bytes that the entire frame takes up. */
1599 HOST_WIDE_INT var_size
; /* # bytes that variables take up. */
1600 HOST_WIDE_INT args_size
; /* # bytes that outgoing arguments take up. */
1601 HOST_WIDE_INT extra_size
; /* # extra bytes. */
1602 HOST_WIDE_INT gp_reg_rounded
; /* # bytes needed to store gp after rounding. */
1603 HOST_WIDE_INT gp_reg_size
; /* # bytes needed to store gp regs. */
1604 HOST_WIDE_INT fp_reg_size
; /* # bytes needed to store fp regs. */
1605 long mask
; /* mask of saved gp registers. */
1606 int fp_inc
; /* 1 or 2 depending on the size of fp regs. */
1607 long fp_bits
; /* bitmask to use for each fp register. */
1612 extra_size
= IQ2000_STACK_ALIGN ((0));
1613 var_size
= IQ2000_STACK_ALIGN (size
);
1614 args_size
= IQ2000_STACK_ALIGN (current_function_outgoing_args_size
);
1616 /* If a function dynamically allocates the stack and
1617 has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space. */
1618 if (args_size
== 0 && current_function_calls_alloca
)
1619 args_size
= 4 * UNITS_PER_WORD
;
1621 total_size
= var_size
+ args_size
+ extra_size
;
1623 /* Calculate space needed for gp registers. */
1624 for (regno
= GP_REG_FIRST
; regno
<= GP_REG_LAST
; regno
++)
1626 if (MUST_SAVE_REGISTER (regno
))
1628 gp_reg_size
+= GET_MODE_SIZE (gpr_mode
);
1629 mask
|= 1L << (regno
- GP_REG_FIRST
);
1633 /* We need to restore these for the handler. */
1634 if (current_function_calls_eh_return
)
1640 regno
= EH_RETURN_DATA_REGNO (i
);
1641 if (regno
== (int) INVALID_REGNUM
)
1643 gp_reg_size
+= GET_MODE_SIZE (gpr_mode
);
1644 mask
|= 1L << (regno
- GP_REG_FIRST
);
1650 gp_reg_rounded
= IQ2000_STACK_ALIGN (gp_reg_size
);
1651 total_size
+= gp_reg_rounded
+ IQ2000_STACK_ALIGN (fp_reg_size
);
1653 /* The gp reg is caller saved, so there is no need for leaf routines
1654 (total_size == extra_size) to save the gp reg. */
1655 if (total_size
== extra_size
1657 total_size
= extra_size
= 0;
1659 total_size
+= IQ2000_STACK_ALIGN (current_function_pretend_args_size
);
1661 /* Save other computed information. */
1662 cfun
->machine
->total_size
= total_size
;
1663 cfun
->machine
->var_size
= var_size
;
1664 cfun
->machine
->args_size
= args_size
;
1665 cfun
->machine
->extra_size
= extra_size
;
1666 cfun
->machine
->gp_reg_size
= gp_reg_size
;
1667 cfun
->machine
->fp_reg_size
= fp_reg_size
;
1668 cfun
->machine
->mask
= mask
;
1669 cfun
->machine
->initialized
= reload_completed
;
1670 cfun
->machine
->num_gp
= gp_reg_size
/ UNITS_PER_WORD
;
1674 unsigned long offset
;
1676 offset
= (args_size
+ extra_size
+ var_size
1677 + gp_reg_size
- GET_MODE_SIZE (gpr_mode
));
1679 cfun
->machine
->gp_sp_offset
= offset
;
1680 cfun
->machine
->gp_save_offset
= offset
- total_size
;
1684 cfun
->machine
->gp_sp_offset
= 0;
1685 cfun
->machine
->gp_save_offset
= 0;
1688 cfun
->machine
->fp_sp_offset
= 0;
1689 cfun
->machine
->fp_save_offset
= 0;
1691 /* Ok, we're done. */
1695 /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
1696 pointer, argument pointer, or return address pointer. TO is either
1697 the stack pointer or hard frame pointer. */
1700 iq2000_initial_elimination_offset (int from
, int to ATTRIBUTE_UNUSED
)
1704 compute_frame_size (get_frame_size ());
1705 if ((from
) == FRAME_POINTER_REGNUM
)
1707 else if ((from
) == ARG_POINTER_REGNUM
)
1708 (offset
) = (cfun
->machine
->total_size
);
1709 else if ((from
) == RETURN_ADDRESS_POINTER_REGNUM
)
1711 if (leaf_function_p ())
1713 else (offset
) = cfun
->machine
->gp_sp_offset
1714 + ((UNITS_PER_WORD
- (POINTER_SIZE
/ BITS_PER_UNIT
))
1715 * (BYTES_BIG_ENDIAN
!= 0));
1721 /* Common code to emit the insns (or to write the instructions to a file)
1722 to save/restore registers.
1723 Other parts of the code assume that IQ2000_TEMP1_REGNUM (aka large_reg)
1724 is not modified within save_restore_insns. */
1726 #define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
1728 /* Emit instructions to load the value (SP + OFFSET) into IQ2000_TEMP2_REGNUM
1729 and return an rtl expression for the register. Write the assembly
1730 instructions directly to FILE if it is not null, otherwise emit them as
1733 This function is a subroutine of save_restore_insns. It is used when
1734 OFFSET is too large to add in a single instruction. */
1737 iq2000_add_large_offset_to_sp (HOST_WIDE_INT offset
)
1739 rtx reg
= gen_rtx_REG (Pmode
, IQ2000_TEMP2_REGNUM
);
1740 rtx offset_rtx
= GEN_INT (offset
);
1742 emit_move_insn (reg
, offset_rtx
);
1743 emit_insn (gen_addsi3 (reg
, reg
, stack_pointer_rtx
));
1747 /* Make INSN frame related and note that it performs the frame-related
1748 operation DWARF_PATTERN. */
1751 iq2000_annotate_frame_insn (rtx insn
, rtx dwarf_pattern
)
1753 RTX_FRAME_RELATED_P (insn
) = 1;
1754 REG_NOTES (insn
) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
1759 /* Emit a move instruction that stores REG in MEM. Make the instruction
1760 frame related and note that it stores REG at (SP + OFFSET). */
1763 iq2000_emit_frame_related_store (rtx mem
, rtx reg
, HOST_WIDE_INT offset
)
1765 rtx dwarf_address
= plus_constant (stack_pointer_rtx
, offset
);
1766 rtx dwarf_mem
= gen_rtx_MEM (GET_MODE (reg
), dwarf_address
);
1768 iq2000_annotate_frame_insn (emit_move_insn (mem
, reg
),
1769 gen_rtx_SET (GET_MODE (reg
), dwarf_mem
, reg
));
1772 /* Emit instructions to save/restore registers, as determined by STORE_P. */
1775 save_restore_insns (int store_p
)
1777 long mask
= cfun
->machine
->mask
;
1780 HOST_WIDE_INT base_offset
;
1781 HOST_WIDE_INT gp_offset
;
1782 HOST_WIDE_INT end_offset
;
1784 gcc_assert (!frame_pointer_needed
1785 || BITSET_P (mask
, HARD_FRAME_POINTER_REGNUM
- GP_REG_FIRST
));
1789 base_reg_rtx
= 0, base_offset
= 0;
1793 /* Save registers starting from high to low. The debuggers prefer at least
1794 the return register be stored at func+4, and also it allows us not to
1795 need a nop in the epilog if at least one register is reloaded in
1796 addition to return address. */
1798 /* Save GP registers if needed. */
1799 /* Pick which pointer to use as a base register. For small frames, just
1800 use the stack pointer. Otherwise, use a temporary register. Save 2
1801 cycles if the save area is near the end of a large frame, by reusing
1802 the constant created in the prologue/epilogue to adjust the stack
1805 gp_offset
= cfun
->machine
->gp_sp_offset
;
1807 = gp_offset
- (cfun
->machine
->gp_reg_size
1808 - GET_MODE_SIZE (gpr_mode
));
1810 if (gp_offset
< 0 || end_offset
< 0)
1812 ("gp_offset (%ld) or end_offset (%ld) is less than zero",
1813 (long) gp_offset
, (long) end_offset
);
1815 else if (gp_offset
< 32768)
1816 base_reg_rtx
= stack_pointer_rtx
, base_offset
= 0;
1820 int reg_save_count
= 0;
1822 for (regno
= GP_REG_LAST
; regno
>= GP_REG_FIRST
; regno
--)
1823 if (BITSET_P (mask
, regno
- GP_REG_FIRST
)) reg_save_count
+= 1;
1824 base_offset
= gp_offset
- ((reg_save_count
- 1) * 4);
1825 base_reg_rtx
= iq2000_add_large_offset_to_sp (base_offset
);
1828 for (regno
= GP_REG_LAST
; regno
>= GP_REG_FIRST
; regno
--)
1830 if (BITSET_P (mask
, regno
- GP_REG_FIRST
))
1834 = gen_rtx_MEM (gpr_mode
,
1835 gen_rtx_PLUS (Pmode
, base_reg_rtx
,
1836 GEN_INT (gp_offset
- base_offset
)));
1838 reg_rtx
= gen_rtx_REG (gpr_mode
, regno
);
1841 iq2000_emit_frame_related_store (mem_rtx
, reg_rtx
, gp_offset
);
1844 emit_move_insn (reg_rtx
, mem_rtx
);
1846 gp_offset
-= GET_MODE_SIZE (gpr_mode
);
1851 /* Expand the prologue into a bunch of separate insns. */
1854 iq2000_expand_prologue (void)
1857 HOST_WIDE_INT tsize
;
1858 int last_arg_is_vararg_marker
= 0;
1859 tree fndecl
= current_function_decl
;
1860 tree fntype
= TREE_TYPE (fndecl
);
1861 tree fnargs
= DECL_ARGUMENTS (fndecl
);
1866 CUMULATIVE_ARGS args_so_far
;
1867 int store_args_on_stack
= (iq2000_can_use_return_insn ());
1869 /* If struct value address is treated as the first argument. */
1870 if (aggregate_value_p (DECL_RESULT (fndecl
), fndecl
)
1871 && ! current_function_returns_pcc_struct
1872 && targetm
.calls
.struct_value_rtx (TREE_TYPE (fndecl
), 1) == 0)
1874 tree type
= build_pointer_type (fntype
);
1875 tree function_result_decl
= build_decl (PARM_DECL
, NULL_TREE
, type
);
1877 DECL_ARG_TYPE (function_result_decl
) = type
;
1878 TREE_CHAIN (function_result_decl
) = fnargs
;
1879 fnargs
= function_result_decl
;
1882 /* For arguments passed in registers, find the register number
1883 of the first argument in the variable part of the argument list,
1884 otherwise GP_ARG_LAST+1. Note also if the last argument is
1885 the varargs special argument, and treat it as part of the
1888 This is only needed if store_args_on_stack is true. */
1889 INIT_CUMULATIVE_ARGS (args_so_far
, fntype
, NULL_RTX
, 0, 0);
1890 regno
= GP_ARG_FIRST
;
1892 for (cur_arg
= fnargs
; cur_arg
!= 0; cur_arg
= next_arg
)
1894 tree passed_type
= DECL_ARG_TYPE (cur_arg
);
1895 enum machine_mode passed_mode
= TYPE_MODE (passed_type
);
1898 if (TREE_ADDRESSABLE (passed_type
))
1900 passed_type
= build_pointer_type (passed_type
);
1901 passed_mode
= Pmode
;
1904 entry_parm
= FUNCTION_ARG (args_so_far
, passed_mode
, passed_type
, 1);
1906 FUNCTION_ARG_ADVANCE (args_so_far
, passed_mode
, passed_type
, 1);
1907 next_arg
= TREE_CHAIN (cur_arg
);
1909 if (entry_parm
&& store_args_on_stack
)
1912 && DECL_NAME (cur_arg
)
1913 && ((0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg
)),
1914 "__builtin_va_alist"))
1915 || (0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg
)),
1918 last_arg_is_vararg_marker
= 1;
1925 gcc_assert (GET_CODE (entry_parm
) == REG
);
1927 /* Passed in a register, so will get homed automatically. */
1928 if (GET_MODE (entry_parm
) == BLKmode
)
1929 words
= (int_size_in_bytes (passed_type
) + 3) / 4;
1931 words
= (GET_MODE_SIZE (GET_MODE (entry_parm
)) + 3) / 4;
1933 regno
= REGNO (entry_parm
) + words
- 1;
1938 regno
= GP_ARG_LAST
+1;
1943 /* In order to pass small structures by value in registers we need to
1944 shift the value into the high part of the register.
1945 Function_arg has encoded a PARALLEL rtx, holding a vector of
1946 adjustments to be made as the next_arg_reg variable, so we split up the
1947 insns, and emit them separately. */
1948 next_arg_reg
= FUNCTION_ARG (args_so_far
, VOIDmode
, void_type_node
, 1);
1949 if (next_arg_reg
!= 0 && GET_CODE (next_arg_reg
) == PARALLEL
)
1951 rtvec adjust
= XVEC (next_arg_reg
, 0);
1952 int num
= GET_NUM_ELEM (adjust
);
1954 for (i
= 0; i
< num
; i
++)
1958 pattern
= RTVEC_ELT (adjust
, i
);
1959 if (GET_CODE (pattern
) != SET
1960 || GET_CODE (SET_SRC (pattern
)) != ASHIFT
)
1961 abort_with_insn (pattern
, "Insn is not a shift");
1962 PUT_CODE (SET_SRC (pattern
), ASHIFTRT
);
1964 insn
= emit_insn (pattern
);
1968 tsize
= compute_frame_size (get_frame_size ());
1970 /* If this function is a varargs function, store any registers that
1971 would normally hold arguments ($4 - $7) on the stack. */
1972 if (store_args_on_stack
1973 && ((TYPE_ARG_TYPES (fntype
) != 0
1974 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1976 || last_arg_is_vararg_marker
))
1978 int offset
= (regno
- GP_ARG_FIRST
) * UNITS_PER_WORD
;
1979 rtx ptr
= stack_pointer_rtx
;
1981 for (; regno
<= GP_ARG_LAST
; regno
++)
1984 ptr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, GEN_INT (offset
));
1985 emit_move_insn (gen_rtx_MEM (gpr_mode
, ptr
),
1986 gen_rtx_REG (gpr_mode
, regno
));
1988 offset
+= GET_MODE_SIZE (gpr_mode
);
1994 rtx tsize_rtx
= GEN_INT (tsize
);
1995 rtx adjustment_rtx
, insn
, dwarf_pattern
;
1999 adjustment_rtx
= gen_rtx_REG (Pmode
, IQ2000_TEMP1_REGNUM
);
2000 emit_move_insn (adjustment_rtx
, tsize_rtx
);
2003 adjustment_rtx
= tsize_rtx
;
2005 insn
= emit_insn (gen_subsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
2008 dwarf_pattern
= gen_rtx_SET (Pmode
, stack_pointer_rtx
,
2009 plus_constant (stack_pointer_rtx
, -tsize
));
2011 iq2000_annotate_frame_insn (insn
, dwarf_pattern
);
2013 save_restore_insns (1);
2015 if (frame_pointer_needed
)
2019 insn
= emit_insn (gen_movsi (hard_frame_pointer_rtx
,
2020 stack_pointer_rtx
));
2023 RTX_FRAME_RELATED_P (insn
) = 1;
2027 emit_insn (gen_blockage ());
2030 /* Expand the epilogue into a bunch of separate insns. */
2033 iq2000_expand_epilogue (void)
2035 HOST_WIDE_INT tsize
= cfun
->machine
->total_size
;
2036 rtx tsize_rtx
= GEN_INT (tsize
);
2037 rtx tmp_rtx
= (rtx
)0;
2039 if (iq2000_can_use_return_insn ())
2041 emit_jump_insn (gen_return ());
2047 tmp_rtx
= gen_rtx_REG (Pmode
, IQ2000_TEMP1_REGNUM
);
2048 emit_move_insn (tmp_rtx
, tsize_rtx
);
2049 tsize_rtx
= tmp_rtx
;
2054 if (frame_pointer_needed
)
2056 emit_insn (gen_blockage ());
2058 emit_insn (gen_movsi (stack_pointer_rtx
, hard_frame_pointer_rtx
));
2061 save_restore_insns (0);
2063 if (current_function_calls_eh_return
)
2065 rtx eh_ofs
= EH_RETURN_STACKADJ_RTX
;
2066 emit_insn (gen_addsi3 (eh_ofs
, eh_ofs
, tsize_rtx
));
2070 emit_insn (gen_blockage ());
2072 if (tsize
!= 0 || current_function_calls_eh_return
)
2074 emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
2079 if (current_function_calls_eh_return
)
2081 /* Perform the additional bump for __throw. */
2082 emit_move_insn (gen_rtx_REG (Pmode
, HARD_FRAME_POINTER_REGNUM
),
2084 emit_insn (gen_rtx_USE (VOIDmode
, gen_rtx_REG (Pmode
,
2085 HARD_FRAME_POINTER_REGNUM
)));
2086 emit_jump_insn (gen_eh_return_internal ());
2089 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode
,
2090 GP_REG_FIRST
+ 31)));
2094 iq2000_expand_eh_return (rtx address
)
2096 HOST_WIDE_INT gp_offset
= cfun
->machine
->gp_sp_offset
;
2099 scratch
= plus_constant (stack_pointer_rtx
, gp_offset
);
2100 emit_move_insn (gen_rtx_MEM (GET_MODE (address
), scratch
), address
);
2103 /* Return nonzero if this function is known to have a null epilogue.
2104 This allows the optimizer to omit jumps to jumps if no stack
2108 iq2000_can_use_return_insn (void)
2110 if (! reload_completed
)
2113 if (df_regs_ever_live_p (31) || profile_flag
)
2116 if (cfun
->machine
->initialized
)
2117 return cfun
->machine
->total_size
== 0;
2119 return compute_frame_size (get_frame_size ()) == 0;
2122 /* Returns nonzero if X contains a SYMBOL_REF. */
2125 symbolic_expression_p (rtx x
)
2127 if (GET_CODE (x
) == SYMBOL_REF
)
2130 if (GET_CODE (x
) == CONST
)
2131 return symbolic_expression_p (XEXP (x
, 0));
2134 return symbolic_expression_p (XEXP (x
, 0));
2136 if (ARITHMETIC_P (x
))
2137 return (symbolic_expression_p (XEXP (x
, 0))
2138 || symbolic_expression_p (XEXP (x
, 1)));
2143 /* Choose the section to use for the constant rtx expression X that has
2147 iq2000_select_rtx_section (enum machine_mode mode
, rtx x ATTRIBUTE_UNUSED
,
2148 unsigned HOST_WIDE_INT align
)
2150 /* For embedded applications, always put constants in read-only data,
2151 in order to reduce RAM usage. */
2152 return mergeable_constant_section (mode
, align
, 0);
2155 /* Choose the section to use for DECL. RELOC is true if its value contains
2156 any relocatable expression.
2158 Some of the logic used here needs to be replicated in
2159 ENCODE_SECTION_INFO in iq2000.h so that references to these symbols
2160 are done correctly. */
2163 iq2000_select_section (tree decl
, int reloc ATTRIBUTE_UNUSED
,
2164 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
)
2166 if (TARGET_EMBEDDED_DATA
)
2168 /* For embedded applications, always put an object in read-only data
2169 if possible, in order to reduce RAM usage. */
2170 if ((TREE_CODE (decl
) == VAR_DECL
2171 && TREE_READONLY (decl
) && !TREE_SIDE_EFFECTS (decl
)
2172 && DECL_INITIAL (decl
)
2173 && (DECL_INITIAL (decl
) == error_mark_node
2174 || TREE_CONSTANT (DECL_INITIAL (decl
))))
2175 /* Deal with calls from output_constant_def_contents. */
2176 || TREE_CODE (decl
) != VAR_DECL
)
2177 return readonly_data_section
;
2179 return data_section
;
2183 /* For hosted applications, always put an object in small data if
2184 possible, as this gives the best performance. */
2185 if ((TREE_CODE (decl
) == VAR_DECL
2186 && TREE_READONLY (decl
) && !TREE_SIDE_EFFECTS (decl
)
2187 && DECL_INITIAL (decl
)
2188 && (DECL_INITIAL (decl
) == error_mark_node
2189 || TREE_CONSTANT (DECL_INITIAL (decl
))))
2190 /* Deal with calls from output_constant_def_contents. */
2191 || TREE_CODE (decl
) != VAR_DECL
)
2192 return readonly_data_section
;
2194 return data_section
;
2197 /* Return register to use for a function return value with VALTYPE for function
2201 iq2000_function_value (const_tree valtype
, const_tree func ATTRIBUTE_UNUSED
)
2203 int reg
= GP_RETURN
;
2204 enum machine_mode mode
= TYPE_MODE (valtype
);
2205 int unsignedp
= TYPE_UNSIGNED (valtype
);
2207 /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns true,
2208 we must promote the mode just as PROMOTE_MODE does. */
2209 mode
= promote_mode (valtype
, mode
, &unsignedp
, 1);
2211 return gen_rtx_REG (mode
, reg
);
2214 /* Return true when an argument must be passed by reference. */
2217 iq2000_pass_by_reference (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
,
2218 const_tree type
, bool named ATTRIBUTE_UNUSED
)
2222 /* We must pass by reference if we would be both passing in registers
2223 and the stack. This is because any subsequent partial arg would be
2224 handled incorrectly in this case. */
2225 if (cum
&& targetm
.calls
.must_pass_in_stack (mode
, type
))
2227 /* Don't pass the actual CUM to FUNCTION_ARG, because we would
2228 get double copies of any offsets generated for small structs
2229 passed in registers. */
2230 CUMULATIVE_ARGS temp
;
2233 if (FUNCTION_ARG (temp
, mode
, type
, named
) != 0)
2237 if (type
== NULL_TREE
|| mode
== DImode
|| mode
== DFmode
)
2240 size
= int_size_in_bytes (type
);
2241 return size
== -1 || size
> UNITS_PER_WORD
;
2244 /* Return the length of INSN. LENGTH is the initial length computed by
2245 attributes in the machine-description file. */
2248 iq2000_adjust_insn_length (rtx insn
, int length
)
2250 /* A unconditional jump has an unfilled delay slot if it is not part
2251 of a sequence. A conditional jump normally has a delay slot. */
2252 if (simplejump_p (insn
)
2253 || ( (GET_CODE (insn
) == JUMP_INSN
2254 || GET_CODE (insn
) == CALL_INSN
)))
2260 /* Output assembly instructions to perform a conditional branch.
2262 INSN is the branch instruction. OPERANDS[0] is the condition.
2263 OPERANDS[1] is the target of the branch. OPERANDS[2] is the target
2264 of the first operand to the condition. If TWO_OPERANDS_P is
2265 nonzero the comparison takes two operands; OPERANDS[3] will be the
2268 If INVERTED_P is nonzero we are to branch if the condition does
2269 not hold. If FLOAT_P is nonzero this is a floating-point comparison.
2271 LENGTH is the length (in bytes) of the sequence we are to generate.
2272 That tells us whether to generate a simple conditional branch, or a
2273 reversed conditional branch around a `jr' instruction. */
2276 iq2000_output_conditional_branch (rtx insn
, rtx
* operands
, int two_operands_p
,
2277 int float_p
, int inverted_p
, int length
)
2279 static char buffer
[200];
2280 /* The kind of comparison we are doing. */
2281 enum rtx_code code
= GET_CODE (operands
[0]);
2282 /* Nonzero if the opcode for the comparison needs a `z' indicating
2283 that it is a comparison against zero. */
2285 /* A string to use in the assembly output to represent the first
2287 const char *op1
= "%z2";
2288 /* A string to use in the assembly output to represent the second
2289 operand. Use the hard-wired zero register if there's no second
2291 const char *op2
= (two_operands_p
? ",%z3" : ",%.");
2292 /* The operand-printing string for the comparison. */
2293 const char *comp
= (float_p
? "%F0" : "%C0");
2294 /* The operand-printing string for the inverted comparison. */
2295 const char *inverted_comp
= (float_p
? "%W0" : "%N0");
2297 /* Likely variants of each branch instruction annul the instruction
2298 in the delay slot if the branch is not taken. */
2299 iq2000_branch_likely
= (final_sequence
&& INSN_ANNULLED_BRANCH_P (insn
));
2301 if (!two_operands_p
)
2303 /* To compute whether than A > B, for example, we normally
2304 subtract B from A and then look at the sign bit. But, if we
2305 are doing an unsigned comparison, and B is zero, we don't
2306 have to do the subtraction. Instead, we can just check to
2307 see if A is nonzero. Thus, we change the CODE here to
2308 reflect the simpler comparison operation. */
2320 /* A condition which will always be true. */
2326 /* A condition which will always be false. */
2332 /* Not a special case. */
2337 /* Relative comparisons are always done against zero. But
2338 equality comparisons are done between two operands, and therefore
2339 do not require a `z' in the assembly language output. */
2340 need_z_p
= (!float_p
&& code
!= EQ
&& code
!= NE
);
2341 /* For comparisons against zero, the zero is not provided
2346 /* Begin by terminating the buffer. That way we can always use
2347 strcat to add to it. */
2354 /* Just a simple conditional branch. */
2356 sprintf (buffer
, "b%s%%?\t%%Z2%%1",
2357 inverted_p
? inverted_comp
: comp
);
2359 sprintf (buffer
, "b%s%s%%?\t%s%s,%%1",
2360 inverted_p
? inverted_comp
: comp
,
2361 need_z_p
? "z" : "",
2369 /* Generate a reversed conditional branch around ` j'
2381 Because we have to jump four bytes *past* the following
2382 instruction if this branch was annulled, we can't just use
2383 a label, as in the picture above; there's no way to put the
2384 label after the next instruction, as the assembler does not
2385 accept `.L+4' as the target of a branch. (We can't just
2386 wait until the next instruction is output; it might be a
2387 macro and take up more than four bytes. Once again, we see
2388 why we want to eliminate macros.)
2390 If the branch is annulled, we jump four more bytes that we
2391 would otherwise; that way we skip the annulled instruction
2392 in the delay slot. */
2395 = ((iq2000_branch_likely
|| length
== 16) ? ".+16" : ".+12");
2398 c
= strchr (buffer
, '\0');
2399 /* Generate the reversed comparison. This takes four
2402 sprintf (c
, "b%s\t%%Z2%s",
2403 inverted_p
? comp
: inverted_comp
,
2406 sprintf (c
, "b%s%s\t%s%s,%s",
2407 inverted_p
? comp
: inverted_comp
,
2408 need_z_p
? "z" : "",
2412 strcat (c
, "\n\tnop\n\tj\t%1");
2414 /* The delay slot was unfilled. Since we're inside
2415 .noreorder, the assembler will not fill in the NOP for
2416 us, so we must do it ourselves. */
2417 strcat (buffer
, "\n\tnop");
2429 #define def_builtin(NAME, TYPE, CODE) \
2430 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
2434 iq2000_init_builtins (void)
2436 tree endlink
= void_list_node
;
2437 tree void_ftype
, void_ftype_int
, void_ftype_int_int
;
2438 tree void_ftype_int_int_int
;
2439 tree int_ftype_int
, int_ftype_int_int
, int_ftype_int_int_int
;
2440 tree int_ftype_int_int_int_int
;
2444 = build_function_type (void_type_node
,
2445 tree_cons (NULL_TREE
, void_type_node
, endlink
));
2449 = build_function_type (void_type_node
,
2450 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
2452 /* void func (int, int) */
2454 = build_function_type (void_type_node
,
2455 tree_cons (NULL_TREE
, integer_type_node
,
2456 tree_cons (NULL_TREE
, integer_type_node
,
2459 /* int func (int) */
2461 = build_function_type (integer_type_node
,
2462 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
2464 /* int func (int, int) */
2466 = build_function_type (integer_type_node
,
2467 tree_cons (NULL_TREE
, integer_type_node
,
2468 tree_cons (NULL_TREE
, integer_type_node
,
2471 /* void func (int, int, int) */
2472 void_ftype_int_int_int
2473 = build_function_type
2475 tree_cons (NULL_TREE
, integer_type_node
,
2476 tree_cons (NULL_TREE
, integer_type_node
,
2477 tree_cons (NULL_TREE
,
2481 /* int func (int, int, int, int) */
2482 int_ftype_int_int_int_int
2483 = build_function_type
2485 tree_cons (NULL_TREE
, integer_type_node
,
2486 tree_cons (NULL_TREE
, integer_type_node
,
2487 tree_cons (NULL_TREE
,
2489 tree_cons (NULL_TREE
,
2493 /* int func (int, int, int) */
2494 int_ftype_int_int_int
2495 = build_function_type
2497 tree_cons (NULL_TREE
, integer_type_node
,
2498 tree_cons (NULL_TREE
, integer_type_node
,
2499 tree_cons (NULL_TREE
,
2503 /* int func (int, int, int, int) */
2504 int_ftype_int_int_int_int
2505 = build_function_type
2507 tree_cons (NULL_TREE
, integer_type_node
,
2508 tree_cons (NULL_TREE
, integer_type_node
,
2509 tree_cons (NULL_TREE
,
2511 tree_cons (NULL_TREE
,
2515 def_builtin ("__builtin_ado16", int_ftype_int_int
, IQ2000_BUILTIN_ADO16
);
2516 def_builtin ("__builtin_ram", int_ftype_int_int_int_int
, IQ2000_BUILTIN_RAM
);
2517 def_builtin ("__builtin_chkhdr", void_ftype_int_int
, IQ2000_BUILTIN_CHKHDR
);
2518 def_builtin ("__builtin_pkrl", void_ftype_int_int
, IQ2000_BUILTIN_PKRL
);
2519 def_builtin ("__builtin_cfc0", int_ftype_int
, IQ2000_BUILTIN_CFC0
);
2520 def_builtin ("__builtin_cfc1", int_ftype_int
, IQ2000_BUILTIN_CFC1
);
2521 def_builtin ("__builtin_cfc2", int_ftype_int
, IQ2000_BUILTIN_CFC2
);
2522 def_builtin ("__builtin_cfc3", int_ftype_int
, IQ2000_BUILTIN_CFC3
);
2523 def_builtin ("__builtin_ctc0", void_ftype_int_int
, IQ2000_BUILTIN_CTC0
);
2524 def_builtin ("__builtin_ctc1", void_ftype_int_int
, IQ2000_BUILTIN_CTC1
);
2525 def_builtin ("__builtin_ctc2", void_ftype_int_int
, IQ2000_BUILTIN_CTC2
);
2526 def_builtin ("__builtin_ctc3", void_ftype_int_int
, IQ2000_BUILTIN_CTC3
);
2527 def_builtin ("__builtin_mfc0", int_ftype_int
, IQ2000_BUILTIN_MFC0
);
2528 def_builtin ("__builtin_mfc1", int_ftype_int
, IQ2000_BUILTIN_MFC1
);
2529 def_builtin ("__builtin_mfc2", int_ftype_int
, IQ2000_BUILTIN_MFC2
);
2530 def_builtin ("__builtin_mfc3", int_ftype_int
, IQ2000_BUILTIN_MFC3
);
2531 def_builtin ("__builtin_mtc0", void_ftype_int_int
, IQ2000_BUILTIN_MTC0
);
2532 def_builtin ("__builtin_mtc1", void_ftype_int_int
, IQ2000_BUILTIN_MTC1
);
2533 def_builtin ("__builtin_mtc2", void_ftype_int_int
, IQ2000_BUILTIN_MTC2
);
2534 def_builtin ("__builtin_mtc3", void_ftype_int_int
, IQ2000_BUILTIN_MTC3
);
2535 def_builtin ("__builtin_lur", void_ftype_int_int
, IQ2000_BUILTIN_LUR
);
2536 def_builtin ("__builtin_rb", void_ftype_int_int
, IQ2000_BUILTIN_RB
);
2537 def_builtin ("__builtin_rx", void_ftype_int_int
, IQ2000_BUILTIN_RX
);
2538 def_builtin ("__builtin_srrd", void_ftype_int
, IQ2000_BUILTIN_SRRD
);
2539 def_builtin ("__builtin_srwr", void_ftype_int_int
, IQ2000_BUILTIN_SRWR
);
2540 def_builtin ("__builtin_wb", void_ftype_int_int
, IQ2000_BUILTIN_WB
);
2541 def_builtin ("__builtin_wx", void_ftype_int_int
, IQ2000_BUILTIN_WX
);
2542 def_builtin ("__builtin_luc32l", void_ftype_int_int
, IQ2000_BUILTIN_LUC32L
);
2543 def_builtin ("__builtin_luc64", void_ftype_int_int
, IQ2000_BUILTIN_LUC64
);
2544 def_builtin ("__builtin_luc64l", void_ftype_int_int
, IQ2000_BUILTIN_LUC64L
);
2545 def_builtin ("__builtin_luk", void_ftype_int_int
, IQ2000_BUILTIN_LUK
);
2546 def_builtin ("__builtin_lulck", void_ftype_int
, IQ2000_BUILTIN_LULCK
);
2547 def_builtin ("__builtin_lum32", void_ftype_int_int
, IQ2000_BUILTIN_LUM32
);
2548 def_builtin ("__builtin_lum32l", void_ftype_int_int
, IQ2000_BUILTIN_LUM32L
);
2549 def_builtin ("__builtin_lum64", void_ftype_int_int
, IQ2000_BUILTIN_LUM64
);
2550 def_builtin ("__builtin_lum64l", void_ftype_int_int
, IQ2000_BUILTIN_LUM64L
);
2551 def_builtin ("__builtin_lurl", void_ftype_int_int
, IQ2000_BUILTIN_LURL
);
2552 def_builtin ("__builtin_mrgb", int_ftype_int_int_int
, IQ2000_BUILTIN_MRGB
);
2553 def_builtin ("__builtin_srrdl", void_ftype_int
, IQ2000_BUILTIN_SRRDL
);
2554 def_builtin ("__builtin_srulck", void_ftype_int
, IQ2000_BUILTIN_SRULCK
);
2555 def_builtin ("__builtin_srwru", void_ftype_int_int
, IQ2000_BUILTIN_SRWRU
);
2556 def_builtin ("__builtin_trapqfl", void_ftype
, IQ2000_BUILTIN_TRAPQFL
);
2557 def_builtin ("__builtin_trapqne", void_ftype
, IQ2000_BUILTIN_TRAPQNE
);
2558 def_builtin ("__builtin_traprel", void_ftype_int
, IQ2000_BUILTIN_TRAPREL
);
2559 def_builtin ("__builtin_wbu", void_ftype_int_int_int
, IQ2000_BUILTIN_WBU
);
2560 def_builtin ("__builtin_syscall", void_ftype
, IQ2000_BUILTIN_SYSCALL
);
2563 /* Builtin for ICODE having ARGCOUNT args in EXP where each arg
2567 expand_one_builtin (enum insn_code icode
, rtx target
, tree exp
,
2568 enum rtx_code
*code
, int argcount
)
2573 enum machine_mode mode
[5];
2576 mode
[0] = insn_data
[icode
].operand
[0].mode
;
2577 for (i
= 0; i
< argcount
; i
++)
2579 arg
[i
] = CALL_EXPR_ARG (exp
, i
);
2580 op
[i
] = expand_expr (arg
[i
], NULL_RTX
, VOIDmode
, 0);
2581 mode
[i
] = insn_data
[icode
].operand
[i
].mode
;
2582 if (code
[i
] == CONST_INT
&& GET_CODE (op
[i
]) != CONST_INT
)
2583 error ("argument %qd is not a constant", i
+ 1);
2585 && ! (*insn_data
[icode
].operand
[i
].predicate
) (op
[i
], mode
[i
]))
2586 op
[i
] = copy_to_mode_reg (mode
[i
], op
[i
]);
2589 if (insn_data
[icode
].operand
[0].constraint
[0] == '=')
2592 || GET_MODE (target
) != mode
[0]
2593 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, mode
[0]))
2594 target
= gen_reg_rtx (mode
[0]);
2602 pat
= GEN_FCN (icode
) (target
);
2605 pat
= GEN_FCN (icode
) (target
, op
[0]);
2607 pat
= GEN_FCN (icode
) (op
[0]);
2611 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1]);
2613 pat
= GEN_FCN (icode
) (op
[0], op
[1]);
2617 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2]);
2619 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2]);
2623 pat
= GEN_FCN (icode
) (target
, op
[0], op
[1], op
[2], op
[3]);
2625 pat
= GEN_FCN (icode
) (op
[0], op
[1], op
[2], op
[3]);
2637 /* Expand an expression EXP that calls a built-in function,
2638 with result going to TARGET if that's convenient
2639 (and in mode MODE if that's convenient).
2640 SUBTARGET may be used as the target for computing one of EXP's operands.
2641 IGNORE is nonzero if the value is to be ignored. */
2644 iq2000_expand_builtin (tree exp
, rtx target
, rtx subtarget ATTRIBUTE_UNUSED
,
2645 enum machine_mode mode ATTRIBUTE_UNUSED
,
2646 int ignore ATTRIBUTE_UNUSED
)
2648 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2649 int fcode
= DECL_FUNCTION_CODE (fndecl
);
2650 enum rtx_code code
[5];
2662 case IQ2000_BUILTIN_ADO16
:
2663 return expand_one_builtin (CODE_FOR_ado16
, target
, exp
, code
, 2);
2665 case IQ2000_BUILTIN_RAM
:
2666 code
[1] = CONST_INT
;
2667 code
[2] = CONST_INT
;
2668 code
[3] = CONST_INT
;
2669 return expand_one_builtin (CODE_FOR_ram
, target
, exp
, code
, 4);
2671 case IQ2000_BUILTIN_CHKHDR
:
2672 return expand_one_builtin (CODE_FOR_chkhdr
, target
, exp
, code
, 2);
2674 case IQ2000_BUILTIN_PKRL
:
2675 return expand_one_builtin (CODE_FOR_pkrl
, target
, exp
, code
, 2);
2677 case IQ2000_BUILTIN_CFC0
:
2678 code
[0] = CONST_INT
;
2679 return expand_one_builtin (CODE_FOR_cfc0
, target
, exp
, code
, 1);
2681 case IQ2000_BUILTIN_CFC1
:
2682 code
[0] = CONST_INT
;
2683 return expand_one_builtin (CODE_FOR_cfc1
, target
, exp
, code
, 1);
2685 case IQ2000_BUILTIN_CFC2
:
2686 code
[0] = CONST_INT
;
2687 return expand_one_builtin (CODE_FOR_cfc2
, target
, exp
, code
, 1);
2689 case IQ2000_BUILTIN_CFC3
:
2690 code
[0] = CONST_INT
;
2691 return expand_one_builtin (CODE_FOR_cfc3
, target
, exp
, code
, 1);
2693 case IQ2000_BUILTIN_CTC0
:
2694 code
[1] = CONST_INT
;
2695 return expand_one_builtin (CODE_FOR_ctc0
, target
, exp
, code
, 2);
2697 case IQ2000_BUILTIN_CTC1
:
2698 code
[1] = CONST_INT
;
2699 return expand_one_builtin (CODE_FOR_ctc1
, target
, exp
, code
, 2);
2701 case IQ2000_BUILTIN_CTC2
:
2702 code
[1] = CONST_INT
;
2703 return expand_one_builtin (CODE_FOR_ctc2
, target
, exp
, code
, 2);
2705 case IQ2000_BUILTIN_CTC3
:
2706 code
[1] = CONST_INT
;
2707 return expand_one_builtin (CODE_FOR_ctc3
, target
, exp
, code
, 2);
2709 case IQ2000_BUILTIN_MFC0
:
2710 code
[0] = CONST_INT
;
2711 return expand_one_builtin (CODE_FOR_mfc0
, target
, exp
, code
, 1);
2713 case IQ2000_BUILTIN_MFC1
:
2714 code
[0] = CONST_INT
;
2715 return expand_one_builtin (CODE_FOR_mfc1
, target
, exp
, code
, 1);
2717 case IQ2000_BUILTIN_MFC2
:
2718 code
[0] = CONST_INT
;
2719 return expand_one_builtin (CODE_FOR_mfc2
, target
, exp
, code
, 1);
2721 case IQ2000_BUILTIN_MFC3
:
2722 code
[0] = CONST_INT
;
2723 return expand_one_builtin (CODE_FOR_mfc3
, target
, exp
, code
, 1);
2725 case IQ2000_BUILTIN_MTC0
:
2726 code
[1] = CONST_INT
;
2727 return expand_one_builtin (CODE_FOR_mtc0
, target
, exp
, code
, 2);
2729 case IQ2000_BUILTIN_MTC1
:
2730 code
[1] = CONST_INT
;
2731 return expand_one_builtin (CODE_FOR_mtc1
, target
, exp
, code
, 2);
2733 case IQ2000_BUILTIN_MTC2
:
2734 code
[1] = CONST_INT
;
2735 return expand_one_builtin (CODE_FOR_mtc2
, target
, exp
, code
, 2);
2737 case IQ2000_BUILTIN_MTC3
:
2738 code
[1] = CONST_INT
;
2739 return expand_one_builtin (CODE_FOR_mtc3
, target
, exp
, code
, 2);
2741 case IQ2000_BUILTIN_LUR
:
2742 return expand_one_builtin (CODE_FOR_lur
, target
, exp
, code
, 2);
2744 case IQ2000_BUILTIN_RB
:
2745 return expand_one_builtin (CODE_FOR_rb
, target
, exp
, code
, 2);
2747 case IQ2000_BUILTIN_RX
:
2748 return expand_one_builtin (CODE_FOR_rx
, target
, exp
, code
, 2);
2750 case IQ2000_BUILTIN_SRRD
:
2751 return expand_one_builtin (CODE_FOR_srrd
, target
, exp
, code
, 1);
2753 case IQ2000_BUILTIN_SRWR
:
2754 return expand_one_builtin (CODE_FOR_srwr
, target
, exp
, code
, 2);
2756 case IQ2000_BUILTIN_WB
:
2757 return expand_one_builtin (CODE_FOR_wb
, target
, exp
, code
, 2);
2759 case IQ2000_BUILTIN_WX
:
2760 return expand_one_builtin (CODE_FOR_wx
, target
, exp
, code
, 2);
2762 case IQ2000_BUILTIN_LUC32L
:
2763 return expand_one_builtin (CODE_FOR_luc32l
, target
, exp
, code
, 2);
2765 case IQ2000_BUILTIN_LUC64
:
2766 return expand_one_builtin (CODE_FOR_luc64
, target
, exp
, code
, 2);
2768 case IQ2000_BUILTIN_LUC64L
:
2769 return expand_one_builtin (CODE_FOR_luc64l
, target
, exp
, code
, 2);
2771 case IQ2000_BUILTIN_LUK
:
2772 return expand_one_builtin (CODE_FOR_luk
, target
, exp
, code
, 2);
2774 case IQ2000_BUILTIN_LULCK
:
2775 return expand_one_builtin (CODE_FOR_lulck
, target
, exp
, code
, 1);
2777 case IQ2000_BUILTIN_LUM32
:
2778 return expand_one_builtin (CODE_FOR_lum32
, target
, exp
, code
, 2);
2780 case IQ2000_BUILTIN_LUM32L
:
2781 return expand_one_builtin (CODE_FOR_lum32l
, target
, exp
, code
, 2);
2783 case IQ2000_BUILTIN_LUM64
:
2784 return expand_one_builtin (CODE_FOR_lum64
, target
, exp
, code
, 2);
2786 case IQ2000_BUILTIN_LUM64L
:
2787 return expand_one_builtin (CODE_FOR_lum64l
, target
, exp
, code
, 2);
2789 case IQ2000_BUILTIN_LURL
:
2790 return expand_one_builtin (CODE_FOR_lurl
, target
, exp
, code
, 2);
2792 case IQ2000_BUILTIN_MRGB
:
2793 code
[2] = CONST_INT
;
2794 return expand_one_builtin (CODE_FOR_mrgb
, target
, exp
, code
, 3);
2796 case IQ2000_BUILTIN_SRRDL
:
2797 return expand_one_builtin (CODE_FOR_srrdl
, target
, exp
, code
, 1);
2799 case IQ2000_BUILTIN_SRULCK
:
2800 return expand_one_builtin (CODE_FOR_srulck
, target
, exp
, code
, 1);
2802 case IQ2000_BUILTIN_SRWRU
:
2803 return expand_one_builtin (CODE_FOR_srwru
, target
, exp
, code
, 2);
2805 case IQ2000_BUILTIN_TRAPQFL
:
2806 return expand_one_builtin (CODE_FOR_trapqfl
, target
, exp
, code
, 0);
2808 case IQ2000_BUILTIN_TRAPQNE
:
2809 return expand_one_builtin (CODE_FOR_trapqne
, target
, exp
, code
, 0);
2811 case IQ2000_BUILTIN_TRAPREL
:
2812 return expand_one_builtin (CODE_FOR_traprel
, target
, exp
, code
, 1);
2814 case IQ2000_BUILTIN_WBU
:
2815 return expand_one_builtin (CODE_FOR_wbu
, target
, exp
, code
, 3);
2817 case IQ2000_BUILTIN_SYSCALL
:
2818 return expand_one_builtin (CODE_FOR_syscall
, target
, exp
, code
, 0);
2824 /* Worker function for TARGET_RETURN_IN_MEMORY. */
2827 iq2000_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
2829 return ((int_size_in_bytes (type
) > (2 * UNITS_PER_WORD
))
2830 || (int_size_in_bytes (type
) == -1));
2833 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
2836 iq2000_setup_incoming_varargs (CUMULATIVE_ARGS
*cum
,
2837 enum machine_mode mode ATTRIBUTE_UNUSED
,
2838 tree type ATTRIBUTE_UNUSED
, int * pretend_size
,
2841 unsigned int iq2000_off
= ! cum
->last_arg_fp
;
2842 unsigned int iq2000_fp_off
= cum
->last_arg_fp
;
2844 if ((cum
->arg_words
< MAX_ARGS_IN_REGISTERS
- iq2000_off
))
2846 int iq2000_save_gp_regs
2847 = MAX_ARGS_IN_REGISTERS
- cum
->arg_words
- iq2000_off
;
2848 int iq2000_save_fp_regs
2849 = (MAX_ARGS_IN_REGISTERS
- cum
->fp_arg_words
- iq2000_fp_off
);
2851 if (iq2000_save_gp_regs
< 0)
2852 iq2000_save_gp_regs
= 0;
2853 if (iq2000_save_fp_regs
< 0)
2854 iq2000_save_fp_regs
= 0;
2856 *pretend_size
= ((iq2000_save_gp_regs
* UNITS_PER_WORD
)
2857 + (iq2000_save_fp_regs
* UNITS_PER_FPREG
));
2861 if (cum
->arg_words
< MAX_ARGS_IN_REGISTERS
- iq2000_off
)
2864 ptr
= plus_constant (virtual_incoming_args_rtx
,
2865 - (iq2000_save_gp_regs
2867 mem
= gen_rtx_MEM (BLKmode
, ptr
);
2869 (cum
->arg_words
+ GP_ARG_FIRST
+ iq2000_off
,
2871 iq2000_save_gp_regs
);
2877 /* A C compound statement to output to stdio stream STREAM the
2878 assembler syntax for an instruction operand that is a memory
2879 reference whose address is ADDR. ADDR is an RTL expression. */
2882 print_operand_address (FILE * file
, rtx addr
)
2885 error ("PRINT_OPERAND_ADDRESS, null pointer");
2888 switch (GET_CODE (addr
))
2891 if (REGNO (addr
) == ARG_POINTER_REGNUM
)
2892 abort_with_insn (addr
, "Arg pointer not eliminated.");
2894 fprintf (file
, "0(%s)", reg_names
[REGNO (addr
)]);
2899 rtx arg0
= XEXP (addr
, 0);
2900 rtx arg1
= XEXP (addr
, 1);
2902 if (GET_CODE (arg0
) != REG
)
2903 abort_with_insn (addr
,
2904 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG.");
2906 fprintf (file
, "%%lo(");
2907 print_operand_address (file
, arg1
);
2908 fprintf (file
, ")(%s)", reg_names
[REGNO (arg0
)]);
2916 rtx arg0
= XEXP (addr
, 0);
2917 rtx arg1
= XEXP (addr
, 1);
2919 if (GET_CODE (arg0
) == REG
)
2923 if (GET_CODE (offset
) == REG
)
2924 abort_with_insn (addr
, "PRINT_OPERAND_ADDRESS, 2 regs");
2927 else if (GET_CODE (arg1
) == REG
)
2928 reg
= arg1
, offset
= arg0
;
2929 else if (CONSTANT_P (arg0
) && CONSTANT_P (arg1
))
2931 output_addr_const (file
, addr
);
2935 abort_with_insn (addr
, "PRINT_OPERAND_ADDRESS, no regs");
2937 if (! CONSTANT_P (offset
))
2938 abort_with_insn (addr
, "PRINT_OPERAND_ADDRESS, invalid insn #2");
2940 if (REGNO (reg
) == ARG_POINTER_REGNUM
)
2941 abort_with_insn (addr
, "Arg pointer not eliminated.");
2943 output_addr_const (file
, offset
);
2944 fprintf (file
, "(%s)", reg_names
[REGNO (reg
)]);
2952 output_addr_const (file
, addr
);
2953 if (GET_CODE (addr
) == CONST_INT
)
2954 fprintf (file
, "(%s)", reg_names
[0]);
2958 abort_with_insn (addr
, "PRINT_OPERAND_ADDRESS, invalid insn #1");
2963 /* A C compound statement to output to stdio stream FILE the
2964 assembler syntax for an instruction operand OP.
2966 LETTER is a value that can be used to specify one of several ways
2967 of printing the operand. It is used when identical operands
2968 must be printed differently depending on the context. LETTER
2969 comes from the `%' specification that was used to request
2970 printing of the operand. If the specification was just `%DIGIT'
2971 then LETTER is 0; if the specification was `%LTR DIGIT' then LETTER
2972 is the ASCII code for LTR.
2974 If OP is a register, this macro should print the register's name.
2975 The names can be found in an array `reg_names' whose type is
2976 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2978 When the machine description has a specification `%PUNCT' (a `%'
2979 followed by a punctuation character), this macro is called with
2980 a null pointer for X and the punctuation character for LETTER.
2982 The IQ2000 specific codes are:
2984 'X' X is CONST_INT, prints upper 16 bits in hexadecimal format = "0x%04x",
2985 'x' X is CONST_INT, prints lower 16 bits in hexadecimal format = "0x%04x",
2986 'd' output integer constant in decimal,
2987 'z' if the operand is 0, use $0 instead of normal operand.
2988 'D' print second part of double-word register or memory operand.
2989 'L' print low-order register of double-word register operand.
2990 'M' print high-order register of double-word register operand.
2991 'C' print part of opcode for a branch condition.
2992 'F' print part of opcode for a floating-point branch condition.
2993 'N' print part of opcode for a branch condition, inverted.
2994 'W' print part of opcode for a floating-point branch condition, inverted.
2995 'A' Print part of opcode for a bit test condition.
2996 'P' Print label for a bit test.
2997 'p' Print log for a bit test.
2998 'B' print 'z' for EQ, 'n' for NE
2999 'b' print 'n' for EQ, 'z' for NE
3000 'T' print 'f' for EQ, 't' for NE
3001 't' print 't' for EQ, 'f' for NE
3002 'Z' print register and a comma, but print nothing for $fcc0
3003 '?' Print 'l' if we are to use a branch likely instead of normal branch.
3004 '@' Print the name of the assembler temporary register (at or $1).
3005 '.' Print the name of the register with a hard-wired zero (zero or $0).
3006 '$' Print the name of the stack pointer register (sp or $29).
3007 '+' Print the name of the gp register (gp or $28). */
3010 print_operand (FILE *file
, rtx op
, int letter
)
3014 if (PRINT_OPERAND_PUNCT_VALID_P (letter
))
3019 if (iq2000_branch_likely
)
3024 fputs (reg_names
[GP_REG_FIRST
+ 1], file
);
3028 fputs (reg_names
[GP_REG_FIRST
+ 0], file
);
3032 fputs (reg_names
[STACK_POINTER_REGNUM
], file
);
3036 fputs (reg_names
[GP_REG_FIRST
+ 28], file
);
3040 error ("PRINT_OPERAND: Unknown punctuation '%c'", letter
);
3049 error ("PRINT_OPERAND null pointer");
3053 code
= GET_CODE (op
);
3055 if (code
== SIGN_EXTEND
)
3056 op
= XEXP (op
, 0), code
= GET_CODE (op
);
3061 case EQ
: fputs ("eq", file
); break;
3062 case NE
: fputs ("ne", file
); break;
3063 case GT
: fputs ("gt", file
); break;
3064 case GE
: fputs ("ge", file
); break;
3065 case LT
: fputs ("lt", file
); break;
3066 case LE
: fputs ("le", file
); break;
3067 case GTU
: fputs ("ne", file
); break;
3068 case GEU
: fputs ("geu", file
); break;
3069 case LTU
: fputs ("ltu", file
); break;
3070 case LEU
: fputs ("eq", file
); break;
3072 abort_with_insn (op
, "PRINT_OPERAND, invalid insn for %%C");
3075 else if (letter
== 'N')
3078 case EQ
: fputs ("ne", file
); break;
3079 case NE
: fputs ("eq", file
); break;
3080 case GT
: fputs ("le", file
); break;
3081 case GE
: fputs ("lt", file
); break;
3082 case LT
: fputs ("ge", file
); break;
3083 case LE
: fputs ("gt", file
); break;
3084 case GTU
: fputs ("leu", file
); break;
3085 case GEU
: fputs ("ltu", file
); break;
3086 case LTU
: fputs ("geu", file
); break;
3087 case LEU
: fputs ("gtu", file
); break;
3089 abort_with_insn (op
, "PRINT_OPERAND, invalid insn for %%N");
3092 else if (letter
== 'F')
3095 case EQ
: fputs ("c1f", file
); break;
3096 case NE
: fputs ("c1t", file
); break;
3098 abort_with_insn (op
, "PRINT_OPERAND, invalid insn for %%F");
3101 else if (letter
== 'W')
3104 case EQ
: fputs ("c1t", file
); break;
3105 case NE
: fputs ("c1f", file
); break;
3107 abort_with_insn (op
, "PRINT_OPERAND, invalid insn for %%W");
3110 else if (letter
== 'A')
3111 fputs (code
== LABEL_REF
? "i" : "in", file
);
3113 else if (letter
== 'P')
3115 if (code
== LABEL_REF
)
3116 output_addr_const (file
, op
);
3117 else if (code
!= PC
)
3118 output_operand_lossage ("invalid %%P operand");
3121 else if (letter
== 'p')
3124 if (code
!= CONST_INT
3125 || (value
= exact_log2 (INTVAL (op
))) < 0)
3126 output_operand_lossage ("invalid %%p value");
3127 fprintf (file
, "%d", value
);
3130 else if (letter
== 'Z')
3135 else if (code
== REG
|| code
== SUBREG
)
3140 regnum
= REGNO (op
);
3142 regnum
= true_regnum (op
);
3144 if ((letter
== 'M' && ! WORDS_BIG_ENDIAN
)
3145 || (letter
== 'L' && WORDS_BIG_ENDIAN
)
3149 fprintf (file
, "%s", reg_names
[regnum
]);
3152 else if (code
== MEM
)
3155 output_address (plus_constant (XEXP (op
, 0), 4));
3157 output_address (XEXP (op
, 0));
3160 else if (code
== CONST_DOUBLE
3161 && GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
3165 real_to_decimal (s
, CONST_DOUBLE_REAL_VALUE (op
), sizeof (s
), 0, 1);
3169 else if (letter
== 'x' && GET_CODE (op
) == CONST_INT
)
3170 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, 0xffff & INTVAL(op
));
3172 else if (letter
== 'X' && GET_CODE(op
) == CONST_INT
)
3173 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, 0xffff & (INTVAL (op
) >> 16));
3175 else if (letter
== 'd' && GET_CODE(op
) == CONST_INT
)
3176 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, (INTVAL(op
)));
3178 else if (letter
== 'z' && GET_CODE (op
) == CONST_INT
&& INTVAL (op
) == 0)
3179 fputs (reg_names
[GP_REG_FIRST
], file
);
3181 else if (letter
== 'd' || letter
== 'x' || letter
== 'X')
3182 output_operand_lossage ("invalid use of %%d, %%x, or %%X");
3184 else if (letter
== 'B')
3185 fputs (code
== EQ
? "z" : "n", file
);
3186 else if (letter
== 'b')
3187 fputs (code
== EQ
? "n" : "z", file
);
3188 else if (letter
== 'T')
3189 fputs (code
== EQ
? "f" : "t", file
);
3190 else if (letter
== 't')
3191 fputs (code
== EQ
? "t" : "f", file
);
3193 else if (code
== CONST
&& GET_CODE (XEXP (op
, 0)) == REG
)
3195 print_operand (file
, XEXP (op
, 0), letter
);
3199 output_addr_const (file
, op
);
3203 iq2000_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
, int * total
)
3205 enum machine_mode mode
= GET_MODE (x
);
3211 int num_words
= (GET_MODE_SIZE (mode
) > UNITS_PER_WORD
) ? 2 : 1;
3213 if (simple_memory_operand (x
, mode
))
3214 return COSTS_N_INSNS (num_words
);
3216 * total
= COSTS_N_INSNS (2 * num_words
);
3221 * total
= COSTS_N_INSNS (6);
3228 * total
= COSTS_N_INSNS (mode
== DImode
? 2 : 1);
3235 * total
= COSTS_N_INSNS ((GET_CODE (XEXP (x
, 1)) == CONST_INT
) ? 4 : 12);
3237 * total
= COSTS_N_INSNS (1);
3241 if (mode
== SFmode
|| mode
== DFmode
)
3242 * total
= COSTS_N_INSNS (1);
3244 * total
= COSTS_N_INSNS (4);
3249 if (mode
== SFmode
|| mode
== DFmode
)
3250 * total
= COSTS_N_INSNS (6);
3251 else if (mode
== DImode
)
3252 * total
= COSTS_N_INSNS (4);
3254 * total
= COSTS_N_INSNS (1);
3258 * total
= (mode
== DImode
) ? 4 : 1;
3263 * total
= COSTS_N_INSNS (7);
3264 else if (mode
== DFmode
)
3265 * total
= COSTS_N_INSNS (8);
3267 * total
= COSTS_N_INSNS (10);
3273 * total
= COSTS_N_INSNS (23);
3274 else if (mode
== DFmode
)
3275 * total
= COSTS_N_INSNS (36);
3277 * total
= COSTS_N_INSNS (69);
3282 * total
= COSTS_N_INSNS (69);
3286 * total
= COSTS_N_INSNS (2);
3290 * total
= COSTS_N_INSNS (1);
3298 * total
= COSTS_N_INSNS (2);
3303 rtx offset
= const0_rtx
;
3304 rtx symref
= eliminate_constant_term (XEXP (x
, 0), & offset
);
3306 if (GET_CODE (symref
) == LABEL_REF
)
3307 * total
= COSTS_N_INSNS (2);
3308 else if (GET_CODE (symref
) != SYMBOL_REF
)
3309 * total
= COSTS_N_INSNS (4);
3310 /* Let's be paranoid.... */
3311 else if (INTVAL (offset
) < -32768 || INTVAL (offset
) > 32767)
3312 * total
= COSTS_N_INSNS (2);
3314 * total
= COSTS_N_INSNS (SYMBOL_REF_FLAG (symref
) ? 1 : 2);
3319 * total
= COSTS_N_INSNS (SYMBOL_REF_FLAG (x
) ? 1 : 2);
3326 split_double (x
, & high
, & low
);
3328 * total
= COSTS_N_INSNS ( (high
== CONST0_RTX (GET_MODE (high
))
3329 || low
== CONST0_RTX (GET_MODE (low
)))
3340 #include "gt-iq2000.h"