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