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