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