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