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