comparison gcc/config/iq2000/iq2000.c @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children 77e2b8dfacca
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
1 /* Subroutines used for code generation on Vitesse IQ2000 processors
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
3 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include <signal.h>
25 #include "tm.h"
26 #include "tree.h"
27 #include "rtl.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "flags.h"
36 #include "function.h"
37 #include "expr.h"
38 #include "optabs.h"
39 #include "libfuncs.h"
40 #include "recog.h"
41 #include "toplev.h"
42 #include "reload.h"
43 #include "ggc.h"
44 #include "tm_p.h"
45 #include "debug.h"
46 #include "target.h"
47 #include "target-def.h"
48 #include "langhooks.h"
49
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
52 of EQ, NE, etc. */
53
54 enum internal_test
55 {
56 ITEST_EQ,
57 ITEST_NE,
58 ITEST_GT,
59 ITEST_GE,
60 ITEST_LT,
61 ITEST_LE,
62 ITEST_GTU,
63 ITEST_GEU,
64 ITEST_LTU,
65 ITEST_LEU,
66 ITEST_MAX
67 };
68
69 struct constant;
70
71
72 /* Structure to be filled in by compute_frame_size with register
73 save masks, and offsets for the current function. */
74
75 struct iq2000_frame_info
76 {
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. */
90 } iq2000_frame_info;
91
92 struct machine_function GTY(())
93 {
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. */
108 };
109
110 /* Global variables for machine-dependent things. */
111
112 /* List of all IQ2000 punctuation characters used by print_operand. */
113 char iq2000_print_operand_punct[256];
114
115 /* The target cpu for optimization and scheduling. */
116 enum processor_type iq2000_tune;
117
118 /* Which instruction set architecture to use. */
119 int iq2000_isa;
120
121 /* Cached operands, and operator to compare for use in set/branch/trap
122 on condition codes. */
123 rtx branch_cmp[2];
124
125 /* What type of branch to use. */
126 enum cmp_type branch_type;
127
128 /* Local variables. */
129
130 /* The next branch instruction is a branch likely, not branch normal. */
131 static int iq2000_branch_likely;
132
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;
137
138 /* # of nops needed by previous insn. */
139 static int dslots_number_nops;
140
141 /* Number of 1/2/3 word references to data items (i.e., not jal's). */
142 static int num_refs[3];
143
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;
149
150 /* Mode used for saving/restoring general purpose registers. */
151 static enum machine_mode gpr_mode;
152
153
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 (const_tree, const_tree);
162 static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *,
163 enum machine_mode, tree, int *,
164 int);
165 static bool iq2000_rtx_costs (rtx, int, int, int *, bool);
166 static int iq2000_address_cost (rtx, bool);
167 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
168 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
169 const_tree, bool);
170 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
171 tree, bool);
172 static void iq2000_va_start (tree, rtx);
173
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
188
189 /* The assembler supports switchable .bss sections, but
190 iq2000_select_section doesn't yet make use of them. */
191 #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
192 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false
193
194 #undef TARGET_PROMOTE_FUNCTION_ARGS
195 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
196 #undef TARGET_PROMOTE_FUNCTION_RETURN
197 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
198 #undef TARGET_PROMOTE_PROTOTYPES
199 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
200
201 #undef TARGET_RETURN_IN_MEMORY
202 #define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
203 #undef TARGET_PASS_BY_REFERENCE
204 #define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference
205 #undef TARGET_CALLEE_COPIES
206 #define TARGET_CALLEE_COPIES hook_callee_copies_named
207 #undef TARGET_ARG_PARTIAL_BYTES
208 #define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes
209
210 #undef TARGET_SETUP_INCOMING_VARARGS
211 #define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs
212 #undef TARGET_STRICT_ARGUMENT_NAMING
213 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
214
215 #undef TARGET_EXPAND_BUILTIN_VA_START
216 #define TARGET_EXPAND_BUILTIN_VA_START iq2000_va_start
217
218 struct gcc_target targetm = TARGET_INITIALIZER;
219
220 /* Return nonzero if we split the address into high and low parts. */
221
222 int
223 iq2000_check_split (rtx address, enum machine_mode mode)
224 {
225 /* This is the same check used in simple_memory_operand.
226 We use it here because LO_SUM is not offsettable. */
227 if (GET_MODE_SIZE (mode) > (unsigned) UNITS_PER_WORD)
228 return 0;
229
230 if ((GET_CODE (address) == SYMBOL_REF)
231 || (GET_CODE (address) == CONST
232 && GET_CODE (XEXP (XEXP (address, 0), 0)) == SYMBOL_REF)
233 || GET_CODE (address) == LABEL_REF)
234 return 1;
235
236 return 0;
237 }
238
239 /* Return nonzero if REG is valid for MODE. */
240
241 int
242 iq2000_reg_mode_ok_for_base_p (rtx reg,
243 enum machine_mode mode ATTRIBUTE_UNUSED,
244 int strict)
245 {
246 return (strict
247 ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode)
248 : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode));
249 }
250
251 /* Return a nonzero value if XINSN is a legitimate address for a
252 memory operand of the indicated MODE. STRICT is nonzero if this
253 function is called during reload. */
254
255 int
256 iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict)
257 {
258 if (TARGET_DEBUG_A_MODE)
259 {
260 GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
261 strict ? "" : "not ");
262 GO_DEBUG_RTX (xinsn);
263 }
264
265 /* Check for constant before stripping off SUBREG, so that we don't
266 accept (subreg (const_int)) which will fail to reload. */
267 if (CONSTANT_ADDRESS_P (xinsn)
268 && ! (iq2000_check_split (xinsn, mode))
269 && ! (GET_CODE (xinsn) == CONST_INT && ! SMALL_INT (xinsn)))
270 return 1;
271
272 while (GET_CODE (xinsn) == SUBREG)
273 xinsn = SUBREG_REG (xinsn);
274
275 if (GET_CODE (xinsn) == REG
276 && iq2000_reg_mode_ok_for_base_p (xinsn, mode, strict))
277 return 1;
278
279 if (GET_CODE (xinsn) == LO_SUM)
280 {
281 rtx xlow0 = XEXP (xinsn, 0);
282 rtx xlow1 = XEXP (xinsn, 1);
283
284 while (GET_CODE (xlow0) == SUBREG)
285 xlow0 = SUBREG_REG (xlow0);
286 if (GET_CODE (xlow0) == REG
287 && iq2000_reg_mode_ok_for_base_p (xlow0, mode, strict)
288 && iq2000_check_split (xlow1, mode))
289 return 1;
290 }
291
292 if (GET_CODE (xinsn) == PLUS)
293 {
294 rtx xplus0 = XEXP (xinsn, 0);
295 rtx xplus1 = XEXP (xinsn, 1);
296 enum rtx_code code0;
297 enum rtx_code code1;
298
299 while (GET_CODE (xplus0) == SUBREG)
300 xplus0 = SUBREG_REG (xplus0);
301 code0 = GET_CODE (xplus0);
302
303 while (GET_CODE (xplus1) == SUBREG)
304 xplus1 = SUBREG_REG (xplus1);
305 code1 = GET_CODE (xplus1);
306
307 if (code0 == REG
308 && iq2000_reg_mode_ok_for_base_p (xplus0, mode, strict))
309 {
310 if (code1 == CONST_INT && SMALL_INT (xplus1)
311 && SMALL_INT_UNSIGNED (xplus1) /* No negative offsets */)
312 return 1;
313 }
314 }
315
316 if (TARGET_DEBUG_A_MODE)
317 GO_PRINTF ("Not a legitimate address\n");
318
319 /* The address was not legitimate. */
320 return 0;
321 }
322
323 /* Returns an operand string for the given instruction's delay slot,
324 after updating filled delay slot statistics.
325
326 We assume that operands[0] is the target register that is set.
327
328 In order to check the next insn, most of this functionality is moved
329 to FINAL_PRESCAN_INSN, and we just set the global variables that
330 it needs. */
331
332 const char *
333 iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[],
334 rtx cur_insn)
335 {
336 rtx set_reg;
337 enum machine_mode mode;
338 rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX;
339 int num_nops;
340
341 if (type == DELAY_LOAD || type == DELAY_FCMP)
342 num_nops = 1;
343
344 else
345 num_nops = 0;
346
347 /* Make sure that we don't put nop's after labels. */
348 next_insn = NEXT_INSN (cur_insn);
349 while (next_insn != 0
350 && (GET_CODE (next_insn) == NOTE
351 || GET_CODE (next_insn) == CODE_LABEL))
352 next_insn = NEXT_INSN (next_insn);
353
354 dslots_load_total += num_nops;
355 if (TARGET_DEBUG_C_MODE
356 || type == DELAY_NONE
357 || operands == 0
358 || cur_insn == 0
359 || next_insn == 0
360 || GET_CODE (next_insn) == CODE_LABEL
361 || (set_reg = operands[0]) == 0)
362 {
363 dslots_number_nops = 0;
364 iq2000_load_reg = 0;
365 iq2000_load_reg2 = 0;
366 iq2000_load_reg3 = 0;
367 iq2000_load_reg4 = 0;
368
369 return ret;
370 }
371
372 set_reg = operands[0];
373 if (set_reg == 0)
374 return ret;
375
376 while (GET_CODE (set_reg) == SUBREG)
377 set_reg = SUBREG_REG (set_reg);
378
379 mode = GET_MODE (set_reg);
380 dslots_number_nops = num_nops;
381 iq2000_load_reg = set_reg;
382 if (GET_MODE_SIZE (mode)
383 > (unsigned) (UNITS_PER_WORD))
384 iq2000_load_reg2 = gen_rtx_REG (SImode, REGNO (set_reg) + 1);
385 else
386 iq2000_load_reg2 = 0;
387
388 return ret;
389 }
390
391 /* Determine whether a memory reference takes one (based off of the GP
392 pointer), two (normal), or three (label + reg) instructions, and bump the
393 appropriate counter for -mstats. */
394
395 static void
396 iq2000_count_memory_refs (rtx op, int num)
397 {
398 int additional = 0;
399 int n_words = 0;
400 rtx addr, plus0, plus1;
401 enum rtx_code code0, code1;
402 int looping;
403
404 if (TARGET_DEBUG_B_MODE)
405 {
406 fprintf (stderr, "\n========== iq2000_count_memory_refs:\n");
407 debug_rtx (op);
408 }
409
410 /* Skip MEM if passed, otherwise handle movsi of address. */
411 addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0);
412
413 /* Loop, going through the address RTL. */
414 do
415 {
416 looping = FALSE;
417 switch (GET_CODE (addr))
418 {
419 case REG:
420 case CONST_INT:
421 case LO_SUM:
422 break;
423
424 case PLUS:
425 plus0 = XEXP (addr, 0);
426 plus1 = XEXP (addr, 1);
427 code0 = GET_CODE (plus0);
428 code1 = GET_CODE (plus1);
429
430 if (code0 == REG)
431 {
432 additional++;
433 addr = plus1;
434 looping = 1;
435 continue;
436 }
437
438 if (code0 == CONST_INT)
439 {
440 addr = plus1;
441 looping = 1;
442 continue;
443 }
444
445 if (code1 == REG)
446 {
447 additional++;
448 addr = plus0;
449 looping = 1;
450 continue;
451 }
452
453 if (code1 == CONST_INT)
454 {
455 addr = plus0;
456 looping = 1;
457 continue;
458 }
459
460 if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST)
461 {
462 addr = plus0;
463 looping = 1;
464 continue;
465 }
466
467 if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST)
468 {
469 addr = plus1;
470 looping = 1;
471 continue;
472 }
473
474 break;
475
476 case LABEL_REF:
477 n_words = 2; /* Always 2 words. */
478 break;
479
480 case CONST:
481 addr = XEXP (addr, 0);
482 looping = 1;
483 continue;
484
485 case SYMBOL_REF:
486 n_words = SYMBOL_REF_FLAG (addr) ? 1 : 2;
487 break;
488
489 default:
490 break;
491 }
492 }
493 while (looping);
494
495 if (n_words == 0)
496 return;
497
498 n_words += additional;
499 if (n_words > 3)
500 n_words = 3;
501
502 num_refs[n_words-1] += num;
503 }
504
505 /* Abort after printing out a specific insn. */
506
507 static void
508 abort_with_insn (rtx insn, const char * reason)
509 {
510 error (reason);
511 debug_rtx (insn);
512 fancy_abort (__FILE__, __LINE__, __FUNCTION__);
513 }
514
515 /* Return the appropriate instructions to move one operand to another. */
516
517 const char *
518 iq2000_move_1word (rtx operands[], rtx insn, int unsignedp)
519 {
520 const char *ret = 0;
521 rtx op0 = operands[0];
522 rtx op1 = operands[1];
523 enum rtx_code code0 = GET_CODE (op0);
524 enum rtx_code code1 = GET_CODE (op1);
525 enum machine_mode mode = GET_MODE (op0);
526 int subreg_offset0 = 0;
527 int subreg_offset1 = 0;
528 enum delay_type delay = DELAY_NONE;
529
530 while (code0 == SUBREG)
531 {
532 subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),
533 GET_MODE (SUBREG_REG (op0)),
534 SUBREG_BYTE (op0),
535 GET_MODE (op0));
536 op0 = SUBREG_REG (op0);
537 code0 = GET_CODE (op0);
538 }
539
540 while (code1 == SUBREG)
541 {
542 subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),
543 GET_MODE (SUBREG_REG (op1)),
544 SUBREG_BYTE (op1),
545 GET_MODE (op1));
546 op1 = SUBREG_REG (op1);
547 code1 = GET_CODE (op1);
548 }
549
550 /* For our purposes, a condition code mode is the same as SImode. */
551 if (mode == CCmode)
552 mode = SImode;
553
554 if (code0 == REG)
555 {
556 int regno0 = REGNO (op0) + subreg_offset0;
557
558 if (code1 == REG)
559 {
560 int regno1 = REGNO (op1) + subreg_offset1;
561
562 /* Do not do anything for assigning a register to itself */
563 if (regno0 == regno1)
564 ret = "";
565
566 else if (GP_REG_P (regno0))
567 {
568 if (GP_REG_P (regno1))
569 ret = "or\t%0,%%0,%1";
570 }
571
572 }
573
574 else if (code1 == MEM)
575 {
576 delay = DELAY_LOAD;
577
578 if (TARGET_STATS)
579 iq2000_count_memory_refs (op1, 1);
580
581 if (GP_REG_P (regno0))
582 {
583 /* For loads, use the mode of the memory item, instead of the
584 target, so zero/sign extend can use this code as well. */
585 switch (GET_MODE (op1))
586 {
587 default:
588 break;
589 case SFmode:
590 ret = "lw\t%0,%1";
591 break;
592 case SImode:
593 case CCmode:
594 ret = "lw\t%0,%1";
595 break;
596 case HImode:
597 ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1";
598 break;
599 case QImode:
600 ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1";
601 break;
602 }
603 }
604 }
605
606 else if (code1 == CONST_INT
607 || (code1 == CONST_DOUBLE
608 && GET_MODE (op1) == VOIDmode))
609 {
610 if (code1 == CONST_DOUBLE)
611 {
612 /* This can happen when storing constants into long long
613 bitfields. Just store the least significant word of
614 the value. */
615 operands[1] = op1 = GEN_INT (CONST_DOUBLE_LOW (op1));
616 }
617
618 if (INTVAL (op1) == 0)
619 {
620 if (GP_REG_P (regno0))
621 ret = "or\t%0,%%0,%z1";
622 }
623 else if (GP_REG_P (regno0))
624 {
625 if (SMALL_INT_UNSIGNED (op1))
626 ret = "ori\t%0,%%0,%x1\t\t\t# %1";
627 else if (SMALL_INT (op1))
628 ret = "addiu\t%0,%%0,%1\t\t\t# %1";
629 else
630 ret = "lui\t%0,%X1\t\t\t# %1\n\tori\t%0,%0,%x1";
631 }
632 }
633
634 else if (code1 == CONST_DOUBLE && mode == SFmode)
635 {
636 if (op1 == CONST0_RTX (SFmode))
637 {
638 if (GP_REG_P (regno0))
639 ret = "or\t%0,%%0,%.";
640 }
641
642 else
643 {
644 delay = DELAY_LOAD;
645 ret = "li.s\t%0,%1";
646 }
647 }
648
649 else if (code1 == LABEL_REF)
650 {
651 if (TARGET_STATS)
652 iq2000_count_memory_refs (op1, 1);
653
654 ret = "la\t%0,%a1";
655 }
656
657 else if (code1 == SYMBOL_REF || code1 == CONST)
658 {
659 if (TARGET_STATS)
660 iq2000_count_memory_refs (op1, 1);
661
662 ret = "la\t%0,%a1";
663 }
664
665 else if (code1 == PLUS)
666 {
667 rtx add_op0 = XEXP (op1, 0);
668 rtx add_op1 = XEXP (op1, 1);
669
670 if (GET_CODE (XEXP (op1, 1)) == REG
671 && GET_CODE (XEXP (op1, 0)) == CONST_INT)
672 add_op0 = XEXP (op1, 1), add_op1 = XEXP (op1, 0);
673
674 operands[2] = add_op0;
675 operands[3] = add_op1;
676 ret = "add%:\t%0,%2,%3";
677 }
678
679 else if (code1 == HIGH)
680 {
681 operands[1] = XEXP (op1, 0);
682 ret = "lui\t%0,%%hi(%1)";
683 }
684 }
685
686 else if (code0 == MEM)
687 {
688 if (TARGET_STATS)
689 iq2000_count_memory_refs (op0, 1);
690
691 if (code1 == REG)
692 {
693 int regno1 = REGNO (op1) + subreg_offset1;
694
695 if (GP_REG_P (regno1))
696 {
697 switch (mode)
698 {
699 case SFmode: ret = "sw\t%1,%0"; break;
700 case SImode: ret = "sw\t%1,%0"; break;
701 case HImode: ret = "sh\t%1,%0"; break;
702 case QImode: ret = "sb\t%1,%0"; break;
703 default: break;
704 }
705 }
706 }
707
708 else if (code1 == CONST_INT && INTVAL (op1) == 0)
709 {
710 switch (mode)
711 {
712 case SFmode: ret = "sw\t%z1,%0"; break;
713 case SImode: ret = "sw\t%z1,%0"; break;
714 case HImode: ret = "sh\t%z1,%0"; break;
715 case QImode: ret = "sb\t%z1,%0"; break;
716 default: break;
717 }
718 }
719
720 else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode))
721 {
722 switch (mode)
723 {
724 case SFmode: ret = "sw\t%.,%0"; break;
725 case SImode: ret = "sw\t%.,%0"; break;
726 case HImode: ret = "sh\t%.,%0"; break;
727 case QImode: ret = "sb\t%.,%0"; break;
728 default: break;
729 }
730 }
731 }
732
733 if (ret == 0)
734 {
735 abort_with_insn (insn, "Bad move");
736 return 0;
737 }
738
739 if (delay != DELAY_NONE)
740 return iq2000_fill_delay_slot (ret, delay, operands, insn);
741
742 return ret;
743 }
744
745 /* Provide the costs of an addressing mode that contains ADDR. */
746
747 static int
748 iq2000_address_cost (rtx addr, bool speed)
749 {
750 switch (GET_CODE (addr))
751 {
752 case LO_SUM:
753 return 1;
754
755 case LABEL_REF:
756 return 2;
757
758 case CONST:
759 {
760 rtx offset = const0_rtx;
761
762 addr = eliminate_constant_term (XEXP (addr, 0), & offset);
763 if (GET_CODE (addr) == LABEL_REF)
764 return 2;
765
766 if (GET_CODE (addr) != SYMBOL_REF)
767 return 4;
768
769 if (! SMALL_INT (offset))
770 return 2;
771 }
772
773 /* Fall through. */
774
775 case SYMBOL_REF:
776 return SYMBOL_REF_FLAG (addr) ? 1 : 2;
777
778 case PLUS:
779 {
780 rtx plus0 = XEXP (addr, 0);
781 rtx plus1 = XEXP (addr, 1);
782
783 if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
784 plus0 = XEXP (addr, 1), plus1 = XEXP (addr, 0);
785
786 if (GET_CODE (plus0) != REG)
787 break;
788
789 switch (GET_CODE (plus1))
790 {
791 case CONST_INT:
792 return SMALL_INT (plus1) ? 1 : 2;
793
794 case CONST:
795 case SYMBOL_REF:
796 case LABEL_REF:
797 case HIGH:
798 case LO_SUM:
799 return iq2000_address_cost (plus1, speed) + 1;
800
801 default:
802 break;
803 }
804 }
805
806 default:
807 break;
808 }
809
810 return 4;
811 }
812
813 /* Make normal rtx_code into something we can index from an array. */
814
815 static enum internal_test
816 map_test_to_internal_test (enum rtx_code test_code)
817 {
818 enum internal_test test = ITEST_MAX;
819
820 switch (test_code)
821 {
822 case EQ: test = ITEST_EQ; break;
823 case NE: test = ITEST_NE; break;
824 case GT: test = ITEST_GT; break;
825 case GE: test = ITEST_GE; break;
826 case LT: test = ITEST_LT; break;
827 case LE: test = ITEST_LE; break;
828 case GTU: test = ITEST_GTU; break;
829 case GEU: test = ITEST_GEU; break;
830 case LTU: test = ITEST_LTU; break;
831 case LEU: test = ITEST_LEU; break;
832 default: break;
833 }
834
835 return test;
836 }
837
838 /* Generate the code to do a TEST_CODE comparison on two integer values CMP0
839 and CMP1. P_INVERT is NULL or ptr if branch needs to reverse its test.
840 The return value RESULT is:
841 (reg:SI xx) The pseudo register the comparison is in
842 0 No register, generate a simple branch. */
843
844 rtx
845 gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1,
846 int *p_invert)
847 {
848 struct cmp_info
849 {
850 enum rtx_code test_code; /* Code to use in instruction (LT vs. LTU). */
851 int const_low; /* Low bound of constant we can accept. */
852 int const_high; /* High bound of constant we can accept. */
853 int const_add; /* Constant to add (convert LE -> LT). */
854 int reverse_regs; /* Reverse registers in test. */
855 int invert_const; /* != 0 if invert value if cmp1 is constant. */
856 int invert_reg; /* != 0 if invert value if cmp1 is register. */
857 int unsignedp; /* != 0 for unsigned comparisons. */
858 };
859
860 static struct cmp_info info[ (int)ITEST_MAX ] =
861 {
862 { XOR, 0, 65535, 0, 0, 0, 0, 0 }, /* EQ */
863 { XOR, 0, 65535, 0, 0, 1, 1, 0 }, /* NE */
864 { LT, -32769, 32766, 1, 1, 1, 0, 0 }, /* GT */
865 { LT, -32768, 32767, 0, 0, 1, 1, 0 }, /* GE */
866 { LT, -32768, 32767, 0, 0, 0, 0, 0 }, /* LT */
867 { LT, -32769, 32766, 1, 1, 0, 1, 0 }, /* LE */
868 { LTU, -32769, 32766, 1, 1, 1, 0, 1 }, /* GTU */
869 { LTU, -32768, 32767, 0, 0, 1, 1, 1 }, /* GEU */
870 { LTU, -32768, 32767, 0, 0, 0, 0, 1 }, /* LTU */
871 { LTU, -32769, 32766, 1, 1, 0, 1, 1 }, /* LEU */
872 };
873
874 enum internal_test test;
875 enum machine_mode mode;
876 struct cmp_info *p_info;
877 int branch_p;
878 int eqne_p;
879 int invert;
880 rtx reg;
881 rtx reg2;
882
883 test = map_test_to_internal_test (test_code);
884 gcc_assert (test != ITEST_MAX);
885
886 p_info = &info[(int) test];
887 eqne_p = (p_info->test_code == XOR);
888
889 mode = GET_MODE (cmp0);
890 if (mode == VOIDmode)
891 mode = GET_MODE (cmp1);
892
893 /* Eliminate simple branches. */
894 branch_p = (result == 0);
895 if (branch_p)
896 {
897 if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
898 {
899 /* Comparisons against zero are simple branches. */
900 if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
901 return 0;
902
903 /* Test for beq/bne. */
904 if (eqne_p)
905 return 0;
906 }
907
908 /* Allocate a pseudo to calculate the value in. */
909 result = gen_reg_rtx (mode);
910 }
911
912 /* Make sure we can handle any constants given to us. */
913 if (GET_CODE (cmp0) == CONST_INT)
914 cmp0 = force_reg (mode, cmp0);
915
916 if (GET_CODE (cmp1) == CONST_INT)
917 {
918 HOST_WIDE_INT value = INTVAL (cmp1);
919
920 if (value < p_info->const_low
921 || value > p_info->const_high)
922 cmp1 = force_reg (mode, cmp1);
923 }
924
925 /* See if we need to invert the result. */
926 invert = (GET_CODE (cmp1) == CONST_INT
927 ? p_info->invert_const : p_info->invert_reg);
928
929 if (p_invert != (int *)0)
930 {
931 *p_invert = invert;
932 invert = 0;
933 }
934
935 /* Comparison to constants, may involve adding 1 to change a LT into LE.
936 Comparison between two registers, may involve switching operands. */
937 if (GET_CODE (cmp1) == CONST_INT)
938 {
939 if (p_info->const_add != 0)
940 {
941 HOST_WIDE_INT new_const = INTVAL (cmp1) + p_info->const_add;
942
943 /* If modification of cmp1 caused overflow,
944 we would get the wrong answer if we follow the usual path;
945 thus, x > 0xffffffffU would turn into x > 0U. */
946 if ((p_info->unsignedp
947 ? (unsigned HOST_WIDE_INT) new_const >
948 (unsigned HOST_WIDE_INT) INTVAL (cmp1)
949 : new_const > INTVAL (cmp1))
950 != (p_info->const_add > 0))
951 {
952 /* This test is always true, but if INVERT is true then
953 the result of the test needs to be inverted so 0 should
954 be returned instead. */
955 emit_move_insn (result, invert ? const0_rtx : const_true_rtx);
956 return result;
957 }
958 else
959 cmp1 = GEN_INT (new_const);
960 }
961 }
962
963 else if (p_info->reverse_regs)
964 {
965 rtx temp = cmp0;
966 cmp0 = cmp1;
967 cmp1 = temp;
968 }
969
970 if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
971 reg = cmp0;
972 else
973 {
974 reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result;
975 convert_move (reg, gen_rtx_fmt_ee (p_info->test_code, mode, cmp0, cmp1), 0);
976 }
977
978 if (test == ITEST_NE)
979 {
980 convert_move (result, gen_rtx_GTU (mode, reg, const0_rtx), 0);
981 if (p_invert != NULL)
982 *p_invert = 0;
983 invert = 0;
984 }
985
986 else if (test == ITEST_EQ)
987 {
988 reg2 = invert ? gen_reg_rtx (mode) : result;
989 convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0);
990 reg = reg2;
991 }
992
993 if (invert)
994 {
995 rtx one;
996
997 one = const1_rtx;
998 convert_move (result, gen_rtx_XOR (mode, reg, one), 0);
999 }
1000
1001 return result;
1002 }
1003
1004 /* Emit the common code for doing conditional branches.
1005 operand[0] is the label to jump to.
1006 The comparison operands are saved away by cmp{si,di,sf,df}. */
1007
1008 void
1009 gen_conditional_branch (rtx operands[], enum rtx_code test_code)
1010 {
1011 enum cmp_type type = branch_type;
1012 rtx cmp0 = branch_cmp[0];
1013 rtx cmp1 = branch_cmp[1];
1014 enum machine_mode mode;
1015 rtx reg;
1016 int invert;
1017 rtx label1, label2;
1018
1019 switch (type)
1020 {
1021 case CMP_SI:
1022 case CMP_DI:
1023 mode = type == CMP_SI ? SImode : DImode;
1024 invert = 0;
1025 reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
1026
1027 if (reg)
1028 {
1029 cmp0 = reg;
1030 cmp1 = const0_rtx;
1031 test_code = NE;
1032 }
1033 else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
1034 /* We don't want to build a comparison against a nonzero
1035 constant. */
1036 cmp1 = force_reg (mode, cmp1);
1037
1038 break;
1039
1040 case CMP_SF:
1041 case CMP_DF:
1042 reg = gen_reg_rtx (CCmode);
1043
1044 /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */
1045 emit_insn (gen_rtx_SET (VOIDmode, reg,
1046 gen_rtx_fmt_ee (test_code == NE ? EQ : test_code,
1047 CCmode, cmp0, cmp1)));
1048
1049 test_code = test_code == NE ? EQ : NE;
1050 mode = CCmode;
1051 cmp0 = reg;
1052 cmp1 = const0_rtx;
1053 invert = 0;
1054 break;
1055
1056 default:
1057 abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1),
1058 "bad test");
1059 }
1060
1061 /* Generate the branch. */
1062 label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);
1063 label2 = pc_rtx;
1064
1065 if (invert)
1066 {
1067 label2 = label1;
1068 label1 = pc_rtx;
1069 }
1070
1071 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1072 gen_rtx_IF_THEN_ELSE (VOIDmode,
1073 gen_rtx_fmt_ee (test_code,
1074 mode,
1075 cmp0, cmp1),
1076 label1, label2)));
1077 }
1078
1079 /* Initialize CUM for a function FNTYPE. */
1080
1081 void
1082 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1083 rtx libname ATTRIBUTE_UNUSED)
1084 {
1085 static CUMULATIVE_ARGS zero_cum;
1086 tree param;
1087 tree next_param;
1088
1089 if (TARGET_DEBUG_D_MODE)
1090 {
1091 fprintf (stderr,
1092 "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype);
1093
1094 if (!fntype)
1095 fputc ('\n', stderr);
1096
1097 else
1098 {
1099 tree ret_type = TREE_TYPE (fntype);
1100
1101 fprintf (stderr, ", fntype code = %s, ret code = %s\n",
1102 tree_code_name[(int)TREE_CODE (fntype)],
1103 tree_code_name[(int)TREE_CODE (ret_type)]);
1104 }
1105 }
1106
1107 *cum = zero_cum;
1108
1109 /* Determine if this function has variable arguments. This is
1110 indicated by the last argument being 'void_type_mode' if there
1111 are no variable arguments. The standard IQ2000 calling sequence
1112 passes all arguments in the general purpose registers in this case. */
1113
1114 for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
1115 param != 0; param = next_param)
1116 {
1117 next_param = TREE_CHAIN (param);
1118 if (next_param == 0 && TREE_VALUE (param) != void_type_node)
1119 cum->gp_reg_found = 1;
1120 }
1121 }
1122
1123 /* Advance the argument of type TYPE and mode MODE to the next argument
1124 position in CUM. */
1125
1126 void
1127 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1128 int named)
1129 {
1130 if (TARGET_DEBUG_D_MODE)
1131 {
1132 fprintf (stderr,
1133 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1134 cum->gp_reg_found, cum->arg_number, cum->arg_words,
1135 GET_MODE_NAME (mode));
1136 fprintf (stderr, "%p", (void *) type);
1137 fprintf (stderr, ", %d )\n\n", named);
1138 }
1139
1140 cum->arg_number++;
1141 switch (mode)
1142 {
1143 case VOIDmode:
1144 break;
1145
1146 default:
1147 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1148 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1149
1150 cum->gp_reg_found = 1;
1151 cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
1152 / UNITS_PER_WORD);
1153 break;
1154
1155 case BLKmode:
1156 cum->gp_reg_found = 1;
1157 cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1158 / UNITS_PER_WORD);
1159 break;
1160
1161 case SFmode:
1162 cum->arg_words ++;
1163 if (! cum->gp_reg_found && cum->arg_number <= 2)
1164 cum->fp_code += 1 << ((cum->arg_number - 1) * 2);
1165 break;
1166
1167 case DFmode:
1168 cum->arg_words += 2;
1169 if (! cum->gp_reg_found && cum->arg_number <= 2)
1170 cum->fp_code += 2 << ((cum->arg_number - 1) * 2);
1171 break;
1172
1173 case DImode:
1174 cum->gp_reg_found = 1;
1175 cum->arg_words += 2;
1176 break;
1177
1178 case QImode:
1179 case HImode:
1180 case SImode:
1181 cum->gp_reg_found = 1;
1182 cum->arg_words ++;
1183 break;
1184 }
1185 }
1186
1187 /* Return an RTL expression containing the register for the given mode MODE
1188 and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */
1189
1190 struct rtx_def *
1191 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, const_tree type,
1192 int named)
1193 {
1194 rtx ret;
1195 int regbase = -1;
1196 int bias = 0;
1197 unsigned int *arg_words = &cum->arg_words;
1198 int struct_p = (type != 0
1199 && (TREE_CODE (type) == RECORD_TYPE
1200 || TREE_CODE (type) == UNION_TYPE
1201 || TREE_CODE (type) == QUAL_UNION_TYPE));
1202
1203 if (TARGET_DEBUG_D_MODE)
1204 {
1205 fprintf (stderr,
1206 "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1207 cum->gp_reg_found, cum->arg_number, cum->arg_words,
1208 GET_MODE_NAME (mode));
1209 fprintf (stderr, "%p", (const void *) type);
1210 fprintf (stderr, ", %d ) = ", named);
1211 }
1212
1213
1214 cum->last_arg_fp = 0;
1215 switch (mode)
1216 {
1217 case SFmode:
1218 regbase = GP_ARG_FIRST;
1219 break;
1220
1221 case DFmode:
1222 cum->arg_words += cum->arg_words & 1;
1223
1224 regbase = GP_ARG_FIRST;
1225 break;
1226
1227 default:
1228 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
1229 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
1230
1231 /* Drops through. */
1232 case BLKmode:
1233 if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)
1234 cum->arg_words += (cum->arg_words & 1);
1235 regbase = GP_ARG_FIRST;
1236 break;
1237
1238 case VOIDmode:
1239 case QImode:
1240 case HImode:
1241 case SImode:
1242 regbase = GP_ARG_FIRST;
1243 break;
1244
1245 case DImode:
1246 cum->arg_words += (cum->arg_words & 1);
1247 regbase = GP_ARG_FIRST;
1248 }
1249
1250 if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS)
1251 {
1252 if (TARGET_DEBUG_D_MODE)
1253 fprintf (stderr, "<stack>%s\n", struct_p ? ", [struct]" : "");
1254
1255 ret = 0;
1256 }
1257 else
1258 {
1259 gcc_assert (regbase != -1);
1260
1261 if (! type || TREE_CODE (type) != RECORD_TYPE
1262 || ! named || ! TYPE_SIZE_UNIT (type)
1263 || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
1264 ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
1265 else
1266 {
1267 tree field;
1268
1269 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
1270 if (TREE_CODE (field) == FIELD_DECL
1271 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
1272 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
1273 && host_integerp (bit_position (field), 0)
1274 && int_bit_position (field) % BITS_PER_WORD == 0)
1275 break;
1276
1277 /* If the whole struct fits a DFmode register,
1278 we don't need the PARALLEL. */
1279 if (! field || mode == DFmode)
1280 ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
1281 else
1282 {
1283 unsigned int chunks;
1284 HOST_WIDE_INT bitpos;
1285 unsigned int regno;
1286 unsigned int i;
1287
1288 /* ??? If this is a packed structure, then the last hunk won't
1289 be 64 bits. */
1290 chunks
1291 = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
1292 if (chunks + *arg_words + bias > (unsigned) MAX_ARGS_IN_REGISTERS)
1293 chunks = MAX_ARGS_IN_REGISTERS - *arg_words - bias;
1294
1295 /* Assign_parms checks the mode of ENTRY_PARM, so we must
1296 use the actual mode here. */
1297 ret = gen_rtx_PARALLEL (mode, rtvec_alloc (chunks));
1298
1299 bitpos = 0;
1300 regno = regbase + *arg_words + bias;
1301 field = TYPE_FIELDS (type);
1302 for (i = 0; i < chunks; i++)
1303 {
1304 rtx reg;
1305
1306 for (; field; field = TREE_CHAIN (field))
1307 if (TREE_CODE (field) == FIELD_DECL
1308 && int_bit_position (field) >= bitpos)
1309 break;
1310
1311 if (field
1312 && int_bit_position (field) == bitpos
1313 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
1314 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
1315 reg = gen_rtx_REG (DFmode, regno++);
1316 else
1317 reg = gen_rtx_REG (word_mode, regno);
1318
1319 XVECEXP (ret, 0, i)
1320 = gen_rtx_EXPR_LIST (VOIDmode, reg,
1321 GEN_INT (bitpos / BITS_PER_UNIT));
1322
1323 bitpos += 64;
1324 regno++;
1325 }
1326 }
1327 }
1328
1329 if (TARGET_DEBUG_D_MODE)
1330 fprintf (stderr, "%s%s\n", reg_names[regbase + *arg_words + bias],
1331 struct_p ? ", [struct]" : "");
1332 }
1333
1334 /* We will be called with a mode of VOIDmode after the last argument
1335 has been seen. Whatever we return will be passed to the call
1336 insn. If we need any shifts for small structures, return them in
1337 a PARALLEL. */
1338 if (mode == VOIDmode)
1339 {
1340 if (cum->num_adjusts > 0)
1341 ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
1342 gen_rtvec_v (cum->num_adjusts, cum->adjust));
1343 }
1344
1345 return ret;
1346 }
1347
1348 static int
1349 iq2000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1350 tree type ATTRIBUTE_UNUSED,
1351 bool named ATTRIBUTE_UNUSED)
1352 {
1353 if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
1354 {
1355 if (TARGET_DEBUG_D_MODE)
1356 fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD);
1357 return UNITS_PER_WORD;
1358 }
1359
1360 return 0;
1361 }
1362
1363 /* Implement va_start. */
1364
1365 static void
1366 iq2000_va_start (tree valist, rtx nextarg)
1367 {
1368 int int_arg_words;
1369 /* Find out how many non-float named formals. */
1370 int gpr_save_area_size;
1371 /* Note UNITS_PER_WORD is 4 bytes. */
1372 int_arg_words = crtl->args.info.arg_words;
1373
1374 if (int_arg_words < 8 )
1375 /* Adjust for the prologue's economy measure. */
1376 gpr_save_area_size = (8 - int_arg_words) * UNITS_PER_WORD;
1377 else
1378 gpr_save_area_size = 0;
1379
1380 /* Everything is in the GPR save area, or in the overflow
1381 area which is contiguous with it. */
1382 nextarg = plus_constant (nextarg, - gpr_save_area_size);
1383 std_expand_builtin_va_start (valist, nextarg);
1384 }
1385
1386 /* Allocate a chunk of memory for per-function machine-dependent data. */
1387
1388 static struct machine_function *
1389 iq2000_init_machine_status (void)
1390 {
1391 struct machine_function *f;
1392
1393 f = GGC_CNEW (struct machine_function);
1394
1395 return f;
1396 }
1397
1398 /* Implement TARGET_HANDLE_OPTION. */
1399
1400 static bool
1401 iq2000_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
1402 {
1403 switch (code)
1404 {
1405 case OPT_mcpu_:
1406 if (strcmp (arg, "iq10") == 0)
1407 iq2000_tune = PROCESSOR_IQ10;
1408 else if (strcmp (arg, "iq2000") == 0)
1409 iq2000_tune = PROCESSOR_IQ2000;
1410 else
1411 return false;
1412 return true;
1413
1414 case OPT_march_:
1415 /* This option has no effect at the moment. */
1416 return (strcmp (arg, "default") == 0
1417 || strcmp (arg, "DEFAULT") == 0
1418 || strcmp (arg, "iq2000") == 0);
1419
1420 default:
1421 return true;
1422 }
1423 }
1424
1425 /* Detect any conflicts in the switches. */
1426
1427 void
1428 override_options (void)
1429 {
1430 target_flags &= ~MASK_GPOPT;
1431
1432 iq2000_isa = IQ2000_ISA_DEFAULT;
1433
1434 /* Identify the processor type. */
1435
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;
1450 iq2000_print_operand_punct['}'] = 1;
1451 iq2000_print_operand_punct['^'] = 1;
1452 iq2000_print_operand_punct['$'] = 1;
1453 iq2000_print_operand_punct['+'] = 1;
1454 iq2000_print_operand_punct['~'] = 1;
1455
1456 /* Save GPR registers in word_mode sized hunks. word_mode hasn't been
1457 initialized yet, so we can't use that here. */
1458 gpr_mode = SImode;
1459
1460 /* Function to allocate machine-dependent function status. */
1461 init_machine_status = iq2000_init_machine_status;
1462 }
1463
1464 /* The arg pointer (which is eliminated) points to the virtual frame pointer,
1465 while the frame pointer (which may be eliminated) points to the stack
1466 pointer after the initial adjustments. */
1467
1468 HOST_WIDE_INT
1469 iq2000_debugger_offset (rtx addr, HOST_WIDE_INT offset)
1470 {
1471 rtx offset2 = const0_rtx;
1472 rtx reg = eliminate_constant_term (addr, & offset2);
1473
1474 if (offset == 0)
1475 offset = INTVAL (offset2);
1476
1477 if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
1478 || reg == hard_frame_pointer_rtx)
1479 {
1480 HOST_WIDE_INT frame_size = (!cfun->machine->initialized)
1481 ? compute_frame_size (get_frame_size ())
1482 : cfun->machine->total_size;
1483
1484 offset = offset - frame_size;
1485 }
1486
1487 return offset;
1488 }
1489
1490 /* If defined, a C statement to be executed just prior to the output of
1491 assembler code for INSN, to modify the extracted operands so they will be
1492 output differently.
1493
1494 Here the argument OPVEC is the vector containing the operands extracted
1495 from INSN, and NOPERANDS is the number of elements of the vector which
1496 contain meaningful data for this insn. The contents of this vector are
1497 what will be used to convert the insn template into assembler code, so you
1498 can change the assembler output by changing the contents of the vector.
1499
1500 We use it to check if the current insn needs a nop in front of it because
1501 of load delays, and also to update the delay slot statistics. */
1502
1503 void
1504 final_prescan_insn (rtx insn, rtx opvec[] ATTRIBUTE_UNUSED,
1505 int noperands ATTRIBUTE_UNUSED)
1506 {
1507 if (dslots_number_nops > 0)
1508 {
1509 rtx pattern = PATTERN (insn);
1510 int length = get_attr_length (insn);
1511
1512 /* Do we need to emit a NOP? */
1513 if (length == 0
1514 || (iq2000_load_reg != 0 && reg_mentioned_p (iq2000_load_reg, pattern))
1515 || (iq2000_load_reg2 != 0 && reg_mentioned_p (iq2000_load_reg2, pattern))
1516 || (iq2000_load_reg3 != 0 && reg_mentioned_p (iq2000_load_reg3, pattern))
1517 || (iq2000_load_reg4 != 0
1518 && reg_mentioned_p (iq2000_load_reg4, pattern)))
1519 fputs ("\tnop\n", asm_out_file);
1520
1521 else
1522 dslots_load_filled ++;
1523
1524 while (--dslots_number_nops > 0)
1525 fputs ("\tnop\n", asm_out_file);
1526
1527 iq2000_load_reg = 0;
1528 iq2000_load_reg2 = 0;
1529 iq2000_load_reg3 = 0;
1530 iq2000_load_reg4 = 0;
1531 }
1532
1533 if ( (GET_CODE (insn) == JUMP_INSN
1534 || GET_CODE (insn) == CALL_INSN
1535 || (GET_CODE (PATTERN (insn)) == RETURN))
1536 && NEXT_INSN (PREV_INSN (insn)) == insn)
1537 {
1538 rtx nop_insn = emit_insn_after (gen_nop (), insn);
1539
1540 INSN_ADDRESSES_NEW (nop_insn, -1);
1541 }
1542
1543 if (TARGET_STATS
1544 && (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN))
1545 dslots_jump_total ++;
1546 }
1547
1548 /* Return the bytes needed to compute the frame pointer from the current
1549 stack pointer where SIZE is the # of var. bytes allocated.
1550
1551 IQ2000 stack frames look like:
1552
1553 Before call After call
1554 +-----------------------+ +-----------------------+
1555 high | | | |
1556 mem. | | | |
1557 | caller's temps. | | caller's temps. |
1558 | | | |
1559 +-----------------------+ +-----------------------+
1560 | | | |
1561 | arguments on stack. | | arguments on stack. |
1562 | | | |
1563 +-----------------------+ +-----------------------+
1564 | 4 words to save | | 4 words to save |
1565 | arguments passed | | arguments passed |
1566 | in registers, even | | in registers, even |
1567 SP->| if not passed. | VFP->| if not passed. |
1568 +-----------------------+ +-----------------------+
1569 | |
1570 | fp register save |
1571 | |
1572 +-----------------------+
1573 | |
1574 | gp register save |
1575 | |
1576 +-----------------------+
1577 | |
1578 | local variables |
1579 | |
1580 +-----------------------+
1581 | |
1582 | alloca allocations |
1583 | |
1584 +-----------------------+
1585 | |
1586 | GP save for V.4 abi |
1587 | |
1588 +-----------------------+
1589 | |
1590 | arguments on stack |
1591 | |
1592 +-----------------------+
1593 | 4 words to save |
1594 | arguments passed |
1595 | in registers, even |
1596 low SP->| if not passed. |
1597 memory +-----------------------+ */
1598
1599 HOST_WIDE_INT
1600 compute_frame_size (HOST_WIDE_INT size)
1601 {
1602 int regno;
1603 HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
1604 HOST_WIDE_INT var_size; /* # bytes that variables take up. */
1605 HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up. */
1606 HOST_WIDE_INT extra_size; /* # extra bytes. */
1607 HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding. */
1608 HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs. */
1609 HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs. */
1610 long mask; /* mask of saved gp registers. */
1611 int fp_inc; /* 1 or 2 depending on the size of fp regs. */
1612 long fp_bits; /* bitmask to use for each fp register. */
1613
1614 gp_reg_size = 0;
1615 fp_reg_size = 0;
1616 mask = 0;
1617 extra_size = IQ2000_STACK_ALIGN ((0));
1618 var_size = IQ2000_STACK_ALIGN (size);
1619 args_size = IQ2000_STACK_ALIGN (crtl->outgoing_args_size);
1620
1621 /* If a function dynamically allocates the stack and
1622 has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space. */
1623 if (args_size == 0 && cfun->calls_alloca)
1624 args_size = 4 * UNITS_PER_WORD;
1625
1626 total_size = var_size + args_size + extra_size;
1627
1628 /* Calculate space needed for gp registers. */
1629 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
1630 {
1631 if (MUST_SAVE_REGISTER (regno))
1632 {
1633 gp_reg_size += GET_MODE_SIZE (gpr_mode);
1634 mask |= 1L << (regno - GP_REG_FIRST);
1635 }
1636 }
1637
1638 /* We need to restore these for the handler. */
1639 if (crtl->calls_eh_return)
1640 {
1641 unsigned int i;
1642
1643 for (i = 0; ; ++i)
1644 {
1645 regno = EH_RETURN_DATA_REGNO (i);
1646 if (regno == (int) INVALID_REGNUM)
1647 break;
1648 gp_reg_size += GET_MODE_SIZE (gpr_mode);
1649 mask |= 1L << (regno - GP_REG_FIRST);
1650 }
1651 }
1652
1653 fp_inc = 2;
1654 fp_bits = 3;
1655 gp_reg_rounded = IQ2000_STACK_ALIGN (gp_reg_size);
1656 total_size += gp_reg_rounded + IQ2000_STACK_ALIGN (fp_reg_size);
1657
1658 /* The gp reg is caller saved, so there is no need for leaf routines
1659 (total_size == extra_size) to save the gp reg. */
1660 if (total_size == extra_size
1661 && ! profile_flag)
1662 total_size = extra_size = 0;
1663
1664 total_size += IQ2000_STACK_ALIGN (crtl->args.pretend_args_size);
1665
1666 /* Save other computed information. */
1667 cfun->machine->total_size = total_size;
1668 cfun->machine->var_size = var_size;
1669 cfun->machine->args_size = args_size;
1670 cfun->machine->extra_size = extra_size;
1671 cfun->machine->gp_reg_size = gp_reg_size;
1672 cfun->machine->fp_reg_size = fp_reg_size;
1673 cfun->machine->mask = mask;
1674 cfun->machine->initialized = reload_completed;
1675 cfun->machine->num_gp = gp_reg_size / UNITS_PER_WORD;
1676
1677 if (mask)
1678 {
1679 unsigned long offset;
1680
1681 offset = (args_size + extra_size + var_size
1682 + gp_reg_size - GET_MODE_SIZE (gpr_mode));
1683
1684 cfun->machine->gp_sp_offset = offset;
1685 cfun->machine->gp_save_offset = offset - total_size;
1686 }
1687 else
1688 {
1689 cfun->machine->gp_sp_offset = 0;
1690 cfun->machine->gp_save_offset = 0;
1691 }
1692
1693 cfun->machine->fp_sp_offset = 0;
1694 cfun->machine->fp_save_offset = 0;
1695
1696 /* Ok, we're done. */
1697 return total_size;
1698 }
1699
1700 /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
1701 pointer, argument pointer, or return address pointer. TO is either
1702 the stack pointer or hard frame pointer. */
1703
1704 int
1705 iq2000_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
1706 {
1707 int offset;
1708
1709 compute_frame_size (get_frame_size ());
1710 if ((from) == FRAME_POINTER_REGNUM)
1711 (offset) = 0;
1712 else if ((from) == ARG_POINTER_REGNUM)
1713 (offset) = (cfun->machine->total_size);
1714 else if ((from) == RETURN_ADDRESS_POINTER_REGNUM)
1715 {
1716 if (leaf_function_p ())
1717 (offset) = 0;
1718 else (offset) = cfun->machine->gp_sp_offset
1719 + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT))
1720 * (BYTES_BIG_ENDIAN != 0));
1721 }
1722
1723 return offset;
1724 }
1725
1726 /* Common code to emit the insns (or to write the instructions to a file)
1727 to save/restore registers.
1728 Other parts of the code assume that IQ2000_TEMP1_REGNUM (aka large_reg)
1729 is not modified within save_restore_insns. */
1730
1731 #define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
1732
1733 /* Emit instructions to load the value (SP + OFFSET) into IQ2000_TEMP2_REGNUM
1734 and return an rtl expression for the register. Write the assembly
1735 instructions directly to FILE if it is not null, otherwise emit them as
1736 rtl.
1737
1738 This function is a subroutine of save_restore_insns. It is used when
1739 OFFSET is too large to add in a single instruction. */
1740
1741 static rtx
1742 iq2000_add_large_offset_to_sp (HOST_WIDE_INT offset)
1743 {
1744 rtx reg = gen_rtx_REG (Pmode, IQ2000_TEMP2_REGNUM);
1745 rtx offset_rtx = GEN_INT (offset);
1746
1747 emit_move_insn (reg, offset_rtx);
1748 emit_insn (gen_addsi3 (reg, reg, stack_pointer_rtx));
1749 return reg;
1750 }
1751
1752 /* Make INSN frame related and note that it performs the frame-related
1753 operation DWARF_PATTERN. */
1754
1755 static void
1756 iq2000_annotate_frame_insn (rtx insn, rtx dwarf_pattern)
1757 {
1758 RTX_FRAME_RELATED_P (insn) = 1;
1759 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1760 dwarf_pattern,
1761 REG_NOTES (insn));
1762 }
1763
1764 /* Emit a move instruction that stores REG in MEM. Make the instruction
1765 frame related and note that it stores REG at (SP + OFFSET). */
1766
1767 static void
1768 iq2000_emit_frame_related_store (rtx mem, rtx reg, HOST_WIDE_INT offset)
1769 {
1770 rtx dwarf_address = plus_constant (stack_pointer_rtx, offset);
1771 rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address);
1772
1773 iq2000_annotate_frame_insn (emit_move_insn (mem, reg),
1774 gen_rtx_SET (GET_MODE (reg), dwarf_mem, reg));
1775 }
1776
1777 /* Emit instructions to save/restore registers, as determined by STORE_P. */
1778
1779 static void
1780 save_restore_insns (int store_p)
1781 {
1782 long mask = cfun->machine->mask;
1783 int regno;
1784 rtx base_reg_rtx;
1785 HOST_WIDE_INT base_offset;
1786 HOST_WIDE_INT gp_offset;
1787 HOST_WIDE_INT end_offset;
1788
1789 gcc_assert (!frame_pointer_needed
1790 || BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST));
1791
1792 if (mask == 0)
1793 {
1794 base_reg_rtx = 0, base_offset = 0;
1795 return;
1796 }
1797
1798 /* Save registers starting from high to low. The debuggers prefer at least
1799 the return register be stored at func+4, and also it allows us not to
1800 need a nop in the epilog if at least one register is reloaded in
1801 addition to return address. */
1802
1803 /* Save GP registers if needed. */
1804 /* Pick which pointer to use as a base register. For small frames, just
1805 use the stack pointer. Otherwise, use a temporary register. Save 2
1806 cycles if the save area is near the end of a large frame, by reusing
1807 the constant created in the prologue/epilogue to adjust the stack
1808 frame. */
1809
1810 gp_offset = cfun->machine->gp_sp_offset;
1811 end_offset
1812 = gp_offset - (cfun->machine->gp_reg_size
1813 - GET_MODE_SIZE (gpr_mode));
1814
1815 if (gp_offset < 0 || end_offset < 0)
1816 internal_error
1817 ("gp_offset (%ld) or end_offset (%ld) is less than zero",
1818 (long) gp_offset, (long) end_offset);
1819
1820 else if (gp_offset < 32768)
1821 base_reg_rtx = stack_pointer_rtx, base_offset = 0;
1822 else
1823 {
1824 int regno;
1825 int reg_save_count = 0;
1826
1827 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
1828 if (BITSET_P (mask, regno - GP_REG_FIRST)) reg_save_count += 1;
1829 base_offset = gp_offset - ((reg_save_count - 1) * 4);
1830 base_reg_rtx = iq2000_add_large_offset_to_sp (base_offset);
1831 }
1832
1833 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
1834 {
1835 if (BITSET_P (mask, regno - GP_REG_FIRST))
1836 {
1837 rtx reg_rtx;
1838 rtx mem_rtx
1839 = gen_rtx_MEM (gpr_mode,
1840 gen_rtx_PLUS (Pmode, base_reg_rtx,
1841 GEN_INT (gp_offset - base_offset)));
1842
1843 reg_rtx = gen_rtx_REG (gpr_mode, regno);
1844
1845 if (store_p)
1846 iq2000_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
1847 else
1848 {
1849 emit_move_insn (reg_rtx, mem_rtx);
1850 }
1851 gp_offset -= GET_MODE_SIZE (gpr_mode);
1852 }
1853 }
1854 }
1855
1856 /* Expand the prologue into a bunch of separate insns. */
1857
1858 void
1859 iq2000_expand_prologue (void)
1860 {
1861 int regno;
1862 HOST_WIDE_INT tsize;
1863 int last_arg_is_vararg_marker = 0;
1864 tree fndecl = current_function_decl;
1865 tree fntype = TREE_TYPE (fndecl);
1866 tree fnargs = DECL_ARGUMENTS (fndecl);
1867 rtx next_arg_reg;
1868 int i;
1869 tree next_arg;
1870 tree cur_arg;
1871 CUMULATIVE_ARGS args_so_far;
1872 int store_args_on_stack = (iq2000_can_use_return_insn ());
1873
1874 /* If struct value address is treated as the first argument. */
1875 if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
1876 && !cfun->returns_pcc_struct
1877 && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
1878 {
1879 tree type = build_pointer_type (fntype);
1880 tree function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
1881
1882 DECL_ARG_TYPE (function_result_decl) = type;
1883 TREE_CHAIN (function_result_decl) = fnargs;
1884 fnargs = function_result_decl;
1885 }
1886
1887 /* For arguments passed in registers, find the register number
1888 of the first argument in the variable part of the argument list,
1889 otherwise GP_ARG_LAST+1. Note also if the last argument is
1890 the varargs special argument, and treat it as part of the
1891 variable arguments.
1892
1893 This is only needed if store_args_on_stack is true. */
1894 INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0, 0);
1895 regno = GP_ARG_FIRST;
1896
1897 for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
1898 {
1899 tree passed_type = DECL_ARG_TYPE (cur_arg);
1900 enum machine_mode passed_mode = TYPE_MODE (passed_type);
1901 rtx entry_parm;
1902
1903 if (TREE_ADDRESSABLE (passed_type))
1904 {
1905 passed_type = build_pointer_type (passed_type);
1906 passed_mode = Pmode;
1907 }
1908
1909 entry_parm = FUNCTION_ARG (args_so_far, passed_mode, passed_type, 1);
1910
1911 FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, passed_type, 1);
1912 next_arg = TREE_CHAIN (cur_arg);
1913
1914 if (entry_parm && store_args_on_stack)
1915 {
1916 if (next_arg == 0
1917 && DECL_NAME (cur_arg)
1918 && ((0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)),
1919 "__builtin_va_alist"))
1920 || (0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)),
1921 "va_alist"))))
1922 {
1923 last_arg_is_vararg_marker = 1;
1924 break;
1925 }
1926 else
1927 {
1928 int words;
1929
1930 gcc_assert (GET_CODE (entry_parm) == REG);
1931
1932 /* Passed in a register, so will get homed automatically. */
1933 if (GET_MODE (entry_parm) == BLKmode)
1934 words = (int_size_in_bytes (passed_type) + 3) / 4;
1935 else
1936 words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
1937
1938 regno = REGNO (entry_parm) + words - 1;
1939 }
1940 }
1941 else
1942 {
1943 regno = GP_ARG_LAST+1;
1944 break;
1945 }
1946 }
1947
1948 /* In order to pass small structures by value in registers we need to
1949 shift the value into the high part of the register.
1950 Function_arg has encoded a PARALLEL rtx, holding a vector of
1951 adjustments to be made as the next_arg_reg variable, so we split up the
1952 insns, and emit them separately. */
1953 next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
1954 if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
1955 {
1956 rtvec adjust = XVEC (next_arg_reg, 0);
1957 int num = GET_NUM_ELEM (adjust);
1958
1959 for (i = 0; i < num; i++)
1960 {
1961 rtx insn, pattern;
1962
1963 pattern = RTVEC_ELT (adjust, i);
1964 if (GET_CODE (pattern) != SET
1965 || GET_CODE (SET_SRC (pattern)) != ASHIFT)
1966 abort_with_insn (pattern, "Insn is not a shift");
1967 PUT_CODE (SET_SRC (pattern), ASHIFTRT);
1968
1969 insn = emit_insn (pattern);
1970 }
1971 }
1972
1973 tsize = compute_frame_size (get_frame_size ());
1974
1975 /* If this function is a varargs function, store any registers that
1976 would normally hold arguments ($4 - $7) on the stack. */
1977 if (store_args_on_stack
1978 && ((TYPE_ARG_TYPES (fntype) != 0
1979 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1980 != void_type_node))
1981 || last_arg_is_vararg_marker))
1982 {
1983 int offset = (regno - GP_ARG_FIRST) * UNITS_PER_WORD;
1984 rtx ptr = stack_pointer_rtx;
1985
1986 for (; regno <= GP_ARG_LAST; regno++)
1987 {
1988 if (offset != 0)
1989 ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
1990 emit_move_insn (gen_rtx_MEM (gpr_mode, ptr),
1991 gen_rtx_REG (gpr_mode, regno));
1992
1993 offset += GET_MODE_SIZE (gpr_mode);
1994 }
1995 }
1996
1997 if (tsize > 0)
1998 {
1999 rtx tsize_rtx = GEN_INT (tsize);
2000 rtx adjustment_rtx, insn, dwarf_pattern;
2001
2002 if (tsize > 32767)
2003 {
2004 adjustment_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
2005 emit_move_insn (adjustment_rtx, tsize_rtx);
2006 }
2007 else
2008 adjustment_rtx = tsize_rtx;
2009
2010 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
2011 adjustment_rtx));
2012
2013 dwarf_pattern = gen_rtx_SET (Pmode, stack_pointer_rtx,
2014 plus_constant (stack_pointer_rtx, -tsize));
2015
2016 iq2000_annotate_frame_insn (insn, dwarf_pattern);
2017
2018 save_restore_insns (1);
2019
2020 if (frame_pointer_needed)
2021 {
2022 rtx insn = 0;
2023
2024 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2025 stack_pointer_rtx));
2026
2027 if (insn)
2028 RTX_FRAME_RELATED_P (insn) = 1;
2029 }
2030 }
2031
2032 emit_insn (gen_blockage ());
2033 }
2034
2035 /* Expand the epilogue into a bunch of separate insns. */
2036
2037 void
2038 iq2000_expand_epilogue (void)
2039 {
2040 HOST_WIDE_INT tsize = cfun->machine->total_size;
2041 rtx tsize_rtx = GEN_INT (tsize);
2042 rtx tmp_rtx = (rtx)0;
2043
2044 if (iq2000_can_use_return_insn ())
2045 {
2046 emit_jump_insn (gen_return ());
2047 return;
2048 }
2049
2050 if (tsize > 32767)
2051 {
2052 tmp_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
2053 emit_move_insn (tmp_rtx, tsize_rtx);
2054 tsize_rtx = tmp_rtx;
2055 }
2056
2057 if (tsize > 0)
2058 {
2059 if (frame_pointer_needed)
2060 {
2061 emit_insn (gen_blockage ());
2062
2063 emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
2064 }
2065
2066 save_restore_insns (0);
2067
2068 if (crtl->calls_eh_return)
2069 {
2070 rtx eh_ofs = EH_RETURN_STACKADJ_RTX;
2071 emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx));
2072 tsize_rtx = eh_ofs;
2073 }
2074
2075 emit_insn (gen_blockage ());
2076
2077 if (tsize != 0 || crtl->calls_eh_return)
2078 {
2079 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2080 tsize_rtx));
2081 }
2082 }
2083
2084 if (crtl->calls_eh_return)
2085 {
2086 /* Perform the additional bump for __throw. */
2087 emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
2088 stack_pointer_rtx);
2089 emit_use (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM));
2090 emit_jump_insn (gen_eh_return_internal ());
2091 }
2092 else
2093 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
2094 GP_REG_FIRST + 31)));
2095 }
2096
2097 void
2098 iq2000_expand_eh_return (rtx address)
2099 {
2100 HOST_WIDE_INT gp_offset = cfun->machine->gp_sp_offset;
2101 rtx scratch;
2102
2103 scratch = plus_constant (stack_pointer_rtx, gp_offset);
2104 emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address);
2105 }
2106
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
2109 was created. */
2110
2111 int
2112 iq2000_can_use_return_insn (void)
2113 {
2114 if (! reload_completed)
2115 return 0;
2116
2117 if (df_regs_ever_live_p (31) || profile_flag)
2118 return 0;
2119
2120 if (cfun->machine->initialized)
2121 return cfun->machine->total_size == 0;
2122
2123 return compute_frame_size (get_frame_size ()) == 0;
2124 }
2125
2126 /* Returns nonzero if X contains a SYMBOL_REF. */
2127
2128 static int
2129 symbolic_expression_p (rtx x)
2130 {
2131 if (GET_CODE (x) == SYMBOL_REF)
2132 return 1;
2133
2134 if (GET_CODE (x) == CONST)
2135 return symbolic_expression_p (XEXP (x, 0));
2136
2137 if (UNARY_P (x))
2138 return symbolic_expression_p (XEXP (x, 0));
2139
2140 if (ARITHMETIC_P (x))
2141 return (symbolic_expression_p (XEXP (x, 0))
2142 || symbolic_expression_p (XEXP (x, 1)));
2143
2144 return 0;
2145 }
2146
2147 /* Choose the section to use for the constant rtx expression X that has
2148 mode MODE. */
2149
2150 static section *
2151 iq2000_select_rtx_section (enum machine_mode mode, rtx x ATTRIBUTE_UNUSED,
2152 unsigned HOST_WIDE_INT align)
2153 {
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);
2157 }
2158
2159 /* Choose the section to use for DECL. RELOC is true if its value contains
2160 any relocatable expression.
2161
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. */
2165
2166 static section *
2167 iq2000_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
2168 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
2169 {
2170 if (TARGET_EMBEDDED_DATA)
2171 {
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;
2182 else
2183 return data_section;
2184 }
2185 else
2186 {
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;
2197 else
2198 return data_section;
2199 }
2200 }
2201 /* Return register to use for a function return value with VALTYPE for function
2202 FUNC. */
2203
2204 rtx
2205 iq2000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
2206 {
2207 int reg = GP_RETURN;
2208 enum machine_mode mode = TYPE_MODE (valtype);
2209 int unsignedp = TYPE_UNSIGNED (valtype);
2210
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);
2214
2215 return gen_rtx_REG (mode, reg);
2216 }
2217
2218 /* Return true when an argument must be passed by reference. */
2219
2220 static bool
2221 iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
2222 const_tree type, bool named ATTRIBUTE_UNUSED)
2223 {
2224 int size;
2225
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))
2230 {
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;
2235
2236 temp = *cum;
2237 if (FUNCTION_ARG (temp, mode, type, named) != 0)
2238 return 1;
2239 }
2240
2241 if (type == NULL_TREE || mode == DImode || mode == DFmode)
2242 return 0;
2243
2244 size = int_size_in_bytes (type);
2245 return size == -1 || size > UNITS_PER_WORD;
2246 }
2247
2248 /* Return the length of INSN. LENGTH is the initial length computed by
2249 attributes in the machine-description file. */
2250
2251 int
2252 iq2000_adjust_insn_length (rtx insn, int length)
2253 {
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)))
2259 length += 4;
2260
2261 return length;
2262 }
2263
2264 /* Output assembly instructions to perform a conditional branch.
2265
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
2270 second operand.
2271
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.
2274
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. */
2278
2279 char *
2280 iq2000_output_conditional_branch (rtx insn, rtx * operands, int two_operands_p,
2281 int float_p, int inverted_p, int length)
2282 {
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. */
2288 int need_z_p;
2289 /* A string to use in the assembly output to represent the first
2290 operand. */
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
2294 operand. */
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");
2300
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));
2304
2305 if (!two_operands_p)
2306 {
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. */
2313 switch (code)
2314 {
2315 case GTU:
2316 code = NE;
2317 break;
2318
2319 case LEU:
2320 code = EQ;
2321 break;
2322
2323 case GEU:
2324 /* A condition which will always be true. */
2325 code = EQ;
2326 op1 = "%.";
2327 break;
2328
2329 case LTU:
2330 /* A condition which will always be false. */
2331 code = NE;
2332 op1 = "%.";
2333 break;
2334
2335 default:
2336 /* Not a special case. */
2337 break;
2338 }
2339 }
2340
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
2346 explicitly. */
2347 if (need_z_p)
2348 op2 = "";
2349
2350 /* Begin by terminating the buffer. That way we can always use
2351 strcat to add to it. */
2352 buffer[0] = '\0';
2353
2354 switch (length)
2355 {
2356 case 4:
2357 case 8:
2358 /* Just a simple conditional branch. */
2359 if (float_p)
2360 sprintf (buffer, "b%s%%?\t%%Z2%%1",
2361 inverted_p ? inverted_comp : comp);
2362 else
2363 sprintf (buffer, "b%s%s%%?\t%s%s,%%1",
2364 inverted_p ? inverted_comp : comp,
2365 need_z_p ? "z" : "",
2366 op1,
2367 op2);
2368 return buffer;
2369
2370 case 12:
2371 case 16:
2372 {
2373 /* Generate a reversed conditional branch around ` j'
2374 instruction:
2375
2376 .set noreorder
2377 .set nomacro
2378 bc l
2379 nop
2380 j target
2381 .set macro
2382 .set reorder
2383 l:
2384
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.)
2393
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. */
2397
2398 const char *target
2399 = ((iq2000_branch_likely || length == 16) ? ".+16" : ".+12");
2400 char *c;
2401
2402 c = strchr (buffer, '\0');
2403 /* Generate the reversed comparison. This takes four
2404 bytes. */
2405 if (float_p)
2406 sprintf (c, "b%s\t%%Z2%s",
2407 inverted_p ? comp : inverted_comp,
2408 target);
2409 else
2410 sprintf (c, "b%s%s\t%s%s,%s",
2411 inverted_p ? comp : inverted_comp,
2412 need_z_p ? "z" : "",
2413 op1,
2414 op2,
2415 target);
2416 strcat (c, "\n\tnop\n\tj\t%1");
2417 if (length == 16)
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");
2422 return buffer;
2423 }
2424
2425 default:
2426 gcc_unreachable ();
2427 }
2428
2429 /* NOTREACHED */
2430 return 0;
2431 }
2432
2433 #define def_builtin(NAME, TYPE, CODE) \
2434 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
2435 NULL, NULL_TREE)
2436
2437 static void
2438 iq2000_init_builtins (void)
2439 {
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;
2445
2446 /* func () */
2447 void_ftype
2448 = build_function_type (void_type_node,
2449 tree_cons (NULL_TREE, void_type_node, endlink));
2450
2451 /* func (int) */
2452 void_ftype_int
2453 = build_function_type (void_type_node,
2454 tree_cons (NULL_TREE, integer_type_node, endlink));
2455
2456 /* void func (int, int) */
2457 void_ftype_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,
2461 endlink)));
2462
2463 /* int func (int) */
2464 int_ftype_int
2465 = build_function_type (integer_type_node,
2466 tree_cons (NULL_TREE, integer_type_node, endlink));
2467
2468 /* int func (int, int) */
2469 int_ftype_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,
2473 endlink)));
2474
2475 /* void func (int, int, int) */
2476 void_ftype_int_int_int
2477 = build_function_type
2478 (void_type_node,
2479 tree_cons (NULL_TREE, integer_type_node,
2480 tree_cons (NULL_TREE, integer_type_node,
2481 tree_cons (NULL_TREE,
2482 integer_type_node,
2483 endlink))));
2484
2485 /* int func (int, int, int, int) */
2486 int_ftype_int_int_int_int
2487 = build_function_type
2488 (integer_type_node,
2489 tree_cons (NULL_TREE, integer_type_node,
2490 tree_cons (NULL_TREE, integer_type_node,
2491 tree_cons (NULL_TREE,
2492 integer_type_node,
2493 tree_cons (NULL_TREE,
2494 integer_type_node,
2495 endlink)))));
2496
2497 /* int func (int, int, int) */
2498 int_ftype_int_int_int
2499 = build_function_type
2500 (integer_type_node,
2501 tree_cons (NULL_TREE, integer_type_node,
2502 tree_cons (NULL_TREE, integer_type_node,
2503 tree_cons (NULL_TREE,
2504 integer_type_node,
2505 endlink))));
2506
2507 /* int func (int, int, int, int) */
2508 int_ftype_int_int_int_int
2509 = build_function_type
2510 (integer_type_node,
2511 tree_cons (NULL_TREE, integer_type_node,
2512 tree_cons (NULL_TREE, integer_type_node,
2513 tree_cons (NULL_TREE,
2514 integer_type_node,
2515 tree_cons (NULL_TREE,
2516 integer_type_node,
2517 endlink)))));
2518
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);
2565 }
2566
2567 /* Builtin for ICODE having ARGCOUNT args in EXP where each arg
2568 has an rtx CODE. */
2569
2570 static rtx
2571 expand_one_builtin (enum insn_code icode, rtx target, tree exp,
2572 enum rtx_code *code, int argcount)
2573 {
2574 rtx pat;
2575 tree arg [5];
2576 rtx op [5];
2577 enum machine_mode mode [5];
2578 int i;
2579
2580 mode[0] = insn_data[icode].operand[0].mode;
2581 for (i = 0; i < argcount; i++)
2582 {
2583 arg[i] = CALL_EXPR_ARG (exp, i);
2584 op[i] = expand_expr (arg[i], NULL_RTX, VOIDmode, 0);
2585 mode[i] = insn_data[icode].operand[i].mode;
2586 if (code[i] == CONST_INT && GET_CODE (op[i]) != CONST_INT)
2587 error ("argument %qd is not a constant", i + 1);
2588 if (code[i] == REG
2589 && ! (*insn_data[icode].operand[i].predicate) (op[i], mode[i]))
2590 op[i] = copy_to_mode_reg (mode[i], op[i]);
2591 }
2592
2593 if (insn_data[icode].operand[0].constraint[0] == '=')
2594 {
2595 if (target == 0
2596 || GET_MODE (target) != mode[0]
2597 || ! (*insn_data[icode].operand[0].predicate) (target, mode[0]))
2598 target = gen_reg_rtx (mode[0]);
2599 }
2600 else
2601 target = 0;
2602
2603 switch (argcount)
2604 {
2605 case 0:
2606 pat = GEN_FCN (icode) (target);
2607 case 1:
2608 if (target)
2609 pat = GEN_FCN (icode) (target, op[0]);
2610 else
2611 pat = GEN_FCN (icode) (op[0]);
2612 break;
2613 case 2:
2614 if (target)
2615 pat = GEN_FCN (icode) (target, op[0], op[1]);
2616 else
2617 pat = GEN_FCN (icode) (op[0], op[1]);
2618 break;
2619 case 3:
2620 if (target)
2621 pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
2622 else
2623 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
2624 break;
2625 case 4:
2626 if (target)
2627 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
2628 else
2629 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
2630 break;
2631 default:
2632 gcc_unreachable ();
2633 }
2634
2635 if (! pat)
2636 return 0;
2637 emit_insn (pat);
2638 return target;
2639 }
2640
2641 /* Expand an expression EXP that calls a built-in function,
2642 with result going to TARGET if that's convenient
2643 (and in mode MODE if that's convenient).
2644 SUBTARGET may be used as the target for computing one of EXP's operands.
2645 IGNORE is nonzero if the value is to be ignored. */
2646
2647 static rtx
2648 iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
2649 enum machine_mode mode ATTRIBUTE_UNUSED,
2650 int ignore ATTRIBUTE_UNUSED)
2651 {
2652 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2653 int fcode = DECL_FUNCTION_CODE (fndecl);
2654 enum rtx_code code [5];
2655
2656 code[0] = REG;
2657 code[1] = REG;
2658 code[2] = REG;
2659 code[3] = REG;
2660 code[4] = REG;
2661 switch (fcode)
2662 {
2663 default:
2664 break;
2665
2666 case IQ2000_BUILTIN_ADO16:
2667 return expand_one_builtin (CODE_FOR_ado16, target, exp, code, 2);
2668
2669 case IQ2000_BUILTIN_RAM:
2670 code[1] = CONST_INT;
2671 code[2] = CONST_INT;
2672 code[3] = CONST_INT;
2673 return expand_one_builtin (CODE_FOR_ram, target, exp, code, 4);
2674
2675 case IQ2000_BUILTIN_CHKHDR:
2676 return expand_one_builtin (CODE_FOR_chkhdr, target, exp, code, 2);
2677
2678 case IQ2000_BUILTIN_PKRL:
2679 return expand_one_builtin (CODE_FOR_pkrl, target, exp, code, 2);
2680
2681 case IQ2000_BUILTIN_CFC0:
2682 code[0] = CONST_INT;
2683 return expand_one_builtin (CODE_FOR_cfc0, target, exp, code, 1);
2684
2685 case IQ2000_BUILTIN_CFC1:
2686 code[0] = CONST_INT;
2687 return expand_one_builtin (CODE_FOR_cfc1, target, exp, code, 1);
2688
2689 case IQ2000_BUILTIN_CFC2:
2690 code[0] = CONST_INT;
2691 return expand_one_builtin (CODE_FOR_cfc2, target, exp, code, 1);
2692
2693 case IQ2000_BUILTIN_CFC3:
2694 code[0] = CONST_INT;
2695 return expand_one_builtin (CODE_FOR_cfc3, target, exp, code, 1);
2696
2697 case IQ2000_BUILTIN_CTC0:
2698 code[1] = CONST_INT;
2699 return expand_one_builtin (CODE_FOR_ctc0, target, exp, code, 2);
2700
2701 case IQ2000_BUILTIN_CTC1:
2702 code[1] = CONST_INT;
2703 return expand_one_builtin (CODE_FOR_ctc1, target, exp, code, 2);
2704
2705 case IQ2000_BUILTIN_CTC2:
2706 code[1] = CONST_INT;
2707 return expand_one_builtin (CODE_FOR_ctc2, target, exp, code, 2);
2708
2709 case IQ2000_BUILTIN_CTC3:
2710 code[1] = CONST_INT;
2711 return expand_one_builtin (CODE_FOR_ctc3, target, exp, code, 2);
2712
2713 case IQ2000_BUILTIN_MFC0:
2714 code[0] = CONST_INT;
2715 return expand_one_builtin (CODE_FOR_mfc0, target, exp, code, 1);
2716
2717 case IQ2000_BUILTIN_MFC1:
2718 code[0] = CONST_INT;
2719 return expand_one_builtin (CODE_FOR_mfc1, target, exp, code, 1);
2720
2721 case IQ2000_BUILTIN_MFC2:
2722 code[0] = CONST_INT;
2723 return expand_one_builtin (CODE_FOR_mfc2, target, exp, code, 1);
2724
2725 case IQ2000_BUILTIN_MFC3:
2726 code[0] = CONST_INT;
2727 return expand_one_builtin (CODE_FOR_mfc3, target, exp, code, 1);
2728
2729 case IQ2000_BUILTIN_MTC0:
2730 code[1] = CONST_INT;
2731 return expand_one_builtin (CODE_FOR_mtc0, target, exp, code, 2);
2732
2733 case IQ2000_BUILTIN_MTC1:
2734 code[1] = CONST_INT;
2735 return expand_one_builtin (CODE_FOR_mtc1, target, exp, code, 2);
2736
2737 case IQ2000_BUILTIN_MTC2:
2738 code[1] = CONST_INT;
2739 return expand_one_builtin (CODE_FOR_mtc2, target, exp, code, 2);
2740
2741 case IQ2000_BUILTIN_MTC3:
2742 code[1] = CONST_INT;
2743 return expand_one_builtin (CODE_FOR_mtc3, target, exp, code, 2);
2744
2745 case IQ2000_BUILTIN_LUR:
2746 return expand_one_builtin (CODE_FOR_lur, target, exp, code, 2);
2747
2748 case IQ2000_BUILTIN_RB:
2749 return expand_one_builtin (CODE_FOR_rb, target, exp, code, 2);
2750
2751 case IQ2000_BUILTIN_RX:
2752 return expand_one_builtin (CODE_FOR_rx, target, exp, code, 2);
2753
2754 case IQ2000_BUILTIN_SRRD:
2755 return expand_one_builtin (CODE_FOR_srrd, target, exp, code, 1);
2756
2757 case IQ2000_BUILTIN_SRWR:
2758 return expand_one_builtin (CODE_FOR_srwr, target, exp, code, 2);
2759
2760 case IQ2000_BUILTIN_WB:
2761 return expand_one_builtin (CODE_FOR_wb, target, exp, code, 2);
2762
2763 case IQ2000_BUILTIN_WX:
2764 return expand_one_builtin (CODE_FOR_wx, target, exp, code, 2);
2765
2766 case IQ2000_BUILTIN_LUC32L:
2767 return expand_one_builtin (CODE_FOR_luc32l, target, exp, code, 2);
2768
2769 case IQ2000_BUILTIN_LUC64:
2770 return expand_one_builtin (CODE_FOR_luc64, target, exp, code, 2);
2771
2772 case IQ2000_BUILTIN_LUC64L:
2773 return expand_one_builtin (CODE_FOR_luc64l, target, exp, code, 2);
2774
2775 case IQ2000_BUILTIN_LUK:
2776 return expand_one_builtin (CODE_FOR_luk, target, exp, code, 2);
2777
2778 case IQ2000_BUILTIN_LULCK:
2779 return expand_one_builtin (CODE_FOR_lulck, target, exp, code, 1);
2780
2781 case IQ2000_BUILTIN_LUM32:
2782 return expand_one_builtin (CODE_FOR_lum32, target, exp, code, 2);
2783
2784 case IQ2000_BUILTIN_LUM32L:
2785 return expand_one_builtin (CODE_FOR_lum32l, target, exp, code, 2);
2786
2787 case IQ2000_BUILTIN_LUM64:
2788 return expand_one_builtin (CODE_FOR_lum64, target, exp, code, 2);
2789
2790 case IQ2000_BUILTIN_LUM64L:
2791 return expand_one_builtin (CODE_FOR_lum64l, target, exp, code, 2);
2792
2793 case IQ2000_BUILTIN_LURL:
2794 return expand_one_builtin (CODE_FOR_lurl, target, exp, code, 2);
2795
2796 case IQ2000_BUILTIN_MRGB:
2797 code[2] = CONST_INT;
2798 return expand_one_builtin (CODE_FOR_mrgb, target, exp, code, 3);
2799
2800 case IQ2000_BUILTIN_SRRDL:
2801 return expand_one_builtin (CODE_FOR_srrdl, target, exp, code, 1);
2802
2803 case IQ2000_BUILTIN_SRULCK:
2804 return expand_one_builtin (CODE_FOR_srulck, target, exp, code, 1);
2805
2806 case IQ2000_BUILTIN_SRWRU:
2807 return expand_one_builtin (CODE_FOR_srwru, target, exp, code, 2);
2808
2809 case IQ2000_BUILTIN_TRAPQFL:
2810 return expand_one_builtin (CODE_FOR_trapqfl, target, exp, code, 0);
2811
2812 case IQ2000_BUILTIN_TRAPQNE:
2813 return expand_one_builtin (CODE_FOR_trapqne, target, exp, code, 0);
2814
2815 case IQ2000_BUILTIN_TRAPREL:
2816 return expand_one_builtin (CODE_FOR_traprel, target, exp, code, 1);
2817
2818 case IQ2000_BUILTIN_WBU:
2819 return expand_one_builtin (CODE_FOR_wbu, target, exp, code, 3);
2820
2821 case IQ2000_BUILTIN_SYSCALL:
2822 return expand_one_builtin (CODE_FOR_syscall, target, exp, code, 0);
2823 }
2824
2825 return NULL_RTX;
2826 }
2827
2828 /* Worker function for TARGET_RETURN_IN_MEMORY. */
2829
2830 static bool
2831 iq2000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2832 {
2833 return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
2834 || (int_size_in_bytes (type) == -1));
2835 }
2836
2837 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
2838
2839 static void
2840 iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
2841 enum machine_mode mode ATTRIBUTE_UNUSED,
2842 tree type ATTRIBUTE_UNUSED, int * pretend_size,
2843 int no_rtl)
2844 {
2845 unsigned int iq2000_off = ! cum->last_arg_fp;
2846 unsigned int iq2000_fp_off = cum->last_arg_fp;
2847
2848 if ((cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off))
2849 {
2850 int iq2000_save_gp_regs
2851 = MAX_ARGS_IN_REGISTERS - cum->arg_words - iq2000_off;
2852 int iq2000_save_fp_regs
2853 = (MAX_ARGS_IN_REGISTERS - cum->fp_arg_words - iq2000_fp_off);
2854
2855 if (iq2000_save_gp_regs < 0)
2856 iq2000_save_gp_regs = 0;
2857 if (iq2000_save_fp_regs < 0)
2858 iq2000_save_fp_regs = 0;
2859
2860 *pretend_size = ((iq2000_save_gp_regs * UNITS_PER_WORD)
2861 + (iq2000_save_fp_regs * UNITS_PER_FPREG));
2862
2863 if (! (no_rtl))
2864 {
2865 if (cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off)
2866 {
2867 rtx ptr, mem;
2868 ptr = plus_constant (virtual_incoming_args_rtx,
2869 - (iq2000_save_gp_regs
2870 * UNITS_PER_WORD));
2871 mem = gen_rtx_MEM (BLKmode, ptr);
2872 move_block_from_reg
2873 (cum->arg_words + GP_ARG_FIRST + iq2000_off,
2874 mem,
2875 iq2000_save_gp_regs);
2876 }
2877 }
2878 }
2879 }
2880
2881 /* A C compound statement to output to stdio stream STREAM the
2882 assembler syntax for an instruction operand that is a memory
2883 reference whose address is ADDR. ADDR is an RTL expression. */
2884
2885 void
2886 print_operand_address (FILE * file, rtx addr)
2887 {
2888 if (!addr)
2889 error ("PRINT_OPERAND_ADDRESS, null pointer");
2890
2891 else
2892 switch (GET_CODE (addr))
2893 {
2894 case REG:
2895 if (REGNO (addr) == ARG_POINTER_REGNUM)
2896 abort_with_insn (addr, "Arg pointer not eliminated.");
2897
2898 fprintf (file, "0(%s)", reg_names [REGNO (addr)]);
2899 break;
2900
2901 case LO_SUM:
2902 {
2903 rtx arg0 = XEXP (addr, 0);
2904 rtx arg1 = XEXP (addr, 1);
2905
2906 if (GET_CODE (arg0) != REG)
2907 abort_with_insn (addr,
2908 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG.");
2909
2910 fprintf (file, "%%lo(");
2911 print_operand_address (file, arg1);
2912 fprintf (file, ")(%s)", reg_names [REGNO (arg0)]);
2913 }
2914 break;
2915
2916 case PLUS:
2917 {
2918 rtx reg = 0;
2919 rtx offset = 0;
2920 rtx arg0 = XEXP (addr, 0);
2921 rtx arg1 = XEXP (addr, 1);
2922
2923 if (GET_CODE (arg0) == REG)
2924 {
2925 reg = arg0;
2926 offset = arg1;
2927 if (GET_CODE (offset) == REG)
2928 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, 2 regs");
2929 }
2930
2931 else if (GET_CODE (arg1) == REG)
2932 reg = arg1, offset = arg0;
2933 else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
2934 {
2935 output_addr_const (file, addr);
2936 break;
2937 }
2938 else
2939 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, no regs");
2940
2941 if (! CONSTANT_P (offset))
2942 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #2");
2943
2944 if (REGNO (reg) == ARG_POINTER_REGNUM)
2945 abort_with_insn (addr, "Arg pointer not eliminated.");
2946
2947 output_addr_const (file, offset);
2948 fprintf (file, "(%s)", reg_names [REGNO (reg)]);
2949 }
2950 break;
2951
2952 case LABEL_REF:
2953 case SYMBOL_REF:
2954 case CONST_INT:
2955 case CONST:
2956 output_addr_const (file, addr);
2957 if (GET_CODE (addr) == CONST_INT)
2958 fprintf (file, "(%s)", reg_names [0]);
2959 break;
2960
2961 default:
2962 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #1");
2963 break;
2964 }
2965 }
2966
2967 /* A C compound statement to output to stdio stream FILE the
2968 assembler syntax for an instruction operand OP.
2969
2970 LETTER is a value that can be used to specify one of several ways
2971 of printing the operand. It is used when identical operands
2972 must be printed differently depending on the context. LETTER
2973 comes from the `%' specification that was used to request
2974 printing of the operand. If the specification was just `%DIGIT'
2975 then LETTER is 0; if the specification was `%LTR DIGIT' then LETTER
2976 is the ASCII code for LTR.
2977
2978 If OP is a register, this macro should print the register's name.
2979 The names can be found in an array `reg_names' whose type is
2980 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
2981
2982 When the machine description has a specification `%PUNCT' (a `%'
2983 followed by a punctuation character), this macro is called with
2984 a null pointer for X and the punctuation character for LETTER.
2985
2986 The IQ2000 specific codes are:
2987
2988 'X' X is CONST_INT, prints upper 16 bits in hexadecimal format = "0x%04x",
2989 'x' X is CONST_INT, prints lower 16 bits in hexadecimal format = "0x%04x",
2990 'd' output integer constant in decimal,
2991 'z' if the operand is 0, use $0 instead of normal operand.
2992 'D' print second part of double-word register or memory operand.
2993 'L' print low-order register of double-word register operand.
2994 'M' print high-order register of double-word register operand.
2995 'C' print part of opcode for a branch condition.
2996 'F' print part of opcode for a floating-point branch condition.
2997 'N' print part of opcode for a branch condition, inverted.
2998 'W' print part of opcode for a floating-point branch condition, inverted.
2999 'A' Print part of opcode for a bit test condition.
3000 'P' Print label for a bit test.
3001 'p' Print log for a bit test.
3002 'B' print 'z' for EQ, 'n' for NE
3003 'b' print 'n' for EQ, 'z' for NE
3004 'T' print 'f' for EQ, 't' for NE
3005 't' print 't' for EQ, 'f' for NE
3006 'Z' print register and a comma, but print nothing for $fcc0
3007 '?' Print 'l' if we are to use a branch likely instead of normal branch.
3008 '@' Print the name of the assembler temporary register (at or $1).
3009 '.' Print the name of the register with a hard-wired zero (zero or $0).
3010 '$' Print the name of the stack pointer register (sp or $29).
3011 '+' Print the name of the gp register (gp or $28). */
3012
3013 void
3014 print_operand (FILE *file, rtx op, int letter)
3015 {
3016 enum rtx_code code;
3017
3018 if (PRINT_OPERAND_PUNCT_VALID_P (letter))
3019 {
3020 switch (letter)
3021 {
3022 case '?':
3023 if (iq2000_branch_likely)
3024 putc ('l', file);
3025 break;
3026
3027 case '@':
3028 fputs (reg_names [GP_REG_FIRST + 1], file);
3029 break;
3030
3031 case '.':
3032 fputs (reg_names [GP_REG_FIRST + 0], file);
3033 break;
3034
3035 case '$':
3036 fputs (reg_names[STACK_POINTER_REGNUM], file);
3037 break;
3038
3039 case '+':
3040 fputs (reg_names[GP_REG_FIRST + 28], file);
3041 break;
3042
3043 default:
3044 error ("PRINT_OPERAND: Unknown punctuation '%c'", letter);
3045 break;
3046 }
3047
3048 return;
3049 }
3050
3051 if (! op)
3052 {
3053 error ("PRINT_OPERAND null pointer");
3054 return;
3055 }
3056
3057 code = GET_CODE (op);
3058
3059 if (code == SIGN_EXTEND)
3060 op = XEXP (op, 0), code = GET_CODE (op);
3061
3062 if (letter == 'C')
3063 switch (code)
3064 {
3065 case EQ: fputs ("eq", file); break;
3066 case NE: fputs ("ne", file); break;
3067 case GT: fputs ("gt", file); break;
3068 case GE: fputs ("ge", file); break;
3069 case LT: fputs ("lt", file); break;
3070 case LE: fputs ("le", file); break;
3071 case GTU: fputs ("ne", file); break;
3072 case GEU: fputs ("geu", file); break;
3073 case LTU: fputs ("ltu", file); break;
3074 case LEU: fputs ("eq", file); break;
3075 default:
3076 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%C");
3077 }
3078
3079 else if (letter == 'N')
3080 switch (code)
3081 {
3082 case EQ: fputs ("ne", file); break;
3083 case NE: fputs ("eq", file); break;
3084 case GT: fputs ("le", file); break;
3085 case GE: fputs ("lt", file); break;
3086 case LT: fputs ("ge", file); break;
3087 case LE: fputs ("gt", file); break;
3088 case GTU: fputs ("leu", file); break;
3089 case GEU: fputs ("ltu", file); break;
3090 case LTU: fputs ("geu", file); break;
3091 case LEU: fputs ("gtu", file); break;
3092 default:
3093 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%N");
3094 }
3095
3096 else if (letter == 'F')
3097 switch (code)
3098 {
3099 case EQ: fputs ("c1f", file); break;
3100 case NE: fputs ("c1t", file); break;
3101 default:
3102 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%F");
3103 }
3104
3105 else if (letter == 'W')
3106 switch (code)
3107 {
3108 case EQ: fputs ("c1t", file); break;
3109 case NE: fputs ("c1f", file); break;
3110 default:
3111 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%W");
3112 }
3113
3114 else if (letter == 'A')
3115 fputs (code == LABEL_REF ? "i" : "in", file);
3116
3117 else if (letter == 'P')
3118 {
3119 if (code == LABEL_REF)
3120 output_addr_const (file, op);
3121 else if (code != PC)
3122 output_operand_lossage ("invalid %%P operand");
3123 }
3124
3125 else if (letter == 'p')
3126 {
3127 int value;
3128 if (code != CONST_INT
3129 || (value = exact_log2 (INTVAL (op))) < 0)
3130 output_operand_lossage ("invalid %%p value");
3131 fprintf (file, "%d", value);
3132 }
3133
3134 else if (letter == 'Z')
3135 {
3136 gcc_unreachable ();
3137 }
3138
3139 else if (code == REG || code == SUBREG)
3140 {
3141 int regnum;
3142
3143 if (code == REG)
3144 regnum = REGNO (op);
3145 else
3146 regnum = true_regnum (op);
3147
3148 if ((letter == 'M' && ! WORDS_BIG_ENDIAN)
3149 || (letter == 'L' && WORDS_BIG_ENDIAN)
3150 || letter == 'D')
3151 regnum++;
3152
3153 fprintf (file, "%s", reg_names[regnum]);
3154 }
3155
3156 else if (code == MEM)
3157 {
3158 if (letter == 'D')
3159 output_address (plus_constant (XEXP (op, 0), 4));
3160 else
3161 output_address (XEXP (op, 0));
3162 }
3163
3164 else if (code == CONST_DOUBLE
3165 && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
3166 {
3167 char s[60];
3168
3169 real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (op), sizeof (s), 0, 1);
3170 fputs (s, file);
3171 }
3172
3173 else if (letter == 'x' && GET_CODE (op) == CONST_INT)
3174 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op));
3175
3176 else if (letter == 'X' && GET_CODE(op) == CONST_INT)
3177 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & (INTVAL (op) >> 16));
3178
3179 else if (letter == 'd' && GET_CODE(op) == CONST_INT)
3180 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op)));
3181
3182 else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
3183 fputs (reg_names[GP_REG_FIRST], file);
3184
3185 else if (letter == 'd' || letter == 'x' || letter == 'X')
3186 output_operand_lossage ("invalid use of %%d, %%x, or %%X");
3187
3188 else if (letter == 'B')
3189 fputs (code == EQ ? "z" : "n", file);
3190 else if (letter == 'b')
3191 fputs (code == EQ ? "n" : "z", file);
3192 else if (letter == 'T')
3193 fputs (code == EQ ? "f" : "t", file);
3194 else if (letter == 't')
3195 fputs (code == EQ ? "t" : "f", file);
3196
3197 else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
3198 {
3199 print_operand (file, XEXP (op, 0), letter);
3200 }
3201
3202 else
3203 output_addr_const (file, op);
3204 }
3205
3206 static bool
3207 iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total,
3208 bool speed ATTRIBUTE_UNUSED)
3209 {
3210 enum machine_mode mode = GET_MODE (x);
3211
3212 switch (code)
3213 {
3214 case MEM:
3215 {
3216 int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
3217
3218 if (simple_memory_operand (x, mode))
3219 return COSTS_N_INSNS (num_words);
3220
3221 * total = COSTS_N_INSNS (2 * num_words);
3222 break;
3223 }
3224
3225 case FFS:
3226 * total = COSTS_N_INSNS (6);
3227 break;
3228
3229 case AND:
3230 case IOR:
3231 case XOR:
3232 case NOT:
3233 * total = COSTS_N_INSNS (mode == DImode ? 2 : 1);
3234 break;
3235
3236 case ASHIFT:
3237 case ASHIFTRT:
3238 case LSHIFTRT:
3239 if (mode == DImode)
3240 * total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT) ? 4 : 12);
3241 else
3242 * total = COSTS_N_INSNS (1);
3243 break;
3244
3245 case ABS:
3246 if (mode == SFmode || mode == DFmode)
3247 * total = COSTS_N_INSNS (1);
3248 else
3249 * total = COSTS_N_INSNS (4);
3250 break;
3251
3252 case PLUS:
3253 case MINUS:
3254 if (mode == SFmode || mode == DFmode)
3255 * total = COSTS_N_INSNS (6);
3256 else if (mode == DImode)
3257 * total = COSTS_N_INSNS (4);
3258 else
3259 * total = COSTS_N_INSNS (1);
3260 break;
3261
3262 case NEG:
3263 * total = (mode == DImode) ? 4 : 1;
3264 break;
3265
3266 case MULT:
3267 if (mode == SFmode)
3268 * total = COSTS_N_INSNS (7);
3269 else if (mode == DFmode)
3270 * total = COSTS_N_INSNS (8);
3271 else
3272 * total = COSTS_N_INSNS (10);
3273 break;
3274
3275 case DIV:
3276 case MOD:
3277 if (mode == SFmode)
3278 * total = COSTS_N_INSNS (23);
3279 else if (mode == DFmode)
3280 * total = COSTS_N_INSNS (36);
3281 else
3282 * total = COSTS_N_INSNS (69);
3283 break;
3284
3285 case UDIV:
3286 case UMOD:
3287 * total = COSTS_N_INSNS (69);
3288 break;
3289
3290 case SIGN_EXTEND:
3291 * total = COSTS_N_INSNS (2);
3292 break;
3293
3294 case ZERO_EXTEND:
3295 * total = COSTS_N_INSNS (1);
3296 break;
3297
3298 case CONST_INT:
3299 * total = 0;
3300 break;
3301
3302 case LABEL_REF:
3303 * total = COSTS_N_INSNS (2);
3304 break;
3305
3306 case CONST:
3307 {
3308 rtx offset = const0_rtx;
3309 rtx symref = eliminate_constant_term (XEXP (x, 0), & offset);
3310
3311 if (GET_CODE (symref) == LABEL_REF)
3312 * total = COSTS_N_INSNS (2);
3313 else if (GET_CODE (symref) != SYMBOL_REF)
3314 * total = COSTS_N_INSNS (4);
3315 /* Let's be paranoid.... */
3316 else if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)
3317 * total = COSTS_N_INSNS (2);
3318 else
3319 * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (symref) ? 1 : 2);
3320 break;
3321 }
3322
3323 case SYMBOL_REF:
3324 * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (x) ? 1 : 2);
3325 break;
3326
3327 case CONST_DOUBLE:
3328 {
3329 rtx high, low;
3330
3331 split_double (x, & high, & low);
3332
3333 * total = COSTS_N_INSNS ( (high == CONST0_RTX (GET_MODE (high))
3334 || low == CONST0_RTX (GET_MODE (low)))
3335 ? 2 : 4);
3336 break;
3337 }
3338
3339 default:
3340 return false;
3341 }
3342 return true;
3343 }
3344
3345 #include "gt-iq2000.h"