]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/iq2000/iq2000.c
alloc-pool.h, [...]: Update copyright.
[thirdparty/gcc.git] / gcc / config / iq2000 / iq2000.c
CommitLineData
6b3d1e47 1/* Subroutines used for code generation on Vitesse IQ2000 processors
69a45040 2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
6b3d1e47 3
b7849684 4This file is part of GCC.
6b3d1e47 5
b7849684 6GCC is free software; you can redistribute it and/or modify
6b3d1e47
SC
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
b7849684 11GCC is distributed in the hope that it will be useful,
6b3d1e47
SC
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
b7849684 17along with GCC; see the file COPYING. If not, write to
6b3d1e47
SC
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
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
49/* Enumeration for all of the relational tests, so that we can build
50 arrays indexed by the test type, and not worry about the order
51 of EQ, NE, etc. */
52
b5144086
SC
53enum internal_test
54 {
6b3d1e47
SC
55 ITEST_EQ,
56 ITEST_NE,
57 ITEST_GT,
58 ITEST_GE,
59 ITEST_LT,
60 ITEST_LE,
61 ITEST_GTU,
62 ITEST_GEU,
63 ITEST_LTU,
64 ITEST_LEU,
65 ITEST_MAX
66 };
67
68struct constant;
69
6b3d1e47
SC
70\f
71/* Structure to be filled in by compute_frame_size with register
72 save masks, and offsets for the current function. */
73
74struct iq2000_frame_info
75{
b5144086
SC
76 long total_size; /* # bytes that the entire frame takes up. */
77 long var_size; /* # bytes that variables take up. */
78 long args_size; /* # bytes that outgoing arguments take up. */
79 long extra_size; /* # bytes of extra gunk. */
80 int gp_reg_size; /* # bytes needed to store gp regs. */
81 int fp_reg_size; /* # bytes needed to store fp regs. */
82 long mask; /* Mask of saved gp registers. */
83 long gp_save_offset; /* Offset from vfp to store gp registers. */
84 long fp_save_offset; /* Offset from vfp to store fp registers. */
85 long gp_sp_offset; /* Offset from new sp to store gp registers. */
86 long fp_sp_offset; /* Offset from new sp to store fp registers. */
87 int initialized; /* != 0 if frame size already calculated. */
88 int num_gp; /* Number of gp registers saved. */
89} iq2000_frame_info;
90
91struct machine_function GTY(())
6b3d1e47
SC
92{
93 /* Current frame information, calculated by compute_frame_size. */
b5144086
SC
94 long total_size; /* # bytes that the entire frame takes up. */
95 long var_size; /* # bytes that variables take up. */
96 long args_size; /* # bytes that outgoing arguments take up. */
97 long extra_size; /* # bytes of extra gunk. */
98 int gp_reg_size; /* # bytes needed to store gp regs. */
99 int fp_reg_size; /* # bytes needed to store fp regs. */
100 long mask; /* Mask of saved gp registers. */
101 long gp_save_offset; /* Offset from vfp to store gp registers. */
102 long fp_save_offset; /* Offset from vfp to store fp registers. */
103 long gp_sp_offset; /* Offset from new sp to store gp registers. */
104 long fp_sp_offset; /* Offset from new sp to store fp registers. */
105 int initialized; /* != 0 if frame size already calculated. */
106 int num_gp; /* Number of gp registers saved. */
6b3d1e47
SC
107};
108
109/* Global variables for machine-dependent things. */
110
b5144086
SC
111/* List of all IQ2000 punctuation characters used by print_operand. */
112char iq2000_print_operand_punct[256];
6b3d1e47 113
b5144086
SC
114/* The target cpu for optimization and scheduling. */
115enum processor_type iq2000_tune;
6b3d1e47 116
b5144086
SC
117/* Which instruction set architecture to use. */
118int iq2000_isa;
6b3d1e47
SC
119
120/* Cached operands, and operator to compare for use in set/branch/trap
121 on condition codes. */
122rtx branch_cmp[2];
123
b5144086 124/* What type of branch to use. */
6b3d1e47
SC
125enum cmp_type branch_type;
126
b5144086
SC
127/* Strings to hold which cpu and instruction set architecture to use. */
128const char * iq2000_cpu_string; /* For -mcpu=<xxx>. */
129const char * iq2000_arch_string; /* For -march=<xxx>. */
6b3d1e47 130
6b3d1e47 131
b5144086 132/* Local variables. */
6b3d1e47 133
b5144086
SC
134/* The next branch instruction is a branch likely, not branch normal. */
135static int iq2000_branch_likely;
136
137/* Count of delay slots and how many are filled. */
138static int dslots_load_total;
139static int dslots_load_filled;
140static int dslots_jump_total;
141
142/* # of nops needed by previous insn. */
143static int dslots_number_nops;
144
145/* Number of 1/2/3 word references to data items (ie, not jal's). */
146static int num_refs[3];
147
148/* Registers to check for load delay. */
149static rtx iq2000_load_reg;
150static rtx iq2000_load_reg2;
151static rtx iq2000_load_reg3;
152static rtx iq2000_load_reg4;
153
154/* The target cpu for code generation. */
155static enum processor_type iq2000_arch;
6b3d1e47
SC
156
157/* Mode used for saving/restoring general purpose registers. */
158static enum machine_mode gpr_mode;
159
6b3d1e47
SC
160\f
161/* Initialize the GCC target structure. */
b5144086
SC
162static struct machine_function* iq2000_init_machine_status (void);
163static void iq2000_select_rtx_section (enum machine_mode, rtx, unsigned HOST_WIDE_INT);
164static void iq2000_init_builtins (void);
165static rtx iq2000_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
69a45040
KH
166static bool iq2000_return_in_memory (tree, tree);
167static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *,
168 enum machine_mode, tree, int *,
169 int);
b5144086
SC
170static bool iq2000_rtx_costs (rtx, int, int, int *);
171static int iq2000_address_cost (rtx);
172static void iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
69a45040 173static bool iq2000_return_in_memory (tree, tree);
b5144086
SC
174
175#undef TARGET_INIT_BUILTINS
176#define TARGET_INIT_BUILTINS iq2000_init_builtins
177#undef TARGET_EXPAND_BUILTIN
178#define TARGET_EXPAND_BUILTIN iq2000_expand_builtin
179#undef TARGET_ASM_SELECT_RTX_SECTION
180#define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section
181#undef TARGET_RTX_COSTS
182#define TARGET_RTX_COSTS iq2000_rtx_costs
183#undef TARGET_ADDRESS_COST
184#define TARGET_ADDRESS_COST iq2000_address_cost
185#undef TARGET_ASM_SELECT_SECTION
186#define TARGET_ASM_SELECT_SECTION iq2000_select_section
6b3d1e47 187
69a45040
KH
188#undef TARGET_PROMOTE_FUNCTION_ARGS
189#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
190#undef TARGET_PROMOTE_FUNCTION_RETURN
191#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
192#undef TARGET_PROMOTE_PROTOTYPES
193#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
194
195#undef TARGET_STRUCT_VALUE_RTX
196#define TARGET_STRUCT_VALUE_RTX hook_rtx_tree_int_null
197#undef TARGET_RETURN_IN_MEMORY
198#define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
199
200#undef TARGET_SETUP_INCOMING_VARARGS
201#define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs
202#undef TARGET_STRICT_ARGUMENT_NAMING
203#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
204
6b3d1e47
SC
205struct gcc_target targetm = TARGET_INITIALIZER;
206\f
207/* Return 1 if OP can be used as an operand where a register or 16 bit unsigned
208 integer is needed. */
209
210int
b7849684 211uns_arith_operand (rtx op, enum machine_mode mode)
6b3d1e47
SC
212{
213 if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op))
214 return 1;
215
216 return register_operand (op, mode);
217}
218
b5144086 219/* Return 1 if OP can be used as an operand where a 16 bit integer is needed. */
6b3d1e47
SC
220
221int
b7849684 222arith_operand (rtx op, enum machine_mode mode)
6b3d1e47
SC
223{
224 if (GET_CODE (op) == CONST_INT && SMALL_INT (op))
225 return 1;
226
227 return register_operand (op, mode);
228}
229
b5144086 230/* Return 1 if OP is a integer which fits in 16 bits. */
6b3d1e47
SC
231
232int
b7849684 233small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
6b3d1e47
SC
234{
235 return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
236}
237
238/* Return 1 if OP is a 32 bit integer which is too big to be loaded with one
239 instruction. */
240
241int
b7849684 242large_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
6b3d1e47
SC
243{
244 HOST_WIDE_INT value;
245
246 if (GET_CODE (op) != CONST_INT)
247 return 0;
248
249 value = INTVAL (op);
250
b5144086 251 /* IOR reg,$r0,value. */
6b3d1e47
SC
252 if ((value & ~ ((HOST_WIDE_INT) 0x0000ffff)) == 0)
253 return 0;
254
b5144086 255 /* SUBU reg,$r0,value. */
6b3d1e47
SC
256 if (((unsigned HOST_WIDE_INT) (value + 32768)) <= 32767)
257 return 0;
258
b5144086 259 /* LUI reg,value >> 16. */
6b3d1e47
SC
260 if ((value & 0x0000ffff) == 0)
261 return 0;
262
263 return 1;
264}
265
266/* Return 1 if OP is a register or the constant 0. */
267
268int
b7849684 269reg_or_0_operand (rtx op, enum machine_mode mode)
6b3d1e47
SC
270{
271 switch (GET_CODE (op))
272 {
273 case CONST_INT:
274 return INTVAL (op) == 0;
275
276 case CONST_DOUBLE:
277 return op == CONST0_RTX (mode);
278
279 case REG:
280 case SUBREG:
281 return register_operand (op, mode);
282
283 default:
284 break;
285 }
286
287 return 0;
288}
289
290/* Return 1 if OP is a memory operand that fits in a single instruction
291 (ie, register + small offset). */
292
293int
b7849684 294simple_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
6b3d1e47
SC
295{
296 rtx addr, plus0, plus1;
297
b5144086 298 /* Eliminate non-memory operations. */
6b3d1e47
SC
299 if (GET_CODE (op) != MEM)
300 return 0;
301
b5144086 302 /* Dword operations really put out 2 instructions, so eliminate them. */
6b3d1e47
SC
303 if (GET_MODE_SIZE (GET_MODE (op)) > (unsigned) UNITS_PER_WORD)
304 return 0;
305
306 /* Decode the address now. */
307 addr = XEXP (op, 0);
308 switch (GET_CODE (addr))
309 {
310 case REG:
311 case LO_SUM:
312 return 1;
313
314 case CONST_INT:
315 return SMALL_INT (addr);
316
317 case PLUS:
318 plus0 = XEXP (addr, 0);
319 plus1 = XEXP (addr, 1);
320 if (GET_CODE (plus0) == REG
321 && GET_CODE (plus1) == CONST_INT && SMALL_INT (plus1)
b5144086 322 && SMALL_INT_UNSIGNED (plus1) /* No negative offsets. */)
6b3d1e47
SC
323 return 1;
324
325 else if (GET_CODE (plus1) == REG
326 && GET_CODE (plus0) == CONST_INT && SMALL_INT (plus0)
b5144086 327 && SMALL_INT_UNSIGNED (plus1) /* No negative offsets. */)
6b3d1e47
SC
328 return 1;
329
330 else
331 return 0;
332
333 case SYMBOL_REF:
334 return 0;
335
336 default:
337 break;
338 }
339
340 return 0;
341}
342
343/* Return nonzero if the code of this rtx pattern is EQ or NE. */
344
345int
b7849684 346equality_op (rtx op, enum machine_mode mode)
6b3d1e47
SC
347{
348 if (mode != GET_MODE (op))
349 return 0;
350
351 return GET_CODE (op) == EQ || GET_CODE (op) == NE;
352}
353
b5144086 354/* Return nonzero if the code is a relational operations (EQ, LE, etc). */
6b3d1e47
SC
355
356int
b7849684 357cmp_op (rtx op, enum machine_mode mode)
6b3d1e47
SC
358{
359 if (mode != GET_MODE (op))
360 return 0;
361
362 return GET_RTX_CLASS (GET_CODE (op)) == '<';
363}
364
365/* Return nonzero if the operand is either the PC or a label_ref. */
366
367int
b7849684 368pc_or_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
6b3d1e47
SC
369{
370 if (op == pc_rtx)
371 return 1;
372
373 if (GET_CODE (op) == LABEL_REF)
374 return 1;
375
376 return 0;
377}
378
379/* Return nonzero if OP is a valid operand for a call instruction. */
380
381int
b7849684 382call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
6b3d1e47
SC
383{
384 return (CONSTANT_ADDRESS_P (op)
385 || (GET_CODE (op) == REG && op != arg_pointer_rtx
386 && ! (REGNO (op) >= FIRST_PSEUDO_REGISTER
387 && REGNO (op) <= LAST_VIRTUAL_REGISTER)));
388}
389
390/* Return nonzero if OP is valid as a source operand for a move instruction. */
391
392int
b7849684 393move_operand (rtx op, enum machine_mode mode)
6b3d1e47
SC
394{
395 /* Accept any general operand after reload has started; doing so
396 avoids losing if reload does an in-place replacement of a register
397 with a SYMBOL_REF or CONST. */
398 return (general_operand (op, mode)
399 && (! (iq2000_check_split (op, mode))
400 || reload_in_progress || reload_completed));
401}
402
403/* Return nonzero if OP is a constant power of 2. */
404
405int
b7849684 406power_of_2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
6b3d1e47
SC
407{
408 int intval;
409
410 if (GET_CODE (op) != CONST_INT)
411 return 0;
412 else
413 intval = INTVAL (op);
414
415 return ((intval & ((unsigned)(intval) - 1)) == 0);
416}
417
418/* Return nonzero if we split the address into high and low parts. */
419
420int
b7849684 421iq2000_check_split (rtx address, enum machine_mode mode)
6b3d1e47
SC
422{
423 /* This is the same check used in simple_memory_operand.
424 We use it here because LO_SUM is not offsettable. */
425 if (GET_MODE_SIZE (mode) > (unsigned) UNITS_PER_WORD)
426 return 0;
427
428 if ((GET_CODE (address) == SYMBOL_REF)
429 || (GET_CODE (address) == CONST
430 && GET_CODE (XEXP (XEXP (address, 0), 0)) == SYMBOL_REF)
431 || GET_CODE (address) == LABEL_REF)
432 return 1;
433
434 return 0;
435}
436
437/* Return nonzero if REG is valid for MODE. */
438
439int
b7849684
JE
440iq2000_reg_mode_ok_for_base_p (rtx reg,
441 enum machine_mode mode ATTRIBUTE_UNUSED,
442 int strict)
6b3d1e47
SC
443{
444 return (strict
445 ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode)
446 : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode));
447}
448
449/* Return a nonzero value if XINSN is a legitimate address for a
4375e090 450 memory operand of the indicated MODE. STRICT is nonzero if this
6b3d1e47
SC
451 function is called during reload. */
452
453int
b7849684 454iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict)
6b3d1e47
SC
455{
456 if (TARGET_DEBUG_A_MODE)
457 {
458 GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
459 strict ? "" : "not ");
460 GO_DEBUG_RTX (xinsn);
461 }
462
463 /* Check for constant before stripping off SUBREG, so that we don't
464 accept (subreg (const_int)) which will fail to reload. */
465 if (CONSTANT_ADDRESS_P (xinsn)
466 && ! (iq2000_check_split (xinsn, mode))
467 && ! (GET_CODE (xinsn) == CONST_INT && ! SMALL_INT (xinsn)))
468 return 1;
469
470 while (GET_CODE (xinsn) == SUBREG)
471 xinsn = SUBREG_REG (xinsn);
472
473 if (GET_CODE (xinsn) == REG
474 && iq2000_reg_mode_ok_for_base_p (xinsn, mode, strict))
475 return 1;
476
477 if (GET_CODE (xinsn) == LO_SUM)
478 {
b5144086
SC
479 rtx xlow0 = XEXP (xinsn, 0);
480 rtx xlow1 = XEXP (xinsn, 1);
6b3d1e47
SC
481
482 while (GET_CODE (xlow0) == SUBREG)
483 xlow0 = SUBREG_REG (xlow0);
484 if (GET_CODE (xlow0) == REG
485 && iq2000_reg_mode_ok_for_base_p (xlow0, mode, strict)
486 && iq2000_check_split (xlow1, mode))
487 return 1;
488 }
489
490 if (GET_CODE (xinsn) == PLUS)
491 {
b5144086
SC
492 rtx xplus0 = XEXP (xinsn, 0);
493 rtx xplus1 = XEXP (xinsn, 1);
494 enum rtx_code code0;
495 enum rtx_code code1;
6b3d1e47
SC
496
497 while (GET_CODE (xplus0) == SUBREG)
498 xplus0 = SUBREG_REG (xplus0);
499 code0 = GET_CODE (xplus0);
500
501 while (GET_CODE (xplus1) == SUBREG)
502 xplus1 = SUBREG_REG (xplus1);
503 code1 = GET_CODE (xplus1);
504
505 if (code0 == REG
506 && iq2000_reg_mode_ok_for_base_p (xplus0, mode, strict))
507 {
508 if (code1 == CONST_INT && SMALL_INT (xplus1)
509 && SMALL_INT_UNSIGNED (xplus1) /* No negative offsets */)
510 return 1;
511 }
512 }
513
514 if (TARGET_DEBUG_A_MODE)
515 GO_PRINTF ("Not a legitimate address\n");
516
517 /* The address was not legitimate. */
518 return 0;
519}
520\f
521/* Returns an operand string for the given instruction's delay slot,
522 after updating filled delay slot statistics.
523
524 We assume that operands[0] is the target register that is set.
525
526 In order to check the next insn, most of this functionality is moved
527 to FINAL_PRESCAN_INSN, and we just set the global variables that
528 it needs. */
529
530const char *
b7849684
JE
531iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[],
532 rtx cur_insn)
6b3d1e47 533{
b5144086
SC
534 rtx set_reg;
535 enum machine_mode mode;
536 rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX;
537 int num_nops;
6b3d1e47
SC
538
539 if (type == DELAY_LOAD || type == DELAY_FCMP)
540 num_nops = 1;
541
542 else
543 num_nops = 0;
544
545 /* Make sure that we don't put nop's after labels. */
546 next_insn = NEXT_INSN (cur_insn);
547 while (next_insn != 0
548 && (GET_CODE (next_insn) == NOTE
549 || GET_CODE (next_insn) == CODE_LABEL))
550 next_insn = NEXT_INSN (next_insn);
551
552 dslots_load_total += num_nops;
553 if (TARGET_DEBUG_C_MODE
554 || type == DELAY_NONE
555 || operands == 0
556 || cur_insn == 0
557 || next_insn == 0
558 || GET_CODE (next_insn) == CODE_LABEL
559 || (set_reg = operands[0]) == 0)
560 {
561 dslots_number_nops = 0;
562 iq2000_load_reg = 0;
563 iq2000_load_reg2 = 0;
564 iq2000_load_reg3 = 0;
565 iq2000_load_reg4 = 0;
b5144086 566
6b3d1e47
SC
567 return ret;
568 }
569
570 set_reg = operands[0];
571 if (set_reg == 0)
572 return ret;
573
574 while (GET_CODE (set_reg) == SUBREG)
575 set_reg = SUBREG_REG (set_reg);
576
577 mode = GET_MODE (set_reg);
578 dslots_number_nops = num_nops;
579 iq2000_load_reg = set_reg;
580 if (GET_MODE_SIZE (mode)
581 > (unsigned) (UNITS_PER_WORD))
582 iq2000_load_reg2 = gen_rtx_REG (SImode, REGNO (set_reg) + 1);
583 else
584 iq2000_load_reg2 = 0;
585
586 return ret;
587}
588\f
589/* Determine whether a memory reference takes one (based off of the GP
590 pointer), two (normal), or three (label + reg) instructions, and bump the
591 appropriate counter for -mstats. */
592
593static void
b7849684 594iq2000_count_memory_refs (rtx op, int num)
6b3d1e47
SC
595{
596 int additional = 0;
597 int n_words = 0;
598 rtx addr, plus0, plus1;
599 enum rtx_code code0, code1;
600 int looping;
601
602 if (TARGET_DEBUG_B_MODE)
603 {
604 fprintf (stderr, "\n========== iq2000_count_memory_refs:\n");
605 debug_rtx (op);
606 }
607
608 /* Skip MEM if passed, otherwise handle movsi of address. */
609 addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0);
610
611 /* Loop, going through the address RTL. */
612 do
613 {
614 looping = FALSE;
615 switch (GET_CODE (addr))
616 {
617 case REG:
618 case CONST_INT:
619 case LO_SUM:
620 break;
621
622 case PLUS:
623 plus0 = XEXP (addr, 0);
624 plus1 = XEXP (addr, 1);
625 code0 = GET_CODE (plus0);
626 code1 = GET_CODE (plus1);
627
628 if (code0 == REG)
629 {
630 additional++;
631 addr = plus1;
632 looping = 1;
633 continue;
634 }
635
636 if (code0 == CONST_INT)
637 {
638 addr = plus1;
639 looping = 1;
640 continue;
641 }
642
643 if (code1 == REG)
644 {
645 additional++;
646 addr = plus0;
647 looping = 1;
648 continue;
649 }
650
651 if (code1 == CONST_INT)
652 {
653 addr = plus0;
654 looping = 1;
655 continue;
656 }
657
658 if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST)
659 {
660 addr = plus0;
661 looping = 1;
662 continue;
663 }
664
665 if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST)
666 {
667 addr = plus1;
668 looping = 1;
669 continue;
670 }
671
672 break;
673
674 case LABEL_REF:
b5144086 675 n_words = 2; /* Always 2 words. */
6b3d1e47
SC
676 break;
677
678 case CONST:
679 addr = XEXP (addr, 0);
680 looping = 1;
681 continue;
682
683 case SYMBOL_REF:
684 n_words = SYMBOL_REF_FLAG (addr) ? 1 : 2;
685 break;
686
687 default:
688 break;
689 }
690 }
691 while (looping);
692
693 if (n_words == 0)
694 return;
695
696 n_words += additional;
697 if (n_words > 3)
698 n_words = 3;
699
700 num_refs[n_words-1] += num;
701}
702\f
b5144086
SC
703/* Abort after printing out a specific insn. */
704
705static void
706abort_with_insn (rtx insn, const char * reason)
707{
708 error (reason);
709 debug_rtx (insn);
710 abort ();
711}
712\f
6b3d1e47
SC
713/* Return the appropriate instructions to move one operand to another. */
714
715const char *
b7849684 716iq2000_move_1word (rtx operands[], rtx insn, int unsignedp)
6b3d1e47
SC
717{
718 const char *ret = 0;
719 rtx op0 = operands[0];
720 rtx op1 = operands[1];
721 enum rtx_code code0 = GET_CODE (op0);
722 enum rtx_code code1 = GET_CODE (op1);
723 enum machine_mode mode = GET_MODE (op0);
724 int subreg_offset0 = 0;
725 int subreg_offset1 = 0;
726 enum delay_type delay = DELAY_NONE;
727
728 while (code0 == SUBREG)
729 {
730 subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),
731 GET_MODE (SUBREG_REG (op0)),
732 SUBREG_BYTE (op0),
733 GET_MODE (op0));
734 op0 = SUBREG_REG (op0);
735 code0 = GET_CODE (op0);
736 }
737
738 while (code1 == SUBREG)
739 {
740 subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),
741 GET_MODE (SUBREG_REG (op1)),
742 SUBREG_BYTE (op1),
743 GET_MODE (op1));
744 op1 = SUBREG_REG (op1);
745 code1 = GET_CODE (op1);
746 }
747
748 /* For our purposes, a condition code mode is the same as SImode. */
749 if (mode == CCmode)
750 mode = SImode;
751
752 if (code0 == REG)
753 {
754 int regno0 = REGNO (op0) + subreg_offset0;
755
756 if (code1 == REG)
757 {
758 int regno1 = REGNO (op1) + subreg_offset1;
759
760 /* Do not do anything for assigning a register to itself */
761 if (regno0 == regno1)
762 ret = "";
763
764 else if (GP_REG_P (regno0))
765 {
766 if (GP_REG_P (regno1))
767 ret = "or\t%0,%%0,%1";
768 }
769
770 }
771
772 else if (code1 == MEM)
773 {
774 delay = DELAY_LOAD;
775
776 if (TARGET_STATS)
777 iq2000_count_memory_refs (op1, 1);
778
779 if (GP_REG_P (regno0))
780 {
781 /* For loads, use the mode of the memory item, instead of the
782 target, so zero/sign extend can use this code as well. */
783 switch (GET_MODE (op1))
784 {
785 default:
786 break;
787 case SFmode:
788 ret = "lw\t%0,%1";
789 break;
790 case SImode:
791 case CCmode:
792 ret = "lw\t%0,%1";
793 break;
794 case HImode:
795 ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1";
796 break;
797 case QImode:
798 ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1";
799 break;
800 }
801 }
802 }
803
804 else if (code1 == CONST_INT
805 || (code1 == CONST_DOUBLE
806 && GET_MODE (op1) == VOIDmode))
807 {
808 if (code1 == CONST_DOUBLE)
809 {
810 /* This can happen when storing constants into long long
811 bitfields. Just store the least significant word of
812 the value. */
813 operands[1] = op1 = GEN_INT (CONST_DOUBLE_LOW (op1));
814 }
815
816 if (INTVAL (op1) == 0)
817 {
818 if (GP_REG_P (regno0))
819 ret = "or\t%0,%%0,%z1";
820 }
821 else if (GP_REG_P (regno0))
822 {
823 if (SMALL_INT_UNSIGNED (op1))
824 ret = "ori\t%0,%%0,%x1\t\t\t# %1";
825 else if (SMALL_INT (op1))
826 ret = "addiu\t%0,%%0,%1\t\t\t# %1";
827 else
828 ret = "lui\t%0,%X1\t\t\t# %1\n\tori\t%0,%0,%x1";
829 }
830 }
831
832 else if (code1 == CONST_DOUBLE && mode == SFmode)
833 {
834 if (op1 == CONST0_RTX (SFmode))
835 {
836 if (GP_REG_P (regno0))
837 ret = "or\t%0,%%0,%.";
838 }
839
840 else
841 {
842 delay = DELAY_LOAD;
843 ret = "li.s\t%0,%1";
844 }
845 }
846
847 else if (code1 == LABEL_REF)
848 {
849 if (TARGET_STATS)
850 iq2000_count_memory_refs (op1, 1);
851
852 ret = "la\t%0,%a1";
853 }
854
855 else if (code1 == SYMBOL_REF || code1 == CONST)
856 {
857 if (TARGET_STATS)
858 iq2000_count_memory_refs (op1, 1);
859
860 ret = "la\t%0,%a1";
861 }
862
863 else if (code1 == PLUS)
864 {
865 rtx add_op0 = XEXP (op1, 0);
866 rtx add_op1 = XEXP (op1, 1);
867
868 if (GET_CODE (XEXP (op1, 1)) == REG
869 && GET_CODE (XEXP (op1, 0)) == CONST_INT)
870 add_op0 = XEXP (op1, 1), add_op1 = XEXP (op1, 0);
871
872 operands[2] = add_op0;
873 operands[3] = add_op1;
874 ret = "add%:\t%0,%2,%3";
875 }
876
877 else if (code1 == HIGH)
878 {
879 operands[1] = XEXP (op1, 0);
880 ret = "lui\t%0,%%hi(%1)";
881 }
882 }
883
884 else if (code0 == MEM)
885 {
886 if (TARGET_STATS)
887 iq2000_count_memory_refs (op0, 1);
888
889 if (code1 == REG)
890 {
891 int regno1 = REGNO (op1) + subreg_offset1;
892
893 if (GP_REG_P (regno1))
894 {
895 switch (mode)
896 {
897 case SFmode: ret = "sw\t%1,%0"; break;
898 case SImode: ret = "sw\t%1,%0"; break;
899 case HImode: ret = "sh\t%1,%0"; break;
900 case QImode: ret = "sb\t%1,%0"; break;
901 default: break;
902 }
903 }
904 }
905
906 else if (code1 == CONST_INT && INTVAL (op1) == 0)
907 {
908 switch (mode)
909 {
910 case SFmode: ret = "sw\t%z1,%0"; break;
911 case SImode: ret = "sw\t%z1,%0"; break;
912 case HImode: ret = "sh\t%z1,%0"; break;
913 case QImode: ret = "sb\t%z1,%0"; break;
914 default: break;
915 }
916 }
917
918 else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode))
919 {
920 switch (mode)
921 {
922 case SFmode: ret = "sw\t%.,%0"; break;
923 case SImode: ret = "sw\t%.,%0"; break;
924 case HImode: ret = "sh\t%.,%0"; break;
925 case QImode: ret = "sb\t%.,%0"; break;
926 default: break;
927 }
928 }
929 }
930
931 if (ret == 0)
932 {
933 abort_with_insn (insn, "Bad move");
934 return 0;
935 }
936
937 if (delay != DELAY_NONE)
938 return iq2000_fill_delay_slot (ret, delay, operands, insn);
939
940 return ret;
941}
942\f
943/* Provide the costs of an addressing mode that contains ADDR. */
944
b5144086 945static int
b7849684 946iq2000_address_cost (rtx addr)
6b3d1e47
SC
947{
948 switch (GET_CODE (addr))
949 {
950 case LO_SUM:
951 return 1;
952
953 case LABEL_REF:
954 return 2;
955
956 case CONST:
957 {
958 rtx offset = const0_rtx;
b5144086
SC
959
960 addr = eliminate_constant_term (XEXP (addr, 0), & offset);
6b3d1e47
SC
961 if (GET_CODE (addr) == LABEL_REF)
962 return 2;
963
964 if (GET_CODE (addr) != SYMBOL_REF)
965 return 4;
966
967 if (! SMALL_INT (offset))
968 return 2;
969 }
970
b5144086 971 /* Fall through. */
6b3d1e47
SC
972
973 case SYMBOL_REF:
974 return SYMBOL_REF_FLAG (addr) ? 1 : 2;
975
976 case PLUS:
977 {
b5144086
SC
978 rtx plus0 = XEXP (addr, 0);
979 rtx plus1 = XEXP (addr, 1);
6b3d1e47
SC
980
981 if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
982 plus0 = XEXP (addr, 1), plus1 = XEXP (addr, 0);
983
984 if (GET_CODE (plus0) != REG)
985 break;
986
987 switch (GET_CODE (plus1))
988 {
989 case CONST_INT:
990 return SMALL_INT (plus1) ? 1 : 2;
991
992 case CONST:
993 case SYMBOL_REF:
994 case LABEL_REF:
995 case HIGH:
996 case LO_SUM:
997 return iq2000_address_cost (plus1) + 1;
998
999 default:
1000 break;
1001 }
1002 }
1003
1004 default:
1005 break;
1006 }
1007
1008 return 4;
1009}
1010\f
1011/* Make normal rtx_code into something we can index from an array. */
1012
1013static enum internal_test
b7849684 1014map_test_to_internal_test (enum rtx_code test_code)
6b3d1e47
SC
1015{
1016 enum internal_test test = ITEST_MAX;
1017
1018 switch (test_code)
1019 {
1020 case EQ: test = ITEST_EQ; break;
1021 case NE: test = ITEST_NE; break;
1022 case GT: test = ITEST_GT; break;
1023 case GE: test = ITEST_GE; break;
1024 case LT: test = ITEST_LT; break;
1025 case LE: test = ITEST_LE; break;
1026 case GTU: test = ITEST_GTU; break;
1027 case GEU: test = ITEST_GEU; break;
1028 case LTU: test = ITEST_LTU; break;
1029 case LEU: test = ITEST_LEU; break;
1030 default: break;
1031 }
1032
1033 return test;
1034}
1035\f
b5144086
SC
1036/* Generate the code to do a TEST_CODE comparison on two integer values CMP0
1037 and CMP1. P_INVERT is NULL or ptr if branch needs to reverse its test.
1038 The return value RESULT is:
6b3d1e47 1039 (reg:SI xx) The pseudo register the comparison is in
b5144086 1040 0 No register, generate a simple branch. */
6b3d1e47
SC
1041
1042rtx
b7849684
JE
1043gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1,
1044 int *p_invert)
6b3d1e47
SC
1045{
1046 struct cmp_info
1047 {
b5144086
SC
1048 enum rtx_code test_code; /* Code to use in instruction (LT vs. LTU). */
1049 int const_low; /* Low bound of constant we can accept. */
1050 int const_high; /* High bound of constant we can accept. */
1051 int const_add; /* Constant to add (convert LE -> LT). */
1052 int reverse_regs; /* Reverse registers in test. */
1053 int invert_const; /* != 0 if invert value if cmp1 is constant. */
1054 int invert_reg; /* != 0 if invert value if cmp1 is register. */
6b3d1e47
SC
1055 int unsignedp; /* != 0 for unsigned comparisons. */
1056 };
1057
b5144086
SC
1058 static struct cmp_info info[ (int)ITEST_MAX ] =
1059 {
6b3d1e47
SC
1060 { XOR, 0, 65535, 0, 0, 0, 0, 0 }, /* EQ */
1061 { XOR, 0, 65535, 0, 0, 1, 1, 0 }, /* NE */
1062 { LT, -32769, 32766, 1, 1, 1, 0, 0 }, /* GT */
1063 { LT, -32768, 32767, 0, 0, 1, 1, 0 }, /* GE */
1064 { LT, -32768, 32767, 0, 0, 0, 0, 0 }, /* LT */
1065 { LT, -32769, 32766, 1, 1, 0, 1, 0 }, /* LE */
1066 { LTU, -32769, 32766, 1, 1, 1, 0, 1 }, /* GTU */
1067 { LTU, -32768, 32767, 0, 0, 1, 1, 1 }, /* GEU */
1068 { LTU, -32768, 32767, 0, 0, 0, 0, 1 }, /* LTU */
1069 { LTU, -32769, 32766, 1, 1, 0, 1, 1 }, /* LEU */
1070 };
1071
1072 enum internal_test test;
1073 enum machine_mode mode;
1074 struct cmp_info *p_info;
1075 int branch_p;
1076 int eqne_p;
1077 int invert;
1078 rtx reg;
1079 rtx reg2;
1080
1081 test = map_test_to_internal_test (test_code);
1082 if (test == ITEST_MAX)
1083 abort ();
1084
1085 p_info = &info[(int) test];
1086 eqne_p = (p_info->test_code == XOR);
1087
1088 mode = GET_MODE (cmp0);
1089 if (mode == VOIDmode)
1090 mode = GET_MODE (cmp1);
1091
b5144086 1092 /* Eliminate simple branches. */
6b3d1e47
SC
1093 branch_p = (result == 0);
1094 if (branch_p)
1095 {
1096 if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
1097 {
b5144086 1098 /* Comparisons against zero are simple branches. */
6b3d1e47
SC
1099 if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
1100 return 0;
1101
1102 /* Test for beq/bne. */
1103 if (eqne_p)
1104 return 0;
1105 }
1106
b5144086 1107 /* Allocate a pseudo to calculate the value in. */
6b3d1e47
SC
1108 result = gen_reg_rtx (mode);
1109 }
1110
1111 /* Make sure we can handle any constants given to us. */
1112 if (GET_CODE (cmp0) == CONST_INT)
1113 cmp0 = force_reg (mode, cmp0);
1114
1115 if (GET_CODE (cmp1) == CONST_INT)
1116 {
1117 HOST_WIDE_INT value = INTVAL (cmp1);
1118
1119 if (value < p_info->const_low
1120 || value > p_info->const_high)
1121 cmp1 = force_reg (mode, cmp1);
1122 }
1123
1124 /* See if we need to invert the result. */
1125 invert = (GET_CODE (cmp1) == CONST_INT
1126 ? p_info->invert_const : p_info->invert_reg);
1127
1128 if (p_invert != (int *)0)
1129 {
1130 *p_invert = invert;
1131 invert = 0;
1132 }
1133
1134 /* Comparison to constants, may involve adding 1 to change a LT into LE.
1135 Comparison between two registers, may involve switching operands. */
1136 if (GET_CODE (cmp1) == CONST_INT)
1137 {
1138 if (p_info->const_add != 0)
1139 {
1140 HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
1141
1142 /* If modification of cmp1 caused overflow,
1143 we would get the wrong answer if we follow the usual path;
1144 thus, x > 0xffffffffU would turn into x > 0U. */
1145 if ((p_info->unsignedp
1146 ? (unsigned HOST_WIDE_INT) new >
1147 (unsigned HOST_WIDE_INT) INTVAL (cmp1)
1148 : new > INTVAL (cmp1))
1149 != (p_info->const_add > 0))
1150 {
1151 /* This test is always true, but if INVERT is true then
1152 the result of the test needs to be inverted so 0 should
1153 be returned instead. */
1154 emit_move_insn (result, invert ? const0_rtx : const_true_rtx);
1155 return result;
1156 }
1157 else
1158 cmp1 = GEN_INT (new);
1159 }
1160 }
1161
1162 else if (p_info->reverse_regs)
1163 {
1164 rtx temp = cmp0;
1165 cmp0 = cmp1;
1166 cmp1 = temp;
1167 }
1168
1169 if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
1170 reg = cmp0;
1171 else
1172 {
1173 reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result;
1c563bed 1174 convert_move (reg, gen_rtx_fmt_ee (p_info->test_code, mode, cmp0, cmp1), 0);
6b3d1e47
SC
1175 }
1176
1177 if (test == ITEST_NE)
1178 {
f1c25d3b 1179 convert_move (result, gen_rtx_GTU (mode, reg, const0_rtx), 0);
6b3d1e47
SC
1180 if (p_invert != NULL)
1181 *p_invert = 0;
1182 invert = 0;
1183 }
1184
1185 else if (test == ITEST_EQ)
1186 {
1187 reg2 = invert ? gen_reg_rtx (mode) : result;
1188 convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0);
1189 reg = reg2;
1190 }
1191
1192 if (invert)
1193 {
1194 rtx one;
1195
1196 one = const1_rtx;
f1c25d3b 1197 convert_move (result, gen_rtx_XOR (mode, reg, one), 0);
6b3d1e47
SC
1198 }
1199
1200 return result;
1201}
1202\f
1203/* Emit the common code for doing conditional branches.
1204 operand[0] is the label to jump to.
1205 The comparison operands are saved away by cmp{si,di,sf,df}. */
1206
1207void
b7849684 1208gen_conditional_branch (rtx operands[], enum rtx_code test_code)
6b3d1e47
SC
1209{
1210 enum cmp_type type = branch_type;
1211 rtx cmp0 = branch_cmp[0];
1212 rtx cmp1 = branch_cmp[1];
1213 enum machine_mode mode;
1214 rtx reg;
1215 int invert;
1216 rtx label1, label2;
1217
1218 switch (type)
1219 {
1220 case CMP_SI:
1221 case CMP_DI:
1222 mode = type == CMP_SI ? SImode : DImode;
1223 invert = 0;
1224 reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
1225
1226 if (reg)
1227 {
1228 cmp0 = reg;
1229 cmp1 = const0_rtx;
1230 test_code = NE;
1231 }
1232 else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
4375e090 1233 /* We don't want to build a comparison against a nonzero
6b3d1e47
SC
1234 constant. */
1235 cmp1 = force_reg (mode, cmp1);
1236
1237 break;
1238
1239 case CMP_SF:
1240 case CMP_DF:
1241 reg = gen_reg_rtx (CCmode);
1242
b5144086 1243 /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */
6b3d1e47 1244 emit_insn (gen_rtx_SET (VOIDmode, reg,
1c563bed 1245 gen_rtx_fmt_ee (test_code == NE ? EQ : test_code,
0f4c242b 1246 CCmode, cmp0, cmp1)));
6b3d1e47
SC
1247
1248 test_code = test_code == NE ? EQ : NE;
1249 mode = CCmode;
1250 cmp0 = reg;
1251 cmp1 = const0_rtx;
1252 invert = 0;
1253 break;
1254
1255 default:
0f4c242b
KH
1256 abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1),
1257 "bad test");
6b3d1e47
SC
1258 }
1259
1260 /* Generate the branch. */
6b3d1e47
SC
1261 label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);
1262 label2 = pc_rtx;
1263
1264 if (invert)
1265 {
1266 label2 = label1;
1267 label1 = pc_rtx;
1268 }
1269
1270 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1271 gen_rtx_IF_THEN_ELSE (VOIDmode,
0f4c242b
KH
1272 gen_rtx_fmt_ee (test_code,
1273 mode,
1274 cmp0, cmp1),
6b3d1e47
SC
1275 label1, label2)));
1276}
1277\f
b5144086 1278/* Initialize CUM for a function FNTYPE. */
6b3d1e47
SC
1279
1280void
b7849684
JE
1281init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1282 rtx libname ATTRIBUTE_UNUSED)
6b3d1e47
SC
1283{
1284 static CUMULATIVE_ARGS zero_cum;
b5144086
SC
1285 tree param;
1286 tree next_param;
6b3d1e47
SC
1287
1288 if (TARGET_DEBUG_D_MODE)
1289 {
1290 fprintf (stderr,
b5144086 1291 "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype);
6b3d1e47
SC
1292
1293 if (!fntype)
1294 fputc ('\n', stderr);
1295
1296 else
1297 {
1298 tree ret_type = TREE_TYPE (fntype);
b5144086 1299
6b3d1e47
SC
1300 fprintf (stderr, ", fntype code = %s, ret code = %s\n",
1301 tree_code_name[(int)TREE_CODE (fntype)],
1302 tree_code_name[(int)TREE_CODE (ret_type)]);
1303 }
1304 }
1305
1306 *cum = zero_cum;
1307
1308 /* Determine if this function has variable arguments. This is
1309 indicated by the last argument being 'void_type_mode' if there
1310 are no variable arguments. The standard IQ2000 calling sequence
1311 passes all arguments in the general purpose registers in this case. */
1312
1313 for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
1314 param != 0; param = next_param)
1315 {
1316 next_param = TREE_CHAIN (param);
1317 if (next_param == 0 && TREE_VALUE (param) != void_type_node)
1318 cum->gp_reg_found = 1;
1319 }
1320}
1321
b5144086
SC
1322/* Advance the argument of type TYPE and mode MODE to the next argument
1323 position in CUM. */
6b3d1e47
SC
1324
1325void
b7849684
JE
1326function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1327 int named)
6b3d1e47
SC
1328{
1329 if (TARGET_DEBUG_D_MODE)
1330 {
1331 fprintf (stderr,
1332 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1333 cum->gp_reg_found, cum->arg_number, cum->arg_words,
1334 GET_MODE_NAME (mode));
1335 fprintf (stderr, HOST_PTR_PRINTF, (const PTR) type);
1336 fprintf (stderr, ", %d )\n\n", named);
1337 }
1338
1339 cum->arg_number++;
1340 switch (mode)
1341 {
1342 case VOIDmode:
1343 break;
1344
1345 default:
1346 if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
1347 && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
1348 abort ();
1349
1350 cum->gp_reg_found = 1;
1351 cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
1352 / UNITS_PER_WORD);
1353 break;
1354
1355 case BLKmode:
1356 cum->gp_reg_found = 1;
1357 cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
1358 / UNITS_PER_WORD);
1359 break;
1360
1361 case SFmode:
b5144086 1362 cum->arg_words ++;
6b3d1e47
SC
1363 if (! cum->gp_reg_found && cum->arg_number <= 2)
1364 cum->fp_code += 1 << ((cum->arg_number - 1) * 2);
1365 break;
1366
1367 case DFmode:
1368 cum->arg_words += 2;
1369 if (! cum->gp_reg_found && cum->arg_number <= 2)
1370 cum->fp_code += 2 << ((cum->arg_number - 1) * 2);
1371 break;
1372
1373 case DImode:
1374 cum->gp_reg_found = 1;
1375 cum->arg_words += 2;
1376 break;
1377
1378 case QImode:
1379 case HImode:
1380 case SImode:
1381 cum->gp_reg_found = 1;
b5144086 1382 cum->arg_words ++;
6b3d1e47
SC
1383 break;
1384 }
1385}
1386
b5144086
SC
1387/* Return an RTL expression containing the register for the given mode MODE
1388 and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */
6b3d1e47
SC
1389
1390struct rtx_def *
b7849684
JE
1391function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1392 int named)
6b3d1e47
SC
1393{
1394 rtx ret;
1395 int regbase = -1;
1396 int bias = 0;
1397 unsigned int *arg_words = &cum->arg_words;
1398 int struct_p = (type != 0
1399 && (TREE_CODE (type) == RECORD_TYPE
1400 || TREE_CODE (type) == UNION_TYPE
1401 || TREE_CODE (type) == QUAL_UNION_TYPE));
1402
1403 if (TARGET_DEBUG_D_MODE)
1404 {
1405 fprintf (stderr,
1406 "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
1407 cum->gp_reg_found, cum->arg_number, cum->arg_words,
1408 GET_MODE_NAME (mode));
1409 fprintf (stderr, HOST_PTR_PRINTF, (const PTR) type);
1410 fprintf (stderr, ", %d ) = ", named);
1411 }
1412
1413
1414 cum->last_arg_fp = 0;
1415 switch (mode)
1416 {
1417 case SFmode:
1418 regbase = GP_ARG_FIRST;
1419 break;
1420
1421 case DFmode:
1422 cum->arg_words += cum->arg_words & 1;
1423
1424 regbase = GP_ARG_FIRST;
1425 break;
1426
1427 default:
1428 if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
1429 && GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
1430 abort ();
1431
1432 /* Drops through. */
1433 case BLKmode:
1434 if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)
1435 cum->arg_words += (cum->arg_words & 1);
1436 regbase = GP_ARG_FIRST;
1437 break;
1438
1439 case VOIDmode:
1440 case QImode:
1441 case HImode:
1442 case SImode:
1443 regbase = GP_ARG_FIRST;
1444 break;
1445
1446 case DImode:
1447 cum->arg_words += (cum->arg_words & 1);
1448 regbase = GP_ARG_FIRST;
1449 }
1450
1451 if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS)
1452 {
1453 if (TARGET_DEBUG_D_MODE)
1454 fprintf (stderr, "<stack>%s\n", struct_p ? ", [struct]" : "");
1455
1456 ret = 0;
1457 }
1458 else
1459 {
1460 if (regbase == -1)
1461 abort ();
1462
1463 if (! type || TREE_CODE (type) != RECORD_TYPE
1464 || ! named || ! TYPE_SIZE_UNIT (type)
1465 || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
1466 ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
1467 else
1468 {
1469 tree field;
1470
1471 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
1472 if (TREE_CODE (field) == FIELD_DECL
1473 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
1474 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
1475 && host_integerp (bit_position (field), 0)
1476 && int_bit_position (field) % BITS_PER_WORD == 0)
1477 break;
1478
1479 /* If the whole struct fits a DFmode register,
1480 we don't need the PARALLEL. */
1481 if (! field || mode == DFmode)
1482 ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
1483 else
1484 {
1485 unsigned int chunks;
1486 HOST_WIDE_INT bitpos;
1487 unsigned int regno;
1488 unsigned int i;
1489
1490 /* ??? If this is a packed structure, then the last hunk won't
1491 be 64 bits. */
6b3d1e47
SC
1492 chunks
1493 = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
1494 if (chunks + *arg_words + bias > (unsigned) MAX_ARGS_IN_REGISTERS)
1495 chunks = MAX_ARGS_IN_REGISTERS - *arg_words - bias;
1496
b5144086 1497 /* Assign_parms checks the mode of ENTRY_PARM, so we must
6b3d1e47
SC
1498 use the actual mode here. */
1499 ret = gen_rtx_PARALLEL (mode, rtvec_alloc (chunks));
1500
1501 bitpos = 0;
1502 regno = regbase + *arg_words + bias;
1503 field = TYPE_FIELDS (type);
1504 for (i = 0; i < chunks; i++)
1505 {
1506 rtx reg;
1507
1508 for (; field; field = TREE_CHAIN (field))
1509 if (TREE_CODE (field) == FIELD_DECL
1510 && int_bit_position (field) >= bitpos)
1511 break;
1512
1513 if (field
1514 && int_bit_position (field) == bitpos
1515 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
1516 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
1517 reg = gen_rtx_REG (DFmode, regno++);
1518 else
1519 reg = gen_rtx_REG (word_mode, regno);
1520
1521 XVECEXP (ret, 0, i)
1522 = gen_rtx_EXPR_LIST (VOIDmode, reg,
1523 GEN_INT (bitpos / BITS_PER_UNIT));
1524
1525 bitpos += 64;
1526 regno++;
1527 }
1528 }
1529 }
1530
1531 if (TARGET_DEBUG_D_MODE)
1532 fprintf (stderr, "%s%s\n", reg_names[regbase + *arg_words + bias],
1533 struct_p ? ", [struct]" : "");
1534 }
1535
1536 /* We will be called with a mode of VOIDmode after the last argument
1537 has been seen. Whatever we return will be passed to the call
1538 insn. If we need any shifts for small structures, return them in
1539 a PARALLEL. */
1540 if (mode == VOIDmode)
1541 {
1542 if (cum->num_adjusts > 0)
f1c25d3b 1543 ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
6b3d1e47
SC
1544 gen_rtvec_v (cum->num_adjusts, cum->adjust));
1545 }
1546
1547 return ret;
1548}
1549
1550int
b7849684
JE
1551function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1552 tree type ATTRIBUTE_UNUSED,
1553 int named ATTRIBUTE_UNUSED)
6b3d1e47
SC
1554{
1555 if (mode == DImode
1556 && cum->arg_words == MAX_ARGS_IN_REGISTERS - (unsigned)1)
1557 {
1558 if (TARGET_DEBUG_D_MODE)
1559 fprintf (stderr, "function_arg_partial_nregs = 1\n");
1560
1561 return 1;
1562 }
1563
1564 return 0;
1565}
1566\f
1567/* Implement va_start. */
1568
1569void
b7849684 1570iq2000_va_start (tree valist, rtx nextarg)
6b3d1e47
SC
1571{
1572 int int_arg_words;
b5144086 1573 /* Find out how many non-float named formals. */
6b3d1e47 1574 int gpr_save_area_size;
b5144086 1575 /* Note UNITS_PER_WORD is 4 bytes. */
6b3d1e47 1576 int_arg_words = current_function_args_info.arg_words;
b5144086 1577
6b3d1e47 1578 if (int_arg_words < 8 )
b5144086 1579 /* Adjust for the prologue's economy measure. */
6b3d1e47
SC
1580 gpr_save_area_size = (8 - int_arg_words) * UNITS_PER_WORD;
1581 else
1582 gpr_save_area_size = 0;
1583
1584 /* Everything is in the GPR save area, or in the overflow
1585 area which is contiguous with it. */
b5144086 1586 nextarg = plus_constant (nextarg, - gpr_save_area_size);
6b3d1e47
SC
1587 std_expand_builtin_va_start (valist, nextarg);
1588}
1589
1590/* Implement va_arg. */
1591
1592rtx
b7849684 1593iq2000_va_arg (tree valist, tree type)
6b3d1e47
SC
1594{
1595 HOST_WIDE_INT size, rsize;
1596 rtx addr_rtx;
1597 tree t;
6b3d1e47
SC
1598 int indirect;
1599 rtx r, lab_over = NULL_RTX, lab_false;
1600 tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
1601 tree ovfl, gtop, ftop, goff, foff;
1602
1603 size = int_size_in_bytes (type);
1604 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
1605 indirect
1606 = function_arg_pass_by_reference (NULL, TYPE_MODE (type), type, 0);
1607 if (indirect)
1608 {
1609 size = POINTER_SIZE / BITS_PER_UNIT;
1610 rsize = UNITS_PER_WORD;
1611 }
1612
1613 addr_rtx = gen_reg_rtx (Pmode);
1614
1615 {
1616 /* Case of all args in a merged stack. No need to check bounds,
1617 just advance valist along the stack. */
6b3d1e47 1618 tree gpr = valist;
b5144086 1619
6b3d1e47
SC
1620 if (! indirect
1621 && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)
1622 {
1623 t = build (PLUS_EXPR, TREE_TYPE (gpr), gpr,
1624 build_int_2 (2*UNITS_PER_WORD - 1, 0));
1625 t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
1626 build_int_2 (-2*UNITS_PER_WORD, -1));
1627 t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);
1628 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1629 }
1630
1631 t = build (POSTINCREMENT_EXPR, TREE_TYPE (gpr), gpr,
1632 size_int (rsize));
1633 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
1634 if (r != addr_rtx)
1635 emit_move_insn (addr_rtx, r);
1636
5b8d96f1 1637 /* Flush the POSTINCREMENT. */
6b3d1e47
SC
1638 emit_queue();
1639
1640 if (indirect)
1641 {
1642 r = gen_rtx_MEM (Pmode, addr_rtx);
1643 set_mem_alias_set (r, get_varargs_alias_set ());
1644 emit_move_insn (addr_rtx, r);
1645 }
1646 else
1647 {
1648 if (BYTES_BIG_ENDIAN && rsize != size)
1649 addr_rtx = plus_constant (addr_rtx, rsize - size);
1650 }
1651 return addr_rtx;
1652 }
1653
1654 /* Not a simple merged stack. Need ptrs and indexes left by va_start. */
6b3d1e47
SC
1655 f_ovfl = TYPE_FIELDS (va_list_type_node);
1656 f_gtop = TREE_CHAIN (f_ovfl);
1657 f_ftop = TREE_CHAIN (f_gtop);
1658 f_goff = TREE_CHAIN (f_ftop);
1659 f_foff = TREE_CHAIN (f_goff);
1660
1661 ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl);
1662 gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop);
1663 ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop);
1664 goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff);
1665 foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff);
1666
1667 lab_false = gen_label_rtx ();
1668 lab_over = gen_label_rtx ();
1669
1670 if (TREE_CODE (type) == REAL_TYPE)
1671 {
6b3d1e47
SC
1672 /* Emit code to branch if foff == 0. */
1673 r = expand_expr (foff, NULL_RTX, TYPE_MODE (TREE_TYPE (foff)),
1674 EXPAND_NORMAL);
1675 emit_cmp_and_jump_insns (r, const0_rtx, EQ,
1676 const1_rtx, GET_MODE (r), 1, lab_false);
1677
b5144086 1678 /* Emit code for addr_rtx = ftop - foff. */
6b3d1e47
SC
1679 t = build (MINUS_EXPR, TREE_TYPE (ftop), ftop, foff );
1680 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
1681 if (r != addr_rtx)
1682 emit_move_insn (addr_rtx, r);
1683
1684 /* Emit code for foff-=8.
b5144086 1685 Advances the offset up FPR save area by one double. */
6b3d1e47
SC
1686 t = build (MINUS_EXPR, TREE_TYPE (foff), foff, build_int_2 (8, 0));
1687 t = build (MODIFY_EXPR, TREE_TYPE (foff), foff, t);
1688 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1689
b5144086 1690 emit_queue ();
6b3d1e47
SC
1691 emit_jump (lab_over);
1692 emit_barrier ();
1693 emit_label (lab_false);
1694
1695 /* If a 4-byte int is followed by an 8-byte float, then
1696 natural alignment causes a 4 byte gap.
1697 So, dynamically adjust ovfl up to a multiple of 8. */
1698 t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), ovfl,
1699 build_int_2 (7, 0));
1700 t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, t);
1701 t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
1702 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1703
1704 /* Emit code for addr_rtx = the ovfl pointer into overflow area.
1705 Postincrement the ovfl pointer by 8. */
1706 t = build (POSTINCREMENT_EXPR, TREE_TYPE(ovfl), ovfl,
1707 size_int (8));
1708 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
1709 if (r != addr_rtx)
1710 emit_move_insn (addr_rtx, r);
1711
1712 emit_queue();
1713 emit_label (lab_over);
1714 return addr_rtx;
1715 }
1716 else
1717 {
b5144086 1718 /* Not REAL_TYPE. */
6b3d1e47
SC
1719 int step_size;
1720
1721 if (TREE_CODE (type) == INTEGER_TYPE
1722 && TYPE_PRECISION (type) == 64)
1723 {
1724 /* int takes 32 bits of the GPR save area, but
1725 longlong takes an aligned 64 bits. So, emit code
1726 to zero the low order bits of goff, thus aligning
1727 the later calculation of (gtop-goff) upwards. */
1728 t = build (BIT_AND_EXPR, TREE_TYPE (goff), goff,
1729 build_int_2 (-8, -1));
1730 t = build (MODIFY_EXPR, TREE_TYPE (goff), goff, t);
1731 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1732 }
1733
1734 /* Emit code to branch if goff == 0. */
1735 r = expand_expr (goff, NULL_RTX, TYPE_MODE (TREE_TYPE (goff)),
1736 EXPAND_NORMAL);
1737 emit_cmp_and_jump_insns (r, const0_rtx, EQ,
1738 const1_rtx, GET_MODE (r), 1, lab_false);
1739
1740 /* Emit code for addr_rtx = gtop - goff. */
1741 t = build (MINUS_EXPR, TREE_TYPE (gtop), gtop, goff);
1742 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
1743 if (r != addr_rtx)
1744 emit_move_insn (addr_rtx, r);
1745
1746 if (TYPE_PRECISION (type) == 64)
1747 step_size = 8;
1748 else
1749 step_size = UNITS_PER_WORD;
1750
1751 /* Emit code for goff = goff - step_size.
1752 Advances the offset up GPR save area over the item. */
1753 t = build (MINUS_EXPR, TREE_TYPE (goff), goff,
1754 build_int_2 (step_size, 0));
1755 t = build (MODIFY_EXPR, TREE_TYPE (goff), goff, t);
1756 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1757
1758 emit_queue();
1759 emit_jump (lab_over);
1760 emit_barrier ();
1761 emit_label (lab_false);
1762
b5144086 1763 /* Emit code for addr_rtx -> overflow area, postinc by step_size. */
6b3d1e47
SC
1764 t = build (POSTINCREMENT_EXPR, TREE_TYPE(ovfl), ovfl,
1765 size_int (step_size));
1766 r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
1767 if (r != addr_rtx)
1768 emit_move_insn (addr_rtx, r);
1769
1770 emit_queue();
1771 emit_label (lab_over);
1772
1773 if (indirect)
1774 {
1775 r = gen_rtx_MEM (Pmode, addr_rtx);
1776 set_mem_alias_set (r, get_varargs_alias_set ());
1777 emit_move_insn (addr_rtx, r);
1778 }
1779 else
1780 {
1781 if (BYTES_BIG_ENDIAN && rsize != size)
1782 addr_rtx = plus_constant (addr_rtx, rsize - size);
1783 }
1784 return addr_rtx;
1785 }
1786}
1787\f
b5144086 1788/* Allocate a chunk of memory for per-function machine-dependent data. */
6b3d1e47 1789
b5144086
SC
1790static struct machine_function *
1791iq2000_init_machine_status (void)
6b3d1e47 1792{
b5144086
SC
1793 struct machine_function *f;
1794
1795 f = ggc_alloc_cleared (sizeof (struct machine_function));
1796
1797 return f;
6b3d1e47 1798}
b5144086
SC
1799
1800static enum processor_type
1801iq2000_parse_cpu (const char * cpu_string)
1802{
1803 const char *p = cpu_string;
1804 enum processor_type cpu;
1805
1806 cpu = PROCESSOR_DEFAULT;
1807 switch (p[2])
1808 {
1809 case '1':
1810 if (!strcmp (p, "iq10"))
1811 cpu = PROCESSOR_IQ10;
1812 break;
1813 case '2':
1814 if (!strcmp (p, "iq2000"))
1815 cpu = PROCESSOR_IQ2000;
1816 break;
1817 }
1818
1819 return cpu;
1820}
1821
6b3d1e47
SC
1822/* Detect any conflicts in the switches. */
1823
1824void
b7849684 1825override_options (void)
6b3d1e47 1826{
b5144086 1827 enum processor_type iq2000_cpu;
6b3d1e47
SC
1828
1829 target_flags &= ~MASK_GPOPT;
1830
1831 iq2000_isa = IQ2000_ISA_DEFAULT;
1832
1833 /* Identify the processor type. */
1834
1835 if (iq2000_cpu_string != 0)
1836 {
1837 iq2000_cpu = iq2000_parse_cpu (iq2000_cpu_string);
1838 if (iq2000_cpu == PROCESSOR_DEFAULT)
1839 {
1840 error ("bad value (%s) for -mcpu= switch", iq2000_arch_string);
1841 iq2000_cpu_string = "default";
1842 }
1843 iq2000_arch = iq2000_cpu;
1844 iq2000_tune = iq2000_cpu;
1845 }
1846
1847 if (iq2000_arch_string == 0
1848 || ! strcmp (iq2000_arch_string, "default")
1849 || ! strcmp (iq2000_arch_string, "DEFAULT"))
1850 {
1851 switch (iq2000_isa)
1852 {
1853 default:
1854 iq2000_arch_string = "iq2000";
1855 iq2000_arch = PROCESSOR_IQ2000;
1856 break;
1857 }
1858 }
1859 else
1860 {
1861 iq2000_arch = iq2000_parse_cpu (iq2000_arch_string);
1862 if (iq2000_arch == PROCESSOR_DEFAULT)
1863 {
1864 error ("bad value (%s) for -march= switch", iq2000_arch_string);
1865 iq2000_arch_string = "default";
1866 }
1867 if (iq2000_arch == PROCESSOR_IQ10)
1868 {
1869 error ("The compiler does not support -march=%s.", iq2000_arch_string);
1870 iq2000_arch_string = "default";
1871 }
1872 }
1873
1874 iq2000_print_operand_punct['?'] = 1;
1875 iq2000_print_operand_punct['#'] = 1;
1876 iq2000_print_operand_punct['&'] = 1;
1877 iq2000_print_operand_punct['!'] = 1;
1878 iq2000_print_operand_punct['*'] = 1;
1879 iq2000_print_operand_punct['@'] = 1;
1880 iq2000_print_operand_punct['.'] = 1;
1881 iq2000_print_operand_punct['('] = 1;
1882 iq2000_print_operand_punct[')'] = 1;
1883 iq2000_print_operand_punct['['] = 1;
1884 iq2000_print_operand_punct[']'] = 1;
1885 iq2000_print_operand_punct['<'] = 1;
1886 iq2000_print_operand_punct['>'] = 1;
1887 iq2000_print_operand_punct['{'] = 1;
1888 iq2000_print_operand_punct['}'] = 1;
1889 iq2000_print_operand_punct['^'] = 1;
1890 iq2000_print_operand_punct['$'] = 1;
1891 iq2000_print_operand_punct['+'] = 1;
1892 iq2000_print_operand_punct['~'] = 1;
1893
1894 /* Save GPR registers in word_mode sized hunks. word_mode hasn't been
1895 initialized yet, so we can't use that here. */
1896 gpr_mode = SImode;
1897
1898 /* Function to allocate machine-dependent function status. */
b5144086 1899 init_machine_status = iq2000_init_machine_status;
6b3d1e47
SC
1900}
1901\f
1902/* The arg pointer (which is eliminated) points to the virtual frame pointer,
1903 while the frame pointer (which may be eliminated) points to the stack
1904 pointer after the initial adjustments. */
1905
1906HOST_WIDE_INT
b7849684 1907iq2000_debugger_offset (rtx addr, HOST_WIDE_INT offset)
6b3d1e47
SC
1908{
1909 rtx offset2 = const0_rtx;
b5144086 1910 rtx reg = eliminate_constant_term (addr, & offset2);
6b3d1e47
SC
1911
1912 if (offset == 0)
1913 offset = INTVAL (offset2);
1914
1915 if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
1916 || reg == hard_frame_pointer_rtx)
1917 {
b5144086 1918 HOST_WIDE_INT frame_size = (!cfun->machine->initialized)
6b3d1e47 1919 ? compute_frame_size (get_frame_size ())
b5144086 1920 : cfun->machine->total_size;
6b3d1e47
SC
1921
1922 offset = offset - frame_size;
1923 }
1924
1925 return offset;
1926}
1927\f
1928/* If defined, a C statement to be executed just prior to the output of
1929 assembler code for INSN, to modify the extracted operands so they will be
1930 output differently.
1931
1932 Here the argument OPVEC is the vector containing the operands extracted
1933 from INSN, and NOPERANDS is the number of elements of the vector which
1934 contain meaningful data for this insn. The contents of this vector are
1935 what will be used to convert the insn template into assembler code, so you
1936 can change the assembler output by changing the contents of the vector.
1937
1938 We use it to check if the current insn needs a nop in front of it because
1939 of load delays, and also to update the delay slot statistics. */
1940
1941void
b7849684
JE
1942final_prescan_insn (rtx insn, rtx opvec[] ATTRIBUTE_UNUSED,
1943 int noperands ATTRIBUTE_UNUSED)
6b3d1e47
SC
1944{
1945 if (dslots_number_nops > 0)
1946 {
1947 rtx pattern = PATTERN (insn);
1948 int length = get_attr_length (insn);
1949
b5144086 1950 /* Do we need to emit a NOP? */
6b3d1e47
SC
1951 if (length == 0
1952 || (iq2000_load_reg != 0 && reg_mentioned_p (iq2000_load_reg, pattern))
1953 || (iq2000_load_reg2 != 0 && reg_mentioned_p (iq2000_load_reg2, pattern))
1954 || (iq2000_load_reg3 != 0 && reg_mentioned_p (iq2000_load_reg3, pattern))
1955 || (iq2000_load_reg4 != 0
1956 && reg_mentioned_p (iq2000_load_reg4, pattern)))
1957 fputs ("\tnop\n", asm_out_file);
1958
1959 else
b5144086 1960 dslots_load_filled ++;
6b3d1e47
SC
1961
1962 while (--dslots_number_nops > 0)
1963 fputs ("\tnop\n", asm_out_file);
1964
1965 iq2000_load_reg = 0;
1966 iq2000_load_reg2 = 0;
1967 iq2000_load_reg3 = 0;
1968 iq2000_load_reg4 = 0;
1969 }
1970
b5144086 1971 if ( (GET_CODE (insn) == JUMP_INSN
6b3d1e47
SC
1972 || GET_CODE (insn) == CALL_INSN
1973 || (GET_CODE (PATTERN (insn)) == RETURN))
1974 && NEXT_INSN (PREV_INSN (insn)) == insn)
1975 {
1976 rtx nop_insn = emit_insn_after (gen_nop (), insn);
b5144086 1977
6b3d1e47
SC
1978 INSN_ADDRESSES_NEW (nop_insn, -1);
1979 }
1980
1981 if (TARGET_STATS
1982 && (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN))
b5144086 1983 dslots_jump_total ++;
6b3d1e47
SC
1984}
1985\f
1986/* Return the bytes needed to compute the frame pointer from the current
b5144086 1987 stack pointer where SIZE is the # of var. bytes allocated.
6b3d1e47
SC
1988
1989 IQ2000 stack frames look like:
1990
1991 Before call After call
1992 +-----------------------+ +-----------------------+
1993 high | | | |
1994 mem. | | | |
1995 | caller's temps. | | caller's temps. |
1996 | | | |
1997 +-----------------------+ +-----------------------+
1998 | | | |
1999 | arguments on stack. | | arguments on stack. |
2000 | | | |
2001 +-----------------------+ +-----------------------+
2002 | 4 words to save | | 4 words to save |
2003 | arguments passed | | arguments passed |
2004 | in registers, even | | in registers, even |
2005 SP->| if not passed. | VFP->| if not passed. |
2006 +-----------------------+ +-----------------------+
2007 | |
2008 | fp register save |
2009 | |
2010 +-----------------------+
2011 | |
2012 | gp register save |
2013 | |
2014 +-----------------------+
2015 | |
2016 | local variables |
2017 | |
2018 +-----------------------+
2019 | |
2020 | alloca allocations |
2021 | |
2022 +-----------------------+
2023 | |
2024 | GP save for V.4 abi |
2025 | |
2026 +-----------------------+
2027 | |
2028 | arguments on stack |
2029 | |
2030 +-----------------------+
2031 | 4 words to save |
2032 | arguments passed |
2033 | in registers, even |
2034 low SP->| if not passed. |
b5144086 2035 memory +-----------------------+ */
6b3d1e47
SC
2036
2037HOST_WIDE_INT
b7849684 2038compute_frame_size (HOST_WIDE_INT size)
6b3d1e47
SC
2039{
2040 int regno;
b5144086
SC
2041 HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
2042 HOST_WIDE_INT var_size; /* # bytes that variables take up. */
2043 HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up. */
2044 HOST_WIDE_INT extra_size; /* # extra bytes. */
2045 HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding. */
2046 HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs. */
2047 HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs. */
2048 long mask; /* mask of saved gp registers. */
2049 int fp_inc; /* 1 or 2 depending on the size of fp regs. */
2050 long fp_bits; /* bitmask to use for each fp register. */
6b3d1e47
SC
2051
2052 gp_reg_size = 0;
2053 fp_reg_size = 0;
2054 mask = 0;
2055 extra_size = IQ2000_STACK_ALIGN ((0));
2056 var_size = IQ2000_STACK_ALIGN (size);
2057 args_size = IQ2000_STACK_ALIGN (current_function_outgoing_args_size);
2058
2059 /* If a function dynamically allocates the stack and
b5144086 2060 has 0 for STACK_DYNAMIC_OFFSET then allocate some stack space. */
6b3d1e47
SC
2061 if (args_size == 0 && current_function_calls_alloca)
2062 args_size = 4 * UNITS_PER_WORD;
2063
2064 total_size = var_size + args_size + extra_size;
2065
2066 /* Calculate space needed for gp registers. */
2067 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
2068 {
2069 if (MUST_SAVE_REGISTER (regno))
2070 {
2071 gp_reg_size += GET_MODE_SIZE (gpr_mode);
2072 mask |= 1L << (regno - GP_REG_FIRST);
2073 }
2074 }
2075
2076 /* We need to restore these for the handler. */
2077 if (current_function_calls_eh_return)
2078 {
b5144086
SC
2079 unsigned int i;
2080
6b3d1e47
SC
2081 for (i = 0; ; ++i)
2082 {
2083 regno = EH_RETURN_DATA_REGNO (i);
b5144086 2084 if (regno == (int) INVALID_REGNUM)
6b3d1e47
SC
2085 break;
2086 gp_reg_size += GET_MODE_SIZE (gpr_mode);
2087 mask |= 1L << (regno - GP_REG_FIRST);
2088 }
2089 }
2090
2091 fp_inc = 2;
2092 fp_bits = 3;
2093 gp_reg_rounded = IQ2000_STACK_ALIGN (gp_reg_size);
2094 total_size += gp_reg_rounded + IQ2000_STACK_ALIGN (fp_reg_size);
2095
2096 /* The gp reg is caller saved, so there is no need for leaf routines
2097 (total_size == extra_size) to save the gp reg. */
2098 if (total_size == extra_size
2099 && ! profile_flag)
2100 total_size = extra_size = 0;
2101
2102 total_size += IQ2000_STACK_ALIGN (current_function_pretend_args_size);
2103
2104 /* Save other computed information. */
b5144086
SC
2105 cfun->machine->total_size = total_size;
2106 cfun->machine->var_size = var_size;
2107 cfun->machine->args_size = args_size;
2108 cfun->machine->extra_size = extra_size;
2109 cfun->machine->gp_reg_size = gp_reg_size;
2110 cfun->machine->fp_reg_size = fp_reg_size;
2111 cfun->machine->mask = mask;
2112 cfun->machine->initialized = reload_completed;
2113 cfun->machine->num_gp = gp_reg_size / UNITS_PER_WORD;
6b3d1e47
SC
2114
2115 if (mask)
2116 {
2117 unsigned long offset;
2118
2119 offset = (args_size + extra_size + var_size
2120 + gp_reg_size - GET_MODE_SIZE (gpr_mode));
2121
b5144086
SC
2122 cfun->machine->gp_sp_offset = offset;
2123 cfun->machine->gp_save_offset = offset - total_size;
6b3d1e47
SC
2124 }
2125 else
2126 {
b5144086
SC
2127 cfun->machine->gp_sp_offset = 0;
2128 cfun->machine->gp_save_offset = 0;
6b3d1e47
SC
2129 }
2130
b5144086
SC
2131 cfun->machine->fp_sp_offset = 0;
2132 cfun->machine->fp_save_offset = 0;
6b3d1e47
SC
2133
2134 /* Ok, we're done. */
2135 return total_size;
2136}
2137\f
2138/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
2139 pointer, argument pointer, or return address pointer. TO is either
2140 the stack pointer or hard frame pointer. */
2141
2142int
b7849684 2143iq2000_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
6b3d1e47
SC
2144{
2145 int offset;
2146
2147 compute_frame_size (get_frame_size ());
2148 if ((from) == FRAME_POINTER_REGNUM)
2149 (offset) = 0;
2150 else if ((from) == ARG_POINTER_REGNUM)
b5144086 2151 (offset) = (cfun->machine->total_size);
6b3d1e47 2152 else if ((from) == RETURN_ADDRESS_POINTER_REGNUM)
b5144086
SC
2153 {
2154 if (leaf_function_p ())
2155 (offset) = 0;
2156 else (offset) = cfun->machine->gp_sp_offset
2157 + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT))
2158 * (BYTES_BIG_ENDIAN != 0));
2159 }
6b3d1e47
SC
2160
2161 return offset;
2162}
2163\f
2164/* Common code to emit the insns (or to write the instructions to a file)
2165 to save/restore registers.
2166 Other parts of the code assume that IQ2000_TEMP1_REGNUM (aka large_reg)
2167 is not modified within save_restore_insns. */
2168
2169#define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
2170
2171/* Emit instructions to load the value (SP + OFFSET) into IQ2000_TEMP2_REGNUM
2172 and return an rtl expression for the register. Write the assembly
2173 instructions directly to FILE if it is not null, otherwise emit them as
2174 rtl.
2175
2176 This function is a subroutine of save_restore_insns. It is used when
2177 OFFSET is too large to add in a single instruction. */
2178
2179static rtx
b7849684 2180iq2000_add_large_offset_to_sp (HOST_WIDE_INT offset)
6b3d1e47
SC
2181{
2182 rtx reg = gen_rtx_REG (Pmode, IQ2000_TEMP2_REGNUM);
2183 rtx offset_rtx = GEN_INT (offset);
2184
2185 emit_move_insn (reg, offset_rtx);
2186 emit_insn (gen_addsi3 (reg, reg, stack_pointer_rtx));
2187 return reg;
2188}
2189
2190/* Make INSN frame related and note that it performs the frame-related
2191 operation DWARF_PATTERN. */
2192
2193static void
b7849684 2194iq2000_annotate_frame_insn (rtx insn, rtx dwarf_pattern)
6b3d1e47
SC
2195{
2196 RTX_FRAME_RELATED_P (insn) = 1;
2197 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
2198 dwarf_pattern,
2199 REG_NOTES (insn));
2200}
2201
2202/* Emit a move instruction that stores REG in MEM. Make the instruction
2203 frame related and note that it stores REG at (SP + OFFSET). */
2204
2205static void
b7849684 2206iq2000_emit_frame_related_store (rtx mem, rtx reg, HOST_WIDE_INT offset)
6b3d1e47
SC
2207{
2208 rtx dwarf_address = plus_constant (stack_pointer_rtx, offset);
2209 rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address);
2210
2211 iq2000_annotate_frame_insn (emit_move_insn (mem, reg),
2212 gen_rtx_SET (GET_MODE (reg), dwarf_mem, reg));
2213}
2214
b5144086
SC
2215/* Emit instructions to save/restore registers, as determined by STORE_P. */
2216
6b3d1e47 2217static void
b7849684 2218save_restore_insns (int store_p)
6b3d1e47 2219{
b5144086 2220 long mask = cfun->machine->mask;
6b3d1e47
SC
2221 int regno;
2222 rtx base_reg_rtx;
2223 HOST_WIDE_INT base_offset;
2224 HOST_WIDE_INT gp_offset;
2225 HOST_WIDE_INT end_offset;
2226
2227 if (frame_pointer_needed
2228 && ! BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST))
2229 abort ();
2230
2231 if (mask == 0)
2232 {
2233 base_reg_rtx = 0, base_offset = 0;
2234 return;
2235 }
2236
2237 /* Save registers starting from high to low. The debuggers prefer at least
2238 the return register be stored at func+4, and also it allows us not to
2239 need a nop in the epilog if at least one register is reloaded in
2240 addition to return address. */
2241
2242 /* Save GP registers if needed. */
2243 /* Pick which pointer to use as a base register. For small frames, just
2244 use the stack pointer. Otherwise, use a temporary register. Save 2
2245 cycles if the save area is near the end of a large frame, by reusing
2246 the constant created in the prologue/epilogue to adjust the stack
2247 frame. */
2248
b5144086 2249 gp_offset = cfun->machine->gp_sp_offset;
6b3d1e47 2250 end_offset
b5144086 2251 = gp_offset - (cfun->machine->gp_reg_size
6b3d1e47
SC
2252 - GET_MODE_SIZE (gpr_mode));
2253
2254 if (gp_offset < 0 || end_offset < 0)
2255 internal_error
2256 ("gp_offset (%ld) or end_offset (%ld) is less than zero.",
2257 (long) gp_offset, (long) end_offset);
2258
2259 else if (gp_offset < 32768)
2260 base_reg_rtx = stack_pointer_rtx, base_offset = 0;
2261 else
2262 {
2263 int regno;
2264 int reg_save_count = 0;
b5144086 2265
6b3d1e47
SC
2266 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
2267 if (BITSET_P (mask, regno - GP_REG_FIRST)) reg_save_count += 1;
2268 base_offset = gp_offset - ((reg_save_count - 1) * 4);
2269 base_reg_rtx = iq2000_add_large_offset_to_sp (base_offset);
2270 }
2271
2272 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
2273 {
2274 if (BITSET_P (mask, regno - GP_REG_FIRST))
2275 {
2276 rtx reg_rtx;
2277 rtx mem_rtx
f1c25d3b
KH
2278 = gen_rtx_MEM (gpr_mode,
2279 gen_rtx_PLUS (Pmode, base_reg_rtx,
6b3d1e47
SC
2280 GEN_INT (gp_offset - base_offset)));
2281
2282 if (! current_function_calls_eh_return)
2283 RTX_UNCHANGING_P (mem_rtx) = 1;
2284
f1c25d3b 2285 reg_rtx = gen_rtx_REG (gpr_mode, regno);
6b3d1e47
SC
2286
2287 if (store_p)
2288 iq2000_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
2289 else
2290 {
2291 emit_move_insn (reg_rtx, mem_rtx);
2292 }
2293 gp_offset -= GET_MODE_SIZE (gpr_mode);
2294 }
2295 }
2296}
2297\f
2298/* Expand the prologue into a bunch of separate insns. */
2299
2300void
b7849684 2301iq2000_expand_prologue (void)
6b3d1e47
SC
2302{
2303 int regno;
2304 HOST_WIDE_INT tsize;
2305 int last_arg_is_vararg_marker = 0;
2306 tree fndecl = current_function_decl;
2307 tree fntype = TREE_TYPE (fndecl);
2308 tree fnargs = DECL_ARGUMENTS (fndecl);
2309 rtx next_arg_reg;
2310 int i;
2311 tree next_arg;
2312 tree cur_arg;
2313 CUMULATIVE_ARGS args_so_far;
2314 int store_args_on_stack = (iq2000_can_use_return_insn ());
2315
2316 /* If struct value address is treated as the first argument. */
b5144086 2317 if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
6b3d1e47 2318 && ! current_function_returns_pcc_struct
b5144086 2319 && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
6b3d1e47
SC
2320 {
2321 tree type = build_pointer_type (fntype);
2322 tree function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
2323
2324 DECL_ARG_TYPE (function_result_decl) = type;
2325 TREE_CHAIN (function_result_decl) = fnargs;
2326 fnargs = function_result_decl;
2327 }
2328
2329 /* For arguments passed in registers, find the register number
2330 of the first argument in the variable part of the argument list,
2331 otherwise GP_ARG_LAST+1. Note also if the last argument is
2332 the varargs special argument, and treat it as part of the
2333 variable arguments.
2334
2335 This is only needed if store_args_on_stack is true. */
6b3d1e47
SC
2336 INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0);
2337 regno = GP_ARG_FIRST;
2338
2339 for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
2340 {
2341 tree passed_type = DECL_ARG_TYPE (cur_arg);
2342 enum machine_mode passed_mode = TYPE_MODE (passed_type);
2343 rtx entry_parm;
2344
2345 if (TREE_ADDRESSABLE (passed_type))
2346 {
2347 passed_type = build_pointer_type (passed_type);
2348 passed_mode = Pmode;
2349 }
2350
2351 entry_parm = FUNCTION_ARG (args_so_far, passed_mode, passed_type, 1);
2352
2353 FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, passed_type, 1);
2354 next_arg = TREE_CHAIN (cur_arg);
2355
2356 if (entry_parm && store_args_on_stack)
2357 {
2358 if (next_arg == 0
2359 && DECL_NAME (cur_arg)
2360 && ((0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)),
2361 "__builtin_va_alist"))
2362 || (0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)),
2363 "va_alist"))))
2364 {
2365 last_arg_is_vararg_marker = 1;
2366 break;
2367 }
2368 else
2369 {
2370 int words;
2371
2372 if (GET_CODE (entry_parm) != REG)
2373 abort ();
2374
5b8d96f1 2375 /* Passed in a register, so will get homed automatically. */
6b3d1e47
SC
2376 if (GET_MODE (entry_parm) == BLKmode)
2377 words = (int_size_in_bytes (passed_type) + 3) / 4;
2378 else
2379 words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
2380
2381 regno = REGNO (entry_parm) + words - 1;
2382 }
2383 }
2384 else
2385 {
2386 regno = GP_ARG_LAST+1;
2387 break;
2388 }
2389 }
2390
2391 /* In order to pass small structures by value in registers we need to
2392 shift the value into the high part of the register.
2393 Function_arg has encoded a PARALLEL rtx, holding a vector of
2394 adjustments to be made as the next_arg_reg variable, so we split up the
2395 insns, and emit them separately. */
6b3d1e47
SC
2396 next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
2397 if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
2398 {
2399 rtvec adjust = XVEC (next_arg_reg, 0);
2400 int num = GET_NUM_ELEM (adjust);
2401
2402 for (i = 0; i < num; i++)
2403 {
2404 rtx insn, pattern;
2405
2406 pattern = RTVEC_ELT (adjust, i);
2407 if (GET_CODE (pattern) != SET
2408 || GET_CODE (SET_SRC (pattern)) != ASHIFT)
2409 abort_with_insn (pattern, "Insn is not a shift");
2410 PUT_CODE (SET_SRC (pattern), ASHIFTRT);
2411
2412 insn = emit_insn (pattern);
2413
2414 /* Global life information isn't valid at this point, so we
2415 can't check whether these shifts are actually used. Mark
2416 them MAYBE_DEAD so that flow2 will remove them, and not
2417 complain about dead code in the prologue. */
2418 REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
2419 REG_NOTES (insn));
2420 }
2421 }
2422
2423 tsize = compute_frame_size (get_frame_size ());
2424
2425 /* If this function is a varargs function, store any registers that
2426 would normally hold arguments ($4 - $7) on the stack. */
2427 if (store_args_on_stack
2428 && ((TYPE_ARG_TYPES (fntype) != 0
2429 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2430 != void_type_node))
2431 || last_arg_is_vararg_marker))
2432 {
2433 int offset = (regno - GP_ARG_FIRST) * UNITS_PER_WORD;
2434 rtx ptr = stack_pointer_rtx;
2435
2436 for (; regno <= GP_ARG_LAST; regno++)
2437 {
2438 if (offset != 0)
f1c25d3b
KH
2439 ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
2440 emit_move_insn (gen_rtx_MEM (gpr_mode, ptr),
2441 gen_rtx_REG (gpr_mode, regno));
6b3d1e47
SC
2442
2443 offset += GET_MODE_SIZE (gpr_mode);
2444 }
2445 }
2446
2447 if (tsize > 0)
2448 {
2449 rtx tsize_rtx = GEN_INT (tsize);
2450 rtx adjustment_rtx, insn, dwarf_pattern;
2451
2452 if (tsize > 32767)
2453 {
f1c25d3b 2454 adjustment_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
6b3d1e47
SC
2455 emit_move_insn (adjustment_rtx, tsize_rtx);
2456 }
2457 else
2458 adjustment_rtx = tsize_rtx;
2459
2460 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
2461 adjustment_rtx));
2462
2463 dwarf_pattern = gen_rtx_SET (Pmode, stack_pointer_rtx,
2464 plus_constant (stack_pointer_rtx, -tsize));
2465
2466 iq2000_annotate_frame_insn (insn, dwarf_pattern);
2467
2468 save_restore_insns (1);
2469
2470 if (frame_pointer_needed)
2471 {
2472 rtx insn = 0;
2473
2474 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
2475 stack_pointer_rtx));
2476
2477 if (insn)
2478 RTX_FRAME_RELATED_P (insn) = 1;
2479 }
2480 }
2481
2482 emit_insn (gen_blockage ());
2483}
2484\f
2485/* Expand the epilogue into a bunch of separate insns. */
2486
2487void
b7849684 2488iq2000_expand_epilogue (void)
6b3d1e47 2489{
b5144086 2490 HOST_WIDE_INT tsize = cfun->machine->total_size;
6b3d1e47
SC
2491 rtx tsize_rtx = GEN_INT (tsize);
2492 rtx tmp_rtx = (rtx)0;
2493
2494 if (iq2000_can_use_return_insn ())
2495 {
2496 emit_insn (gen_return ());
2497 return;
2498 }
2499
2500 if (tsize > 32767)
2501 {
2502 tmp_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
2503 emit_move_insn (tmp_rtx, tsize_rtx);
2504 tsize_rtx = tmp_rtx;
2505 }
2506
2507 if (tsize > 0)
2508 {
2509 if (frame_pointer_needed)
2510 {
2511 emit_insn (gen_blockage ());
2512
2513 emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
2514 }
2515
2516 save_restore_insns (0);
2517
2518 if (current_function_calls_eh_return)
2519 {
2520 rtx eh_ofs = EH_RETURN_STACKADJ_RTX;
2521 emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx));
2522 tsize_rtx = eh_ofs;
2523 }
2524
2525 emit_insn (gen_blockage ());
2526
2527 if (tsize != 0 || current_function_calls_eh_return)
2528 {
2529 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2530 tsize_rtx));
2531 }
2532 }
2533
2534 if (current_function_calls_eh_return)
2535 {
2536 /* Perform the additional bump for __throw. */
f1c25d3b 2537 emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
6b3d1e47 2538 stack_pointer_rtx);
f1c25d3b 2539 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode,
6b3d1e47
SC
2540 HARD_FRAME_POINTER_REGNUM)));
2541 emit_jump_insn (gen_eh_return_internal ());
2542 }
2543 else
f1c25d3b 2544 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
6b3d1e47
SC
2545 GP_REG_FIRST + 31)));
2546}
2547
2548void
b7849684 2549iq2000_expand_eh_return (rtx address)
6b3d1e47 2550{
b5144086 2551 HOST_WIDE_INT gp_offset = cfun->machine->gp_sp_offset;
6b3d1e47
SC
2552 rtx scratch;
2553
2554 scratch = plus_constant (stack_pointer_rtx, gp_offset);
2555 emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address);
2556}
2557\f
2558/* Return nonzero if this function is known to have a null epilogue.
2559 This allows the optimizer to omit jumps to jumps if no stack
2560 was created. */
2561
2562int
b7849684 2563iq2000_can_use_return_insn (void)
6b3d1e47
SC
2564{
2565 if (! reload_completed)
2566 return 0;
2567
2568 if (regs_ever_live[31] || profile_flag)
2569 return 0;
2570
b5144086
SC
2571 if (cfun->machine->initialized)
2572 return cfun->machine->total_size == 0;
6b3d1e47
SC
2573
2574 return compute_frame_size (get_frame_size ()) == 0;
2575}
2576\f
4375e090 2577/* Returns nonzero if X contains a SYMBOL_REF. */
6b3d1e47
SC
2578
2579static int
b7849684 2580symbolic_expression_p (rtx x)
6b3d1e47
SC
2581{
2582 if (GET_CODE (x) == SYMBOL_REF)
2583 return 1;
2584
2585 if (GET_CODE (x) == CONST)
2586 return symbolic_expression_p (XEXP (x, 0));
2587
2588 if (GET_RTX_CLASS (GET_CODE (x)) == '1')
2589 return symbolic_expression_p (XEXP (x, 0));
2590
2591 if (GET_RTX_CLASS (GET_CODE (x)) == 'c'
2592 || GET_RTX_CLASS (GET_CODE (x)) == '2')
2593 return (symbolic_expression_p (XEXP (x, 0))
2594 || symbolic_expression_p (XEXP (x, 1)));
2595
2596 return 0;
2597}
2598
2599/* Choose the section to use for the constant rtx expression X that has
2600 mode MODE. */
2601
2602static void
b7849684
JE
2603iq2000_select_rtx_section (enum machine_mode mode, rtx x ATTRIBUTE_UNUSED,
2604 unsigned HOST_WIDE_INT align)
6b3d1e47
SC
2605{
2606 /* For embedded applications, always put constants in read-only data,
2607 in order to reduce RAM usage. */
2608 /* For embedded applications, always put constants in read-only data,
2609 in order to reduce RAM usage. */
2610 mergeable_constant_section (mode, align, 0);
2611}
2612
2613/* Choose the section to use for DECL. RELOC is true if its value contains
2614 any relocatable expression.
2615
2616 Some of the logic used here needs to be replicated in
2617 ENCODE_SECTION_INFO in iq2000.h so that references to these symbols
2618 are done correctly. */
2619
2620static void
b7849684
JE
2621iq2000_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
2622 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
6b3d1e47
SC
2623{
2624 if (TARGET_EMBEDDED_DATA)
2625 {
2626 /* For embedded applications, always put an object in read-only data
2627 if possible, in order to reduce RAM usage. */
6b3d1e47
SC
2628 if (((TREE_CODE (decl) == VAR_DECL
2629 && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
2630 && DECL_INITIAL (decl)
2631 && (DECL_INITIAL (decl) == error_mark_node
2632 || TREE_CONSTANT (DECL_INITIAL (decl))))
2633 /* Deal with calls from output_constant_def_contents. */
2634 || (TREE_CODE (decl) != VAR_DECL
2635 && (TREE_CODE (decl) != STRING_CST
2636 || !flag_writable_strings))))
2637 readonly_data_section ();
2638 else
2639 data_section ();
2640 }
2641 else
2642 {
2643 /* For hosted applications, always put an object in small data if
2644 possible, as this gives the best performance. */
6b3d1e47
SC
2645 if (((TREE_CODE (decl) == VAR_DECL
2646 && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
2647 && DECL_INITIAL (decl)
2648 && (DECL_INITIAL (decl) == error_mark_node
2649 || TREE_CONSTANT (DECL_INITIAL (decl))))
2650 /* Deal with calls from output_constant_def_contents. */
2651 || (TREE_CODE (decl) != VAR_DECL
2652 && (TREE_CODE (decl) != STRING_CST
2653 || !flag_writable_strings))))
2654 readonly_data_section ();
2655 else
2656 data_section ();
2657 }
2658}
2659/* Return register to use for a function return value with VALTYPE for function
2660 FUNC. */
2661
2662rtx
b7849684 2663iq2000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
6b3d1e47
SC
2664{
2665 int reg = GP_RETURN;
2666 enum machine_mode mode = TYPE_MODE (valtype);
2667 int unsignedp = TREE_UNSIGNED (valtype);
2668
69a45040
KH
2669 /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns true,
2670 we must promote the mode just as PROMOTE_MODE does. */
6b3d1e47
SC
2671 mode = promote_mode (valtype, mode, &unsignedp, 1);
2672
2673 return gen_rtx_REG (mode, reg);
2674}
2675\f
2676/* The implementation of FUNCTION_ARG_PASS_BY_REFERENCE. Return
2677 nonzero when an argument must be passed by reference. */
2678
2679int
b7849684
JE
2680function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
2681 enum machine_mode mode, tree type,
2682 int named ATTRIBUTE_UNUSED)
6b3d1e47
SC
2683{
2684 int size;
2685
2686 /* We must pass by reference if we would be both passing in registers
2687 and the stack. This is because any subsequent partial arg would be
2688 handled incorrectly in this case. */
6b3d1e47
SC
2689 if (cum && MUST_PASS_IN_STACK (mode, type))
2690 {
2691 /* Don't pass the actual CUM to FUNCTION_ARG, because we would
2692 get double copies of any offsets generated for small structs
2693 passed in registers. */
2694 CUMULATIVE_ARGS temp;
b5144086 2695
6b3d1e47
SC
2696 temp = *cum;
2697 if (FUNCTION_ARG (temp, mode, type, named) != 0)
2698 return 1;
2699 }
2700
2701 if (type == NULL_TREE || mode == DImode || mode == DFmode)
2702 return 0;
2703
2704 size = int_size_in_bytes (type);
2705 return size == -1 || size > UNITS_PER_WORD;
2706}
2707
2708/* Return the length of INSN. LENGTH is the initial length computed by
2709 attributes in the machine-description file. */
2710
2711int
b7849684 2712iq2000_adjust_insn_length (rtx insn, int length)
6b3d1e47
SC
2713{
2714 /* A unconditional jump has an unfilled delay slot if it is not part
b5144086 2715 of a sequence. A conditional jump normally has a delay slot. */
6b3d1e47 2716 if (simplejump_p (insn)
b5144086
SC
2717 || ( (GET_CODE (insn) == JUMP_INSN
2718 || GET_CODE (insn) == CALL_INSN)))
6b3d1e47
SC
2719 length += 4;
2720
2721 return length;
2722}
2723
2724/* Output assembly instructions to perform a conditional branch.
2725
2726 INSN is the branch instruction. OPERANDS[0] is the condition.
2727 OPERANDS[1] is the target of the branch. OPERANDS[2] is the target
2728 of the first operand to the condition. If TWO_OPERANDS_P is
4375e090 2729 nonzero the comparison takes two operands; OPERANDS[3] will be the
6b3d1e47
SC
2730 second operand.
2731
4375e090
KH
2732 If INVERTED_P is nonzero we are to branch if the condition does
2733 not hold. If FLOAT_P is nonzero this is a floating-point comparison.
6b3d1e47
SC
2734
2735 LENGTH is the length (in bytes) of the sequence we are to generate.
2736 That tells us whether to generate a simple conditional branch, or a
2737 reversed conditional branch around a `jr' instruction. */
2738
2739char *
b5144086 2740iq2000_output_conditional_branch (rtx insn, rtx * operands, int two_operands_p,
b7849684 2741 int float_p, int inverted_p, int length)
6b3d1e47
SC
2742{
2743 static char buffer[200];
2744 /* The kind of comparison we are doing. */
2745 enum rtx_code code = GET_CODE (operands[0]);
5b8d96f1 2746 /* Nonzero if the opcode for the comparison needs a `z' indicating
2cac216b 2747 that it is a comparison against zero. */
6b3d1e47
SC
2748 int need_z_p;
2749 /* A string to use in the assembly output to represent the first
2750 operand. */
2751 const char *op1 = "%z2";
2752 /* A string to use in the assembly output to represent the second
2753 operand. Use the hard-wired zero register if there's no second
2754 operand. */
2755 const char *op2 = (two_operands_p ? ",%z3" : ",%.");
2756 /* The operand-printing string for the comparison. */
2757 const char *comp = (float_p ? "%F0" : "%C0");
2758 /* The operand-printing string for the inverted comparison. */
2759 const char *inverted_comp = (float_p ? "%W0" : "%N0");
2760
b5144086 2761 /* Likely variants of each branch instruction annul the instruction
6b3d1e47
SC
2762 in the delay slot if the branch is not taken. */
2763 iq2000_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
2764
2765 if (!two_operands_p)
2766 {
2767 /* To compute whether than A > B, for example, we normally
2768 subtract B from A and then look at the sign bit. But, if we
2769 are doing an unsigned comparison, and B is zero, we don't
2770 have to do the subtraction. Instead, we can just check to
4375e090 2771 see if A is nonzero. Thus, we change the CODE here to
6b3d1e47
SC
2772 reflect the simpler comparison operation. */
2773 switch (code)
2774 {
2775 case GTU:
2776 code = NE;
2777 break;
2778
2779 case LEU:
2780 code = EQ;
2781 break;
2782
2783 case GEU:
2784 /* A condition which will always be true. */
2785 code = EQ;
2786 op1 = "%.";
2787 break;
2788
2789 case LTU:
2790 /* A condition which will always be false. */
2791 code = NE;
2792 op1 = "%.";
2793 break;
2794
2795 default:
2796 /* Not a special case. */
2797 break;
2798 }
2799 }
2800
2801 /* Relative comparisons are always done against zero. But
2802 equality comparisons are done between two operands, and therefore
2803 do not require a `z' in the assembly language output. */
2804 need_z_p = (!float_p && code != EQ && code != NE);
2805 /* For comparisons against zero, the zero is not provided
2806 explicitly. */
2807 if (need_z_p)
2808 op2 = "";
2809
2810 /* Begin by terminating the buffer. That way we can always use
2811 strcat to add to it. */
2812 buffer[0] = '\0';
2813
2814 switch (length)
2815 {
2816 case 4:
2817 case 8:
2818 /* Just a simple conditional branch. */
2819 if (float_p)
2820 sprintf (buffer, "b%s%%?\t%%Z2%%1",
2821 inverted_p ? inverted_comp : comp);
2822 else
2823 sprintf (buffer, "b%s%s%%?\t%s%s,%%1",
2824 inverted_p ? inverted_comp : comp,
2825 need_z_p ? "z" : "",
2826 op1,
2827 op2);
2828 return buffer;
2829
2830 case 12:
2831 case 16:
2832 {
2833 /* Generate a reversed conditional branch around ` j'
2834 instruction:
2835
2836 .set noreorder
2837 .set nomacro
2838 bc l
2839 nop
2840 j target
2841 .set macro
2842 .set reorder
2843 l:
2844
2845 Because we have to jump four bytes *past* the following
2846 instruction if this branch was annulled, we can't just use
2847 a label, as in the picture above; there's no way to put the
2848 label after the next instruction, as the assembler does not
2849 accept `.L+4' as the target of a branch. (We can't just
2850 wait until the next instruction is output; it might be a
2851 macro and take up more than four bytes. Once again, we see
2852 why we want to eliminate macros.)
2853
2854 If the branch is annulled, we jump four more bytes that we
2855 would otherwise; that way we skip the annulled instruction
2856 in the delay slot. */
2857
2858 const char *target
2859 = ((iq2000_branch_likely || length == 16) ? ".+16" : ".+12");
2860 char *c;
2861
2862 c = strchr (buffer, '\0');
b5144086 2863 /* Generate the reversed comparision. This takes four
6b3d1e47
SC
2864 bytes. */
2865 if (float_p)
2866 sprintf (c, "b%s\t%%Z2%s",
2867 inverted_p ? comp : inverted_comp,
2868 target);
2869 else
2870 sprintf (c, "b%s%s\t%s%s,%s",
2871 inverted_p ? comp : inverted_comp,
2872 need_z_p ? "z" : "",
2873 op1,
2874 op2,
2875 target);
2876 strcat (c, "\n\tnop\n\tj\t%1");
2877 if (length == 16)
2878 /* The delay slot was unfilled. Since we're inside
2879 .noreorder, the assembler will not fill in the NOP for
2880 us, so we must do it ourselves. */
2881 strcat (buffer, "\n\tnop");
2882 return buffer;
2883 }
2884
2885 default:
2886 abort ();
2887 }
2888
2889 /* NOTREACHED */
2890 return 0;
2891}
2892
6b3d1e47
SC
2893#define def_builtin(NAME, TYPE, CODE) \
2894 builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE)
2895
b5144086 2896static void
b7849684 2897iq2000_init_builtins (void)
6b3d1e47
SC
2898{
2899 tree endlink = void_list_node;
2900 tree void_ftype, void_ftype_int, void_ftype_int_int;
2901 tree void_ftype_int_int_int;
2902 tree int_ftype_int, int_ftype_int_int, int_ftype_int_int_int;
2903 tree int_ftype_int_int_int_int;
2904
2905 /* func () */
2906 void_ftype
2907 = build_function_type (void_type_node,
2908 tree_cons (NULL_TREE, void_type_node, endlink));
2909
2910 /* func (int) */
2911 void_ftype_int
2912 = build_function_type (void_type_node,
2913 tree_cons (NULL_TREE, integer_type_node, endlink));
2914
2915 /* void func (int, int) */
2916 void_ftype_int_int
2917 = build_function_type (void_type_node,
2918 tree_cons (NULL_TREE, integer_type_node,
2919 tree_cons (NULL_TREE, integer_type_node,
2920 endlink)));
2921
2922 /* int func (int) */
2923 int_ftype_int
2924 = build_function_type (integer_type_node,
2925 tree_cons (NULL_TREE, integer_type_node, endlink));
2926
2927 /* int func (int, int) */
2928 int_ftype_int_int
2929 = build_function_type (integer_type_node,
2930 tree_cons (NULL_TREE, integer_type_node,
2931 tree_cons (NULL_TREE, integer_type_node,
2932 endlink)));
2933
2934 /* void func (int, int, int) */
2935void_ftype_int_int_int
2936 = build_function_type
2937 (void_type_node,
2938 tree_cons (NULL_TREE, integer_type_node,
2939 tree_cons (NULL_TREE, integer_type_node,
2940 tree_cons (NULL_TREE,
2941 integer_type_node,
2942 endlink))));
2943
2944 /* int func (int, int, int, int) */
2945 int_ftype_int_int_int_int
2946 = build_function_type
2947 (integer_type_node,
2948 tree_cons (NULL_TREE, integer_type_node,
2949 tree_cons (NULL_TREE, integer_type_node,
2950 tree_cons (NULL_TREE,
2951 integer_type_node,
2952 tree_cons (NULL_TREE,
2953 integer_type_node,
2954 endlink)))));
2955
2956 /* int func (int, int, int) */
2957 int_ftype_int_int_int
2958 = build_function_type
2959 (integer_type_node,
2960 tree_cons (NULL_TREE, integer_type_node,
2961 tree_cons (NULL_TREE, integer_type_node,
2962 tree_cons (NULL_TREE,
2963 integer_type_node,
2964 endlink))));
2965
2966 /* int func (int, int, int, int) */
2967 int_ftype_int_int_int_int
2968 = build_function_type
2969 (integer_type_node,
2970 tree_cons (NULL_TREE, integer_type_node,
2971 tree_cons (NULL_TREE, integer_type_node,
2972 tree_cons (NULL_TREE,
2973 integer_type_node,
2974 tree_cons (NULL_TREE,
2975 integer_type_node,
2976 endlink)))));
2977
2978 def_builtin ("__builtin_ado16", int_ftype_int_int, IQ2000_BUILTIN_ADO16);
2979 def_builtin ("__builtin_ram", int_ftype_int_int_int_int, IQ2000_BUILTIN_RAM);
2980 def_builtin ("__builtin_chkhdr", void_ftype_int_int, IQ2000_BUILTIN_CHKHDR);
2981 def_builtin ("__builtin_pkrl", void_ftype_int_int, IQ2000_BUILTIN_PKRL);
2982 def_builtin ("__builtin_cfc0", int_ftype_int, IQ2000_BUILTIN_CFC0);
2983 def_builtin ("__builtin_cfc1", int_ftype_int, IQ2000_BUILTIN_CFC1);
2984 def_builtin ("__builtin_cfc2", int_ftype_int, IQ2000_BUILTIN_CFC2);
2985 def_builtin ("__builtin_cfc3", int_ftype_int, IQ2000_BUILTIN_CFC3);
2986 def_builtin ("__builtin_ctc0", void_ftype_int_int, IQ2000_BUILTIN_CTC0);
2987 def_builtin ("__builtin_ctc1", void_ftype_int_int, IQ2000_BUILTIN_CTC1);
2988 def_builtin ("__builtin_ctc2", void_ftype_int_int, IQ2000_BUILTIN_CTC2);
2989 def_builtin ("__builtin_ctc3", void_ftype_int_int, IQ2000_BUILTIN_CTC3);
2990 def_builtin ("__builtin_mfc0", int_ftype_int, IQ2000_BUILTIN_MFC0);
2991 def_builtin ("__builtin_mfc1", int_ftype_int, IQ2000_BUILTIN_MFC1);
2992 def_builtin ("__builtin_mfc2", int_ftype_int, IQ2000_BUILTIN_MFC2);
2993 def_builtin ("__builtin_mfc3", int_ftype_int, IQ2000_BUILTIN_MFC3);
2994 def_builtin ("__builtin_mtc0", void_ftype_int_int, IQ2000_BUILTIN_MTC0);
2995 def_builtin ("__builtin_mtc1", void_ftype_int_int, IQ2000_BUILTIN_MTC1);
2996 def_builtin ("__builtin_mtc2", void_ftype_int_int, IQ2000_BUILTIN_MTC2);
2997 def_builtin ("__builtin_mtc3", void_ftype_int_int, IQ2000_BUILTIN_MTC3);
2998 def_builtin ("__builtin_lur", void_ftype_int_int, IQ2000_BUILTIN_LUR);
2999 def_builtin ("__builtin_rb", void_ftype_int_int, IQ2000_BUILTIN_RB);
3000 def_builtin ("__builtin_rx", void_ftype_int_int, IQ2000_BUILTIN_RX);
3001 def_builtin ("__builtin_srrd", void_ftype_int, IQ2000_BUILTIN_SRRD);
3002 def_builtin ("__builtin_srwr", void_ftype_int_int, IQ2000_BUILTIN_SRWR);
3003 def_builtin ("__builtin_wb", void_ftype_int_int, IQ2000_BUILTIN_WB);
3004 def_builtin ("__builtin_wx", void_ftype_int_int, IQ2000_BUILTIN_WX);
3005 def_builtin ("__builtin_luc32l", void_ftype_int_int, IQ2000_BUILTIN_LUC32L);
3006 def_builtin ("__builtin_luc64", void_ftype_int_int, IQ2000_BUILTIN_LUC64);
3007 def_builtin ("__builtin_luc64l", void_ftype_int_int, IQ2000_BUILTIN_LUC64L);
3008 def_builtin ("__builtin_luk", void_ftype_int_int, IQ2000_BUILTIN_LUK);
3009 def_builtin ("__builtin_lulck", void_ftype_int, IQ2000_BUILTIN_LULCK);
3010 def_builtin ("__builtin_lum32", void_ftype_int_int, IQ2000_BUILTIN_LUM32);
3011 def_builtin ("__builtin_lum32l", void_ftype_int_int, IQ2000_BUILTIN_LUM32L);
3012 def_builtin ("__builtin_lum64", void_ftype_int_int, IQ2000_BUILTIN_LUM64);
3013 def_builtin ("__builtin_lum64l", void_ftype_int_int, IQ2000_BUILTIN_LUM64L);
3014 def_builtin ("__builtin_lurl", void_ftype_int_int, IQ2000_BUILTIN_LURL);
3015 def_builtin ("__builtin_mrgb", int_ftype_int_int_int, IQ2000_BUILTIN_MRGB);
3016 def_builtin ("__builtin_srrdl", void_ftype_int, IQ2000_BUILTIN_SRRDL);
3017 def_builtin ("__builtin_srulck", void_ftype_int, IQ2000_BUILTIN_SRULCK);
3018 def_builtin ("__builtin_srwru", void_ftype_int_int, IQ2000_BUILTIN_SRWRU);
3019 def_builtin ("__builtin_trapqfl", void_ftype, IQ2000_BUILTIN_TRAPQFL);
3020 def_builtin ("__builtin_trapqne", void_ftype, IQ2000_BUILTIN_TRAPQNE);
3021 def_builtin ("__builtin_traprel", void_ftype_int, IQ2000_BUILTIN_TRAPREL);
3022 def_builtin ("__builtin_wbu", void_ftype_int_int_int, IQ2000_BUILTIN_WBU);
3023 def_builtin ("__builtin_syscall", void_ftype, IQ2000_BUILTIN_SYSCALL);
3024}
3025
3026/* Builtin for ICODE having ARGCOUNT args in ARGLIST where each arg
b5144086 3027 has an rtx CODE. */
6b3d1e47
SC
3028
3029static rtx
b7849684
JE
3030expand_one_builtin (enum insn_code icode, rtx target, tree arglist,
3031 enum rtx_code *code, int argcount)
6b3d1e47
SC
3032{
3033 rtx pat;
3034 tree arg [5];
3035 rtx op [5];
3036 enum machine_mode mode [5];
3037 int i;
3038
3039 mode[0] = insn_data[icode].operand[0].mode;
3040 for (i = 0; i < argcount; i++)
3041 {
3042 arg[i] = TREE_VALUE (arglist);
3043 arglist = TREE_CHAIN (arglist);
3044 op[i] = expand_expr (arg[i], NULL_RTX, VOIDmode, 0);
3045 mode[i] = insn_data[icode].operand[i].mode;
3046 if (code[i] == CONST_INT && GET_CODE (op[i]) != CONST_INT)
3047 error ("argument `%d' is not a constant", i + 1);
3048 if (code[i] == REG
3049 && ! (*insn_data[icode].operand[i].predicate) (op[i], mode[i]))
3050 op[i] = copy_to_mode_reg (mode[i], op[i]);
3051 }
3052
3053 if (insn_data[icode].operand[0].constraint[0] == '=')
3054 {
3055 if (target == 0
3056 || GET_MODE (target) != mode[0]
3057 || ! (*insn_data[icode].operand[0].predicate) (target, mode[0]))
3058 target = gen_reg_rtx (mode[0]);
3059 }
3060 else
3061 target = 0;
3062
3063 switch (argcount)
3064 {
3065 case 0:
3066 pat = GEN_FCN (icode) (target);
3067 case 1:
3068 if (target)
3069 pat = GEN_FCN (icode) (target, op[0]);
3070 else
3071 pat = GEN_FCN (icode) (op[0]);
3072 break;
3073 case 2:
3074 if (target)
3075 pat = GEN_FCN (icode) (target, op[0], op[1]);
3076 else
3077 pat = GEN_FCN (icode) (op[0], op[1]);
3078 break;
3079 case 3:
3080 if (target)
3081 pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
3082 else
3083 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
3084 break;
3085 case 4:
3086 if (target)
3087 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
3088 else
3089 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
3090 break;
3091 default:
3092 abort ();
3093 }
3094
3095 if (! pat)
3096 return 0;
3097 emit_insn (pat);
3098 return target;
3099}
3100
3101/* Expand an expression EXP that calls a built-in function,
3102 with result going to TARGET if that's convenient
3103 (and in mode MODE if that's convenient).
3104 SUBTARGET may be used as the target for computing one of EXP's operands.
3105 IGNORE is nonzero if the value is to be ignored. */
3106
b5144086 3107static rtx
b7849684
JE
3108iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
3109 enum machine_mode mode ATTRIBUTE_UNUSED,
3110 int ignore ATTRIBUTE_UNUSED)
6b3d1e47
SC
3111{
3112 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3113 tree arglist = TREE_OPERAND (exp, 1);
3114 int fcode = DECL_FUNCTION_CODE (fndecl);
3115 enum rtx_code code [5];
3116
3117 code[0] = REG;
3118 code[1] = REG;
3119 code[2] = REG;
3120 code[3] = REG;
3121 code[4] = REG;
3122 switch (fcode)
3123 {
3124 default:
3125 break;
3126
3127 case IQ2000_BUILTIN_ADO16:
3128 return expand_one_builtin (CODE_FOR_ado16, target, arglist, code, 2);
3129
3130 case IQ2000_BUILTIN_RAM:
3131 code[1] = CONST_INT;
3132 code[2] = CONST_INT;
3133 code[3] = CONST_INT;
3134 return expand_one_builtin (CODE_FOR_ram, target, arglist, code, 4);
3135
3136 case IQ2000_BUILTIN_CHKHDR:
3137 return expand_one_builtin (CODE_FOR_chkhdr, target, arglist, code, 2);
3138
3139 case IQ2000_BUILTIN_PKRL:
3140 return expand_one_builtin (CODE_FOR_pkrl, target, arglist, code, 2);
3141
3142 case IQ2000_BUILTIN_CFC0:
3143 code[0] = CONST_INT;
3144 return expand_one_builtin (CODE_FOR_cfc0, target, arglist, code, 1);
3145
3146 case IQ2000_BUILTIN_CFC1:
3147 code[0] = CONST_INT;
3148 return expand_one_builtin (CODE_FOR_cfc1, target, arglist, code, 1);
3149
3150 case IQ2000_BUILTIN_CFC2:
3151 code[0] = CONST_INT;
3152 return expand_one_builtin (CODE_FOR_cfc2, target, arglist, code, 1);
3153
3154 case IQ2000_BUILTIN_CFC3:
3155 code[0] = CONST_INT;
3156 return expand_one_builtin (CODE_FOR_cfc3, target, arglist, code, 1);
3157
3158 case IQ2000_BUILTIN_CTC0:
3159 code[1] = CONST_INT;
3160 return expand_one_builtin (CODE_FOR_ctc0, target, arglist, code, 2);
3161
3162 case IQ2000_BUILTIN_CTC1:
3163 code[1] = CONST_INT;
3164 return expand_one_builtin (CODE_FOR_ctc1, target, arglist, code, 2);
3165
3166 case IQ2000_BUILTIN_CTC2:
3167 code[1] = CONST_INT;
3168 return expand_one_builtin (CODE_FOR_ctc2, target, arglist, code, 2);
3169
3170 case IQ2000_BUILTIN_CTC3:
3171 code[1] = CONST_INT;
3172 return expand_one_builtin (CODE_FOR_ctc3, target, arglist, code, 2);
3173
3174 case IQ2000_BUILTIN_MFC0:
3175 code[0] = CONST_INT;
3176 return expand_one_builtin (CODE_FOR_mfc0, target, arglist, code, 1);
3177
3178 case IQ2000_BUILTIN_MFC1:
3179 code[0] = CONST_INT;
3180 return expand_one_builtin (CODE_FOR_mfc1, target, arglist, code, 1);
3181
3182 case IQ2000_BUILTIN_MFC2:
3183 code[0] = CONST_INT;
3184 return expand_one_builtin (CODE_FOR_mfc2, target, arglist, code, 1);
3185
3186 case IQ2000_BUILTIN_MFC3:
3187 code[0] = CONST_INT;
3188 return expand_one_builtin (CODE_FOR_mfc3, target, arglist, code, 1);
3189
3190 case IQ2000_BUILTIN_MTC0:
3191 code[1] = CONST_INT;
3192 return expand_one_builtin (CODE_FOR_mtc0, target, arglist, code, 2);
3193
3194 case IQ2000_BUILTIN_MTC1:
3195 code[1] = CONST_INT;
3196 return expand_one_builtin (CODE_FOR_mtc1, target, arglist, code, 2);
3197
3198 case IQ2000_BUILTIN_MTC2:
3199 code[1] = CONST_INT;
3200 return expand_one_builtin (CODE_FOR_mtc2, target, arglist, code, 2);
3201
3202 case IQ2000_BUILTIN_MTC3:
3203 code[1] = CONST_INT;
3204 return expand_one_builtin (CODE_FOR_mtc3, target, arglist, code, 2);
3205
3206 case IQ2000_BUILTIN_LUR:
3207 return expand_one_builtin (CODE_FOR_lur, target, arglist, code, 2);
3208
3209 case IQ2000_BUILTIN_RB:
3210 return expand_one_builtin (CODE_FOR_rb, target, arglist, code, 2);
3211
3212 case IQ2000_BUILTIN_RX:
3213 return expand_one_builtin (CODE_FOR_rx, target, arglist, code, 2);
3214
3215 case IQ2000_BUILTIN_SRRD:
3216 return expand_one_builtin (CODE_FOR_srrd, target, arglist, code, 1);
3217
3218 case IQ2000_BUILTIN_SRWR:
3219 return expand_one_builtin (CODE_FOR_srwr, target, arglist, code, 2);
3220
3221 case IQ2000_BUILTIN_WB:
3222 return expand_one_builtin (CODE_FOR_wb, target, arglist, code, 2);
3223
3224 case IQ2000_BUILTIN_WX:
3225 return expand_one_builtin (CODE_FOR_wx, target, arglist, code, 2);
3226
3227 case IQ2000_BUILTIN_LUC32L:
3228 return expand_one_builtin (CODE_FOR_luc32l, target, arglist, code, 2);
3229
3230 case IQ2000_BUILTIN_LUC64:
3231 return expand_one_builtin (CODE_FOR_luc64, target, arglist, code, 2);
3232
3233 case IQ2000_BUILTIN_LUC64L:
3234 return expand_one_builtin (CODE_FOR_luc64l, target, arglist, code, 2);
3235
3236 case IQ2000_BUILTIN_LUK:
3237 return expand_one_builtin (CODE_FOR_luk, target, arglist, code, 2);
3238
3239 case IQ2000_BUILTIN_LULCK:
3240 return expand_one_builtin (CODE_FOR_lulck, target, arglist, code, 1);
3241
3242 case IQ2000_BUILTIN_LUM32:
3243 return expand_one_builtin (CODE_FOR_lum32, target, arglist, code, 2);
3244
3245 case IQ2000_BUILTIN_LUM32L:
3246 return expand_one_builtin (CODE_FOR_lum32l, target, arglist, code, 2);
3247
3248 case IQ2000_BUILTIN_LUM64:
3249 return expand_one_builtin (CODE_FOR_lum64, target, arglist, code, 2);
3250
3251 case IQ2000_BUILTIN_LUM64L:
3252 return expand_one_builtin (CODE_FOR_lum64l, target, arglist, code, 2);
3253
3254 case IQ2000_BUILTIN_LURL:
3255 return expand_one_builtin (CODE_FOR_lurl, target, arglist, code, 2);
3256
3257 case IQ2000_BUILTIN_MRGB:
3258 code[2] = CONST_INT;
3259 return expand_one_builtin (CODE_FOR_mrgb, target, arglist, code, 3);
3260
3261 case IQ2000_BUILTIN_SRRDL:
3262 return expand_one_builtin (CODE_FOR_srrdl, target, arglist, code, 1);
3263
3264 case IQ2000_BUILTIN_SRULCK:
3265 return expand_one_builtin (CODE_FOR_srulck, target, arglist, code, 1);
3266
3267 case IQ2000_BUILTIN_SRWRU:
3268 return expand_one_builtin (CODE_FOR_srwru, target, arglist, code, 2);
3269
3270 case IQ2000_BUILTIN_TRAPQFL:
3271 return expand_one_builtin (CODE_FOR_trapqfl, target, arglist, code, 0);
3272
3273 case IQ2000_BUILTIN_TRAPQNE:
3274 return expand_one_builtin (CODE_FOR_trapqne, target, arglist, code, 0);
3275
3276 case IQ2000_BUILTIN_TRAPREL:
3277 return expand_one_builtin (CODE_FOR_traprel, target, arglist, code, 1);
3278
3279 case IQ2000_BUILTIN_WBU:
3280 return expand_one_builtin (CODE_FOR_wbu, target, arglist, code, 3);
3281
3282 case IQ2000_BUILTIN_SYSCALL:
3283 return expand_one_builtin (CODE_FOR_syscall, target, arglist, code, 0);
3284 }
3285
3286 return NULL_RTX;
3287}
3288\f
bd5bd7ac
KH
3289/* Worker function for TARGET_RETURN_IN_MEMORY. */
3290
69a45040
KH
3291static bool
3292iq2000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
3293{
3294 return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
3295 || (int_size_in_bytes (type) == -1));
3296}
3297
bd5bd7ac
KH
3298/* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
3299
69a45040
KH
3300static void
3301iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
3302 enum machine_mode mode ATTRIBUTE_UNUSED,
b5144086
SC
3303 tree type ATTRIBUTE_UNUSED, int * pretend_size,
3304 int no_rtl)
6b3d1e47 3305{
69a45040
KH
3306 unsigned int iq2000_off = ! cum->last_arg_fp;
3307 unsigned int iq2000_fp_off = cum->last_arg_fp;
b5144086 3308
69a45040 3309 if ((cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off))
6b3d1e47
SC
3310 {
3311 int iq2000_save_gp_regs
69a45040 3312 = MAX_ARGS_IN_REGISTERS - cum->arg_words - iq2000_off;
6b3d1e47 3313 int iq2000_save_fp_regs
69a45040 3314 = (MAX_ARGS_IN_REGISTERS - cum->fp_arg_words - iq2000_fp_off);
6b3d1e47
SC
3315
3316 if (iq2000_save_gp_regs < 0)
3317 iq2000_save_gp_regs = 0;
3318 if (iq2000_save_fp_regs < 0)
3319 iq2000_save_fp_regs = 0;
3320
3321 *pretend_size = ((iq2000_save_gp_regs * UNITS_PER_WORD)
3322 + (iq2000_save_fp_regs * UNITS_PER_FPREG));
3323
3324 if (! (no_rtl))
3325 {
69a45040 3326 if (cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off)
6b3d1e47
SC
3327 {
3328 rtx ptr, mem;
3329 ptr = plus_constant (virtual_incoming_args_rtx,
3330 - (iq2000_save_gp_regs
3331 * UNITS_PER_WORD));
3332 mem = gen_rtx_MEM (BLKmode, ptr);
3333 move_block_from_reg
69a45040 3334 (cum->arg_words + GP_ARG_FIRST + iq2000_off,
6b3d1e47
SC
3335 mem,
3336 iq2000_save_gp_regs);
3337 }
3338 }
3339 }
3340}
3341\f
3342/* A C compound statement to output to stdio stream STREAM the
3343 assembler syntax for an instruction operand that is a memory
b5144086 3344 reference whose address is ADDR. ADDR is an RTL expression. */
6b3d1e47
SC
3345
3346void
b5144086 3347print_operand_address (FILE * file, rtx addr)
6b3d1e47
SC
3348{
3349 if (!addr)
3350 error ("PRINT_OPERAND_ADDRESS, null pointer");
3351
3352 else
3353 switch (GET_CODE (addr))
3354 {
3355 case REG:
3356 if (REGNO (addr) == ARG_POINTER_REGNUM)
3357 abort_with_insn (addr, "Arg pointer not eliminated.");
3358
3359 fprintf (file, "0(%s)", reg_names [REGNO (addr)]);
3360 break;
3361
3362 case LO_SUM:
3363 {
b5144086
SC
3364 rtx arg0 = XEXP (addr, 0);
3365 rtx arg1 = XEXP (addr, 1);
6b3d1e47
SC
3366
3367 if (GET_CODE (arg0) != REG)
3368 abort_with_insn (addr,
3369 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG.");
3370
3371 fprintf (file, "%%lo(");
3372 print_operand_address (file, arg1);
3373 fprintf (file, ")(%s)", reg_names [REGNO (arg0)]);
3374 }
3375 break;
3376
3377 case PLUS:
3378 {
b5144086
SC
3379 rtx reg = 0;
3380 rtx offset = 0;
3381 rtx arg0 = XEXP (addr, 0);
3382 rtx arg1 = XEXP (addr, 1);
6b3d1e47
SC
3383
3384 if (GET_CODE (arg0) == REG)
3385 {
3386 reg = arg0;
3387 offset = arg1;
3388 if (GET_CODE (offset) == REG)
3389 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, 2 regs");
3390 }
3391
3392 else if (GET_CODE (arg1) == REG)
3393 reg = arg1, offset = arg0;
3394 else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
3395 {
3396 output_addr_const (file, addr);
3397 break;
3398 }
3399 else
3400 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, no regs");
3401
3402 if (! CONSTANT_P (offset))
3403 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #2");
3404
3405 if (REGNO (reg) == ARG_POINTER_REGNUM)
3406 abort_with_insn (addr, "Arg pointer not eliminated.");
3407
3408 output_addr_const (file, offset);
3409 fprintf (file, "(%s)", reg_names [REGNO (reg)]);
3410 }
3411 break;
3412
3413 case LABEL_REF:
3414 case SYMBOL_REF:
3415 case CONST_INT:
3416 case CONST:
3417 output_addr_const (file, addr);
3418 if (GET_CODE (addr) == CONST_INT)
3419 fprintf (file, "(%s)", reg_names [0]);
3420 break;
3421
3422 default:
3423 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #1");
3424 break;
3425 }
3426}
3427\f
b5144086
SC
3428/* A C compound statement to output to stdio stream FILE the
3429 assembler syntax for an instruction operand OP.
6b3d1e47 3430
b5144086 3431 LETTER is a value that can be used to specify one of several ways
6b3d1e47 3432 of printing the operand. It is used when identical operands
b5144086 3433 must be printed differently depending on the context. LETTER
6b3d1e47
SC
3434 comes from the `%' specification that was used to request
3435 printing of the operand. If the specification was just `%DIGIT'
b5144086 3436 then LETTER is 0; if the specification was `%LTR DIGIT' then LETTER
6b3d1e47
SC
3437 is the ASCII code for LTR.
3438
b5144086 3439 If OP is a register, this macro should print the register's name.
6b3d1e47
SC
3440 The names can be found in an array `reg_names' whose type is
3441 `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
3442
3443 When the machine description has a specification `%PUNCT' (a `%'
3444 followed by a punctuation character), this macro is called with
b5144086 3445 a null pointer for X and the punctuation character for LETTER.
6b3d1e47
SC
3446
3447 The IQ2000 specific codes are:
3448
3449 'X' X is CONST_INT, prints upper 16 bits in hexadecimal format = "0x%04x",
3450 'x' X is CONST_INT, prints lower 16 bits in hexadecimal format = "0x%04x",
3451 'd' output integer constant in decimal,
3452 'z' if the operand is 0, use $0 instead of normal operand.
3453 'D' print second part of double-word register or memory operand.
3454 'L' print low-order register of double-word register operand.
3455 'M' print high-order register of double-word register operand.
3456 'C' print part of opcode for a branch condition.
3457 'F' print part of opcode for a floating-point branch condition.
3458 'N' print part of opcode for a branch condition, inverted.
3459 'W' print part of opcode for a floating-point branch condition, inverted.
3460 'A' Print part of opcode for a bit test condition.
3461 'P' Print label for a bit test.
3462 'p' Print log for a bit test.
3463 'B' print 'z' for EQ, 'n' for NE
3464 'b' print 'n' for EQ, 'z' for NE
3465 'T' print 'f' for EQ, 't' for NE
3466 't' print 't' for EQ, 'f' for NE
3467 'Z' print register and a comma, but print nothing for $fcc0
3468 '?' Print 'l' if we are to use a branch likely instead of normal branch.
3469 '@' Print the name of the assembler temporary register (at or $1).
3470 '.' Print the name of the register with a hard-wired zero (zero or $0).
3471 '$' Print the name of the stack pointer register (sp or $29).
3472 '+' Print the name of the gp register (gp or $28). */
3473
3474void
b7849684 3475print_operand (FILE *file, rtx op, int letter)
6b3d1e47 3476{
b5144086 3477 enum rtx_code code;
6b3d1e47
SC
3478
3479 if (PRINT_OPERAND_PUNCT_VALID_P (letter))
3480 {
3481 switch (letter)
3482 {
3483 case '?':
3484 if (iq2000_branch_likely)
3485 putc ('l', file);
3486 break;
3487
3488 case '@':
3489 fputs (reg_names [GP_REG_FIRST + 1], file);
3490 break;
3491
3492 case '.':
3493 fputs (reg_names [GP_REG_FIRST + 0], file);
3494 break;
3495
3496 case '$':
3497 fputs (reg_names[STACK_POINTER_REGNUM], file);
3498 break;
3499
3500 case '+':
3501 fputs (reg_names[GP_REG_FIRST + 28], file);
3502 break;
3503
3504 default:
3505 error ("PRINT_OPERAND: Unknown punctuation '%c'", letter);
3506 break;
3507 }
3508
3509 return;
3510 }
3511
3512 if (! op)
3513 {
3514 error ("PRINT_OPERAND null pointer");
3515 return;
3516 }
3517
3518 code = GET_CODE (op);
3519
3520 if (code == SIGN_EXTEND)
3521 op = XEXP (op, 0), code = GET_CODE (op);
3522
3523 if (letter == 'C')
3524 switch (code)
3525 {
3526 case EQ: fputs ("eq", file); break;
3527 case NE: fputs ("ne", file); break;
3528 case GT: fputs ("gt", file); break;
3529 case GE: fputs ("ge", file); break;
3530 case LT: fputs ("lt", file); break;
3531 case LE: fputs ("le", file); break;
3532 case GTU: fputs ("ne", file); break;
3533 case GEU: fputs ("geu", file); break;
3534 case LTU: fputs ("ltu", file); break;
3535 case LEU: fputs ("eq", file); break;
3536 default:
3537 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%C");
3538 }
3539
3540 else if (letter == 'N')
3541 switch (code)
3542 {
3543 case EQ: fputs ("ne", file); break;
3544 case NE: fputs ("eq", file); break;
3545 case GT: fputs ("le", file); break;
3546 case GE: fputs ("lt", file); break;
3547 case LT: fputs ("ge", file); break;
3548 case LE: fputs ("gt", file); break;
3549 case GTU: fputs ("leu", file); break;
3550 case GEU: fputs ("ltu", file); break;
3551 case LTU: fputs ("geu", file); break;
3552 case LEU: fputs ("gtu", file); break;
3553 default:
3554 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%N");
3555 }
3556
3557 else if (letter == 'F')
3558 switch (code)
3559 {
3560 case EQ: fputs ("c1f", file); break;
3561 case NE: fputs ("c1t", file); break;
3562 default:
3563 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%F");
3564 }
3565
3566 else if (letter == 'W')
3567 switch (code)
3568 {
3569 case EQ: fputs ("c1t", file); break;
3570 case NE: fputs ("c1f", file); break;
3571 default:
3572 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%W");
3573 }
3574
3575 else if (letter == 'A')
3576 fputs (code == LABEL_REF ? "i" : "in", file);
3577
3578 else if (letter == 'P')
3579 {
3580 if (code == LABEL_REF)
3581 output_addr_const (file, op);
3582 else if (code != PC)
3583 output_operand_lossage ("invalid %%P operand");
3584 }
3585
3586 else if (letter == 'p')
3587 {
3588 int value;
3589 if (code != CONST_INT
3590 || (value = exact_log2 (INTVAL (op))) < 0)
3591 output_operand_lossage ("invalid %%p value");
3592 fprintf (file, "%d", value);
3593 }
3594
3595 else if (letter == 'Z')
3596 {
b5144086 3597 int regnum;
6b3d1e47
SC
3598
3599 if (code != REG)
3600 abort ();
3601
3602 regnum = REGNO (op);
3603 abort ();
3604
3605 fprintf (file, "%s,", reg_names[regnum]);
3606 }
3607
3608 else if (code == REG || code == SUBREG)
3609 {
b5144086 3610 int regnum;
6b3d1e47
SC
3611
3612 if (code == REG)
3613 regnum = REGNO (op);
3614 else
3615 regnum = true_regnum (op);
3616
3617 if ((letter == 'M' && ! WORDS_BIG_ENDIAN)
3618 || (letter == 'L' && WORDS_BIG_ENDIAN)
3619 || letter == 'D')
3620 regnum++;
3621
3622 fprintf (file, "%s", reg_names[regnum]);
3623 }
3624
3625 else if (code == MEM)
3626 {
3627 if (letter == 'D')
3628 output_address (plus_constant (XEXP (op, 0), 4));
3629 else
3630 output_address (XEXP (op, 0));
3631 }
3632
3633 else if (code == CONST_DOUBLE
3634 && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
3635 {
3636 char s[60];
3637
3638 real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (op), sizeof (s), 0, 1);
3639 fputs (s, file);
3640 }
3641
3642 else if (letter == 'x' && GET_CODE (op) == CONST_INT)
3643 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op));
3644
3645 else if (letter == 'X' && GET_CODE(op) == CONST_INT)
3646 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & (INTVAL (op) >> 16));
3647
3648 else if (letter == 'd' && GET_CODE(op) == CONST_INT)
3649 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op)));
3650
3651 else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
3652 fputs (reg_names[GP_REG_FIRST], file);
3653
3654 else if (letter == 'd' || letter == 'x' || letter == 'X')
3655 output_operand_lossage ("invalid use of %%d, %%x, or %%X");
3656
3657 else if (letter == 'B')
3658 fputs (code == EQ ? "z" : "n", file);
3659 else if (letter == 'b')
3660 fputs (code == EQ ? "n" : "z", file);
3661 else if (letter == 'T')
3662 fputs (code == EQ ? "f" : "t", file);
3663 else if (letter == 't')
3664 fputs (code == EQ ? "t" : "f", file);
3665
3666 else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
3667 {
3668 print_operand (file, XEXP (op, 0), letter);
3669 }
3670
3671 else
3672 output_addr_const (file, op);
3673}
b5144086
SC
3674
3675static bool
3676iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total)
3677{
3678 enum machine_mode mode = GET_MODE (x);
3679
3680 switch (code)
3681 {
3682 case MEM:
3683 {
3684 int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
3685
3686 if (simple_memory_operand (x, mode))
3687 return COSTS_N_INSNS (num_words);
3688
3689 * total = COSTS_N_INSNS (2 * num_words);
3690 break;
3691 }
3692
3693 case FFS:
3694 * total = COSTS_N_INSNS (6);
3695 break;
3696
3697 case AND:
3698 case IOR:
3699 case XOR:
3700 case NOT:
3701 * total = COSTS_N_INSNS (mode == DImode ? 2 : 1);
3702 break;
3703
3704 case ASHIFT:
3705 case ASHIFTRT:
3706 case LSHIFTRT:
3707 if (mode == DImode)
3708 * total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT) ? 4 : 12);
3709 else
3710 * total = COSTS_N_INSNS (1);
3711 break;
3712
3713 case ABS:
3714 if (mode == SFmode || mode == DFmode)
3715 * total = COSTS_N_INSNS (1);
3716 else
3717 * total = COSTS_N_INSNS (4);
3718 break;
3719
3720 case PLUS:
3721 case MINUS:
3722 if (mode == SFmode || mode == DFmode)
3723 * total = COSTS_N_INSNS (6);
3724 else if (mode == DImode)
3725 * total = COSTS_N_INSNS (4);
3726 else
3727 * total = COSTS_N_INSNS (1);
3728 break;
3729
3730 case NEG:
3731 * total = (mode == DImode) ? 4 : 1;
3732 break;
3733
3734 case MULT:
3735 if (mode == SFmode)
3736 * total = COSTS_N_INSNS (7);
3737 else if (mode == DFmode)
3738 * total = COSTS_N_INSNS (8);
3739 else
3740 * total = COSTS_N_INSNS (10);
3741 break;
3742
3743 case DIV:
3744 case MOD:
3745 if (mode == SFmode)
3746 * total = COSTS_N_INSNS (23);
3747 else if (mode == DFmode)
3748 * total = COSTS_N_INSNS (36);
3749 else
3750 * total = COSTS_N_INSNS (69);
3751 break;
3752
3753 case UDIV:
3754 case UMOD:
3755 * total = COSTS_N_INSNS (69);
3756 break;
3757
3758 case SIGN_EXTEND:
3759 * total = COSTS_N_INSNS (2);
3760 break;
3761
3762 case ZERO_EXTEND:
3763 * total = COSTS_N_INSNS (1);
3764 break;
3765
3766 case CONST_INT:
3767 * total = 0;
3768 break;
3769
3770 case LABEL_REF:
3771 * total = COSTS_N_INSNS (2);
3772 break;
3773
3774 case CONST:
3775 {
3776 rtx offset = const0_rtx;
3777 rtx symref = eliminate_constant_term (XEXP (x, 0), & offset);
3778
3779 if (GET_CODE (symref) == LABEL_REF)
3780 * total = COSTS_N_INSNS (2);
3781 else if (GET_CODE (symref) != SYMBOL_REF)
3782 * total = COSTS_N_INSNS (4);
5b8d96f1 3783 /* Let's be paranoid.... */
b5144086
SC
3784 else if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)
3785 * total = COSTS_N_INSNS (2);
3786 else
3787 * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (symref) ? 1 : 2);
3788 break;
3789 }
3790
3791 case SYMBOL_REF:
3792 * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (x) ? 1 : 2);
3793 break;
3794
3795 case CONST_DOUBLE:
3796 {
3797 rtx high, low;
3798
3799 split_double (x, & high, & low);
3800
3801 * total = COSTS_N_INSNS ( (high == CONST0_RTX (GET_MODE (high))
3802 || low == CONST0_RTX (GET_MODE (low)))
3803 ? 2 : 4);
3804 break;
3805 }
3806
3807 default:
3808 return false;
3809 }
3810 return true;
3811}
3812
3813#include "gt-iq2000.h"