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