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