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