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