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