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