]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/crx/crx.c
freebsd.h (CPP_CPU64_DEFAULT_SPEC): Replace with...
[thirdparty/gcc.git] / gcc / config / crx / crx.c
CommitLineData
db869733
PW
1/* Output routines for GCC for CRX.
2 Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
fac0f722 3 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
6bc7bc14 4 Free Software Foundation, Inc.
db869733
PW
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published
2f83c7d6 10 by the Free Software Foundation; either version 3, or (at your
db869733
PW
11 option) any later version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
17
18 You should have received a copy of the GNU General Public License
2f83c7d6
NC
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
db869733
PW
21
22/*****************************************************************************/
23/* HEADER INCLUDES */
24/*****************************************************************************/
25
26#include "config.h"
27#include "system.h"
28#include "coretypes.h"
29#include "tm.h"
30#include "rtl.h"
31#include "tree.h"
32#include "tm_p.h"
33#include "regs.h"
34#include "hard-reg-set.h"
db869733
PW
35#include "insn-config.h"
36#include "conditions.h"
37#include "output.h"
38#include "insn-codes.h"
39#include "insn-attr.h"
40#include "flags.h"
41#include "except.h"
42#include "function.h"
43#include "recog.h"
44#include "expr.h"
45#include "optabs.h"
718f9c0f 46#include "diagnostic-core.h"
db869733 47#include "basic-block.h"
5a82ecd9 48#include "df.h"
db869733
PW
49#include "target.h"
50#include "target-def.h"
51
52/*****************************************************************************/
53/* DEFINITIONS */
54/*****************************************************************************/
55
56/* Maximum number of register used for passing parameters. */
55d61dba 57#define MAX_REG_FOR_PASSING_ARGS 6
db869733
PW
58
59/* Minimum number register used for passing parameters. */
60#define MIN_REG_FOR_PASSING_ARGS 2
61
62/* The maximum count of words supported in the assembly of the architecture in
63 * a push/pop instruction. */
64#define MAX_COUNT 8
65
66/* Predicate is true if the current function is a 'noreturn' function, i.e. it
67 * is qualified as volatile. */
e95cfa3b 68#define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
db869733 69
e95cfa3b 70/* The following macros are used in crx_decompose_address () */
db869733 71
e95cfa3b
PW
72/* Returns the factor of a scaled index address or -1 if invalid. */
73#define SCALE_FOR_INDEX_P(X) \
74 (GET_CODE (X) == CONST_INT ? \
75 (INTVAL (X) == 1 ? 1 : \
76 INTVAL (X) == 2 ? 2 : \
77 INTVAL (X) == 4 ? 4 : \
78 INTVAL (X) == 8 ? 8 : \
79 -1) : \
80 -1)
db869733
PW
81
82/* Nonzero if the rtx X is a signed const int of n bits */
83#define RTX_SIGNED_INT_FITS_N_BITS(X,n) \
e95cfa3b
PW
84 ((GET_CODE (X) == CONST_INT \
85 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
db869733 86
569b7f6a 87/* Nonzero if the rtx X is an unsigned const int of n bits. */
e95cfa3b
PW
88#define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
89 ((GET_CODE (X) == CONST_INT \
90 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
db869733
PW
91
92/*****************************************************************************/
93/* STATIC VARIABLES */
94/*****************************************************************************/
95
a4d05547 96/* Nonzero if the last param processed is passed in a register. */
db869733
PW
97static int last_parm_in_reg;
98
99/* Will hold the number of the last register the prologue saves, -1 if no
100 * register is saved. */
101static int last_reg_to_save;
102
103/* Each object in the array is a register number. Mark 1 for registers that
104 * need to be saved. */
105static int save_regs[FIRST_PSEUDO_REGISTER];
106
107/* Number of bytes saved on the stack for non-scratch registers */
108static int sum_regs = 0;
109
110/* Number of bytes saved on the stack for local variables. */
111static int local_vars_size;
112
113/* The sum of 2 sizes: locals vars and padding byte for saving the registers.
e95cfa3b 114 * Used in expand_prologue () and expand_epilogue (). */
db869733
PW
115static int size_for_adjusting_sp;
116
117/* In case of a POST_INC or POST_DEC memory reference, we must report the mode
118 * of the memory reference from PRINT_OPERAND to PRINT_OPERAND_ADDRESS. */
119static enum machine_mode output_memory_reference_mode;
120
db869733
PW
121/*****************************************************************************/
122/* TARGETM FUNCTION PROTOTYPES */
123/*****************************************************************************/
124
125static bool crx_fixed_condition_code_regs (unsigned int *, unsigned int *);
126static rtx crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
127 int incoming ATTRIBUTE_UNUSED);
586de218 128static bool crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED);
f40751dd 129static int crx_address_cost (rtx, bool);
c6c3dba9 130static bool crx_legitimate_address_p (enum machine_mode, rtx, bool);
7b5cbb57 131static bool crx_can_eliminate (const int, const int);
a6a54b6f
NF
132static rtx crx_function_arg (CUMULATIVE_ARGS *, enum machine_mode,
133 const_tree, bool);
134static void crx_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
135 const_tree, bool);
c6c3dba9
PB
136
137/*****************************************************************************/
138/* RTL VALIDITY */
139/*****************************************************************************/
140
141#undef TARGET_LEGITIMATE_ADDRESS_P
142#define TARGET_LEGITIMATE_ADDRESS_P crx_legitimate_address_p
db869733 143
7b5cbb57
AS
144#undef TARGET_CAN_ELIMINATE
145#define TARGET_CAN_ELIMINATE crx_can_eliminate
146
db869733
PW
147/*****************************************************************************/
148/* STACK LAYOUT AND CALLING CONVENTIONS */
149/*****************************************************************************/
150
151#undef TARGET_FIXED_CONDITION_CODE_REGS
152#define TARGET_FIXED_CONDITION_CODE_REGS crx_fixed_condition_code_regs
153
154#undef TARGET_STRUCT_VALUE_RTX
155#define TARGET_STRUCT_VALUE_RTX crx_struct_value_rtx
156
157#undef TARGET_RETURN_IN_MEMORY
158#define TARGET_RETURN_IN_MEMORY crx_return_in_memory
159
a6a54b6f
NF
160/*****************************************************************************/
161/* PASSING FUNCTION ARGUMENTS */
162/*****************************************************************************/
163
164#undef TARGET_FUNCTION_ARG
165#define TARGET_FUNCTION_ARG crx_function_arg
166
167#undef TARGET_FUNCTION_ARG_ADVANCE
168#define TARGET_FUNCTION_ARG_ADVANCE crx_function_arg_advance
169
e95cfa3b
PW
170/*****************************************************************************/
171/* RELATIVE COSTS OF OPERATIONS */
172/*****************************************************************************/
173
174#undef TARGET_ADDRESS_COST
175#define TARGET_ADDRESS_COST crx_address_cost
176
db869733
PW
177/*****************************************************************************/
178/* TARGET-SPECIFIC USES OF `__attribute__' */
179/*****************************************************************************/
180
181#undef TARGET_ATTRIBUTE_TABLE
182#define TARGET_ATTRIBUTE_TABLE crx_attribute_table
183
5a82ecd9 184static const struct attribute_spec crx_attribute_table[] = {
db869733 185 /* ISRs have special prologue and epilogue requirements. */
62d784f7
KT
186 {"interrupt", 0, 0, false, true, true, NULL, false},
187 {NULL, 0, 0, false, false, false, NULL, false}
db869733
PW
188};
189
fac0f722
JM
190/* Option handling. */
191
3020190e
JM
192#undef TARGET_OPTION_OPTIMIZATION_TABLE
193#define TARGET_OPTION_OPTIMIZATION_TABLE crx_option_optimization_table
194
195static const struct default_options crx_option_optimization_table[] =
196 {
197 /* Put each function in its own section so that PAGE-instruction
198 relaxation can do its best. */
199 { OPT_LEVELS_1_PLUS, OPT_ffunction_sections, NULL, 1 },
200 { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
201 { OPT_LEVELS_NONE, 0, NULL, 0 }
202 };
db869733
PW
203
204/* Initialize 'targetm' variable which contains pointers to functions and data
205 * relating to the target machine. */
206
207struct gcc_target targetm = TARGET_INITIALIZER;
208
209
210/*****************************************************************************/
211/* TARGET HOOK IMPLEMENTATIONS */
212/*****************************************************************************/
213
214/* Return the fixed registers used for condition codes. */
215
216static bool
217crx_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
218{
219 *p1 = CC_REGNUM;
220 *p2 = INVALID_REGNUM;
221 return true;
222}
223
224/* Implements hook TARGET_STRUCT_VALUE_RTX. */
225
226static rtx
227crx_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
228 int incoming ATTRIBUTE_UNUSED)
229{
230 return gen_rtx_REG (Pmode, CRX_STRUCT_VALUE_REGNUM);
231}
232
233/* Implements hook TARGET_RETURN_IN_MEMORY. */
234
235static bool
586de218 236crx_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
db869733
PW
237{
238 if (TYPE_MODE (type) == BLKmode)
239 {
240 HOST_WIDE_INT size = int_size_in_bytes (type);
241 return (size == -1 || size > 8);
242 }
243 else
244 return false;
245}
246
247
248/*****************************************************************************/
249/* MACRO IMPLEMENTATIONS */
250/*****************************************************************************/
251
252/* STACK LAYOUT AND CALLING CONVENTIONS ROUTINES */
253/* --------------------------------------------- */
254
255/* Return nonzero if the current function being compiled is an interrupt
256 * function as specified by the "interrupt" attribute. */
257
258int
259crx_interrupt_function_p (void)
260{
261 tree attributes;
262
263 attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
264 return lookup_attribute ("interrupt", attributes) != NULL_TREE;
265}
266
267/* Compute values for the array save_regs and the variable sum_regs. The index
268 * of save_regs is numbers of register, each will get 1 if we need to save it
269 * in the current function, 0 if not. sum_regs is the total sum of the
270 * registers being saved. */
271
272static void
273crx_compute_save_regs (void)
274{
275 unsigned int regno;
276
277 /* initialize here so in case the function is no-return it will be -1. */
278 last_reg_to_save = -1;
279
280 /* No need to save any registers if the function never returns. */
281 if (FUNC_IS_NORETURN_P (current_function_decl))
282 return;
283
284 /* Initialize the number of bytes to be saved. */
285 sum_regs = 0;
286
287 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
288 {
289 if (fixed_regs[regno])
290 {
291 save_regs[regno] = 0;
292 continue;
293 }
294
295 /* If this reg is used and not call-used (except RA), save it. */
e95cfa3b 296 if (crx_interrupt_function_p ())
db869733
PW
297 {
298 if (!current_function_is_leaf && call_used_regs[regno])
299 /* this is a volatile reg in a non-leaf interrupt routine - save it
300 * for the sake of its sons. */
301 save_regs[regno] = 1;
302
6fb5fa3c 303 else if (df_regs_ever_live_p (regno))
db869733
PW
304 /* This reg is used - save it. */
305 save_regs[regno] = 1;
306 else
307 /* This reg is not used, and is not a volatile - don't save. */
308 save_regs[regno] = 0;
309 }
310 else
311 {
312 /* If this reg is used and not call-used (except RA), save it. */
6fb5fa3c 313 if (df_regs_ever_live_p (regno)
db869733
PW
314 && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
315 save_regs[regno] = 1;
316 else
317 save_regs[regno] = 0;
318 }
319 }
320
321 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
322 if (save_regs[regno] == 1)
323 {
324 last_reg_to_save = regno;
325 sum_regs += UNITS_PER_WORD;
326 }
327}
328
329/* Compute the size of the local area and the size to be adjusted by the
330 * prologue and epilogue. */
331
332static void
333crx_compute_frame (void)
334{
335 /* For aligning the local variables. */
336 int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
337 int padding_locals;
338
339 /* Padding needed for each element of the frame. */
340 local_vars_size = get_frame_size ();
341
342 /* Align to the stack alignment. */
343 padding_locals = local_vars_size % stack_alignment;
344 if (padding_locals)
345 padding_locals = stack_alignment - padding_locals;
346
347 local_vars_size += padding_locals;
348
349 size_for_adjusting_sp = local_vars_size + (ACCUMULATE_OUTGOING_ARGS ?
38173d38 350 crtl->outgoing_args_size : 0);
db869733
PW
351}
352
7b5cbb57
AS
353/* Worker function for TARGET_CAN_ELIMINATE. */
354
355bool
356crx_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
357{
358 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
359}
360
db869733
PW
361/* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
362
363int
364crx_initial_elimination_offset (int from, int to)
365{
366 /* Compute this since we need to use sum_regs. */
367 crx_compute_save_regs ();
368
369 /* Compute this since we need to use local_vars_size. */
370 crx_compute_frame ();
371
372 if ((from) == FRAME_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM)
373 return (ACCUMULATE_OUTGOING_ARGS ?
38173d38 374 crtl->outgoing_args_size : 0);
db869733
PW
375 else if ((from) == ARG_POINTER_REGNUM && (to) == FRAME_POINTER_REGNUM)
376 return (sum_regs + local_vars_size);
377 else if ((from) == ARG_POINTER_REGNUM && (to) == STACK_POINTER_REGNUM)
378 return (sum_regs + local_vars_size +
379 (ACCUMULATE_OUTGOING_ARGS ?
38173d38 380 crtl->outgoing_args_size : 0));
db869733
PW
381 else
382 abort ();
383}
384
385/* REGISTER USAGE */
386/* -------------- */
387
388/* Return the class number of the smallest class containing reg number REGNO.
389 * This could be a conditional expression or could index an array. */
390
391enum reg_class
392crx_regno_reg_class (int regno)
393{
394 if (regno >= 0 && regno < SP_REGNUM)
395 return NOSP_REGS;
396
e95cfa3b
PW
397 if (regno == SP_REGNUM)
398 return GENERAL_REGS;
db869733 399
e95cfa3b
PW
400 if (regno == LO_REGNUM)
401 return LO_REGS;
402 if (regno == HI_REGNUM)
403 return HI_REGS;
db869733
PW
404
405 return NO_REGS;
406}
407
408/* Transfer between HILO_REGS and memory via secondary reloading. */
409
410enum reg_class
0a2aaacc 411crx_secondary_reload_class (enum reg_class rclass,
db869733
PW
412 enum machine_mode mode ATTRIBUTE_UNUSED,
413 rtx x ATTRIBUTE_UNUSED)
414{
0a2aaacc 415 if (reg_classes_intersect_p (rclass, HILO_REGS)
db869733
PW
416 && true_regnum (x) == -1)
417 return GENERAL_REGS;
418
419 return NO_REGS;
420}
421
422/* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
423
424int
425crx_hard_regno_mode_ok (int regno, enum machine_mode mode)
426{
427 /* CC can only hold CCmode values. */
428 if (regno == CC_REGNUM)
429 return GET_MODE_CLASS (mode) == MODE_CC;
430 if (GET_MODE_CLASS (mode) == MODE_CC)
431 return 0;
432 /* HILO registers can only hold SImode and DImode */
433 if (HILO_REGNO_P (regno))
434 return mode == SImode || mode == DImode;
435 return 1;
436}
437
438/* PASSING FUNCTION ARGUMENTS */
439/* -------------------------- */
440
441/* If enough param regs are available for passing the param of type TYPE return
442 * the number of registers needed else 0. */
443
444static int
a6a54b6f 445enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
db869733
PW
446 enum machine_mode mode)
447{
448 int type_size;
449 int remaining_size;
450
451 if (mode != BLKmode)
452 type_size = GET_MODE_BITSIZE (mode);
453 else
454 type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
455
456 remaining_size =
457 BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS -
458 (MIN_REG_FOR_PASSING_ARGS + cum->ints) + 1);
459
460 /* Any variable which is too big to pass in two registers, will pass on
461 * stack. */
462 if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
463 return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
464
465 return 0;
466}
467
a6a54b6f 468/* Implements TARGET_FUNCTION_ARG. */
db869733 469
a6a54b6f
NF
470static rtx
471crx_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
472 const_tree type, bool named ATTRIBUTE_UNUSED)
db869733
PW
473{
474 last_parm_in_reg = 0;
475
e95cfa3b 476 /* Function_arg () is called with this type just after all the args have had
db869733
PW
477 * their registers assigned. The rtx that function_arg returns from this type
478 * is supposed to pass to 'gen_call' but currently it is not implemented (see
479 * macro GEN_CALL). */
480 if (type == void_type_node)
481 return NULL_RTX;
482
483 if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
484 return NULL_RTX;
485
486 if (mode == BLKmode)
487 {
488 /* Enable structures that need padding bytes at the end to pass to a
489 * function in registers. */
490 if (enough_regs_for_param (cum, type, mode) != 0)
491 {
492 last_parm_in_reg = 1;
493 return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
494 }
495 }
496
497 if (MIN_REG_FOR_PASSING_ARGS + cum->ints > MAX_REG_FOR_PASSING_ARGS)
498 return NULL_RTX;
499 else
500 {
501 if (enough_regs_for_param (cum, type, mode) != 0)
502 {
503 last_parm_in_reg = 1;
504 return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
505 }
506 }
507
508 return NULL_RTX;
509}
510
511/* Implements the macro INIT_CUMULATIVE_ARGS defined in crx.h. */
512
513void
514crx_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
515 rtx libfunc ATTRIBUTE_UNUSED)
516{
517 tree param, next_param;
518
519 cum->ints = 0;
520
521 /* Determine if this function has variable arguments. This is indicated by
522 * the last argument being 'void_type_mode' if there are no variable
523 * arguments. Change here for a different vararg. */
524 for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
525 param != (tree) 0; param = next_param)
526 {
527 next_param = TREE_CHAIN (param);
528 if (next_param == (tree) 0 && TREE_VALUE (param) != void_type_node)
529 {
530 cum->ints = -1;
531 return;
532 }
533 }
534}
535
a6a54b6f 536/* Implements TARGET_FUNCTION_ARG_ADVANCE. */
db869733 537
a6a54b6f 538static void
db869733 539crx_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
a6a54b6f 540 const_tree type, bool named ATTRIBUTE_UNUSED)
db869733
PW
541{
542 /* l holds the number of registers required */
543 int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
544
545 /* If the parameter isn't passed on a register don't advance cum. */
546 if (!last_parm_in_reg)
547 return;
548
549 if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
550 return;
551
552 if (mode == SImode || mode == HImode || mode == QImode || mode == DImode)
553 {
554 if (l <= 1)
555 cum->ints += 1;
556 else
557 cum->ints += l;
558 }
559 else if (mode == SFmode || mode == DFmode)
560 cum->ints += l;
561 else if ((mode) == BLKmode)
562 {
563 if ((l = enough_regs_for_param (cum, type, mode)) != 0)
564 cum->ints += l;
565 }
566
567}
568
a4d05547 569/* Implements the macro FUNCTION_ARG_REGNO_P defined in crx.h. Return nonzero
db869733
PW
570 * if N is a register used for passing parameters. */
571
572int
573crx_function_arg_regno_p (int n)
574{
575 return (n <= MAX_REG_FOR_PASSING_ARGS && n >= MIN_REG_FOR_PASSING_ARGS);
576}
577
578/* ADDRESSING MODES */
579/* ---------------- */
580
331d9186 581/* Implements the hook for TARGET_LEGITIMATE_ADDRESS_P defined in crx.h.
e95cfa3b 582 * The following addressing modes are supported on CRX:
db869733
PW
583 *
584 * Relocations --> const | symbol_ref | label_ref
a7b376ee
KH
585 * Absolute address --> 32-bit absolute
586 * Post increment --> reg + 12-bit disp.
587 * Post modify --> reg + 12-bit disp.
588 * Register relative --> reg | 32-bit disp. + reg | 4 bit + reg
589 * Scaled index --> reg + reg | 22-bit disp. + reg + reg |
590 * 22-disp. + reg + reg + (2 | 4 | 8) */
db869733 591
f8d0a23d
RH
592static rtx
593crx_addr_reg (rtx addr_reg)
db869733 594{
f8d0a23d
RH
595 if (GET_MODE (addr_reg) != Pmode)
596 return NULL_RTX;
e95cfa3b
PW
597
598 if (REG_P (addr_reg))
f8d0a23d
RH
599 return addr_reg;
600 else if (GET_CODE (addr_reg) == SUBREG
e95cfa3b 601 && REG_P (SUBREG_REG (addr_reg))
f8d0a23d
RH
602 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
603 <= UNITS_PER_WORD))
604 return SUBREG_REG (addr_reg);
e95cfa3b 605 else
f8d0a23d 606 return NULL_RTX;
e95cfa3b
PW
607}
608
609enum crx_addrtype
610crx_decompose_address (rtx addr, struct crx_address *out)
611{
612 rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX;
613 rtx scale_rtx = NULL_RTX, side_effect = NULL_RTX;
614 int scale = -1;
615
616 enum crx_addrtype retval = CRX_INVALID;
617
618 switch (GET_CODE (addr))
db869733 619 {
e95cfa3b
PW
620 case CONST_INT:
621 /* Absolute address (known at compile time) */
622 retval = CRX_ABSOLUTE;
623 disp = addr;
624 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), GET_MODE_BITSIZE (Pmode)))
625 return CRX_INVALID;
626 break;
627
628 case CONST:
629 case SYMBOL_REF:
630 case LABEL_REF:
631 /* Absolute address (known at link time) */
632 retval = CRX_ABSOLUTE;
633 disp = addr;
634 break;
db869733 635
e95cfa3b
PW
636 case REG:
637 case SUBREG:
638 /* Register relative address */
639 retval = CRX_REG_REL;
640 base = addr;
641 break;
db869733 642
e95cfa3b
PW
643 case PLUS:
644 switch (GET_CODE (XEXP (addr, 0)))
645 {
646 case REG:
647 case SUBREG:
648 if (REG_P (XEXP (addr, 1)))
649 {
650 /* Scaled index with scale = 1 and disp. = 0 */
651 retval = CRX_SCALED_INDX;
652 base = XEXP (addr, 1);
653 index = XEXP (addr, 0);
654 scale = 1;
655 }
656 else if (RTX_SIGNED_INT_FITS_N_BITS (XEXP (addr, 1), 28))
657 {
658 /* Register relative address and <= 28-bit disp. */
659 retval = CRX_REG_REL;
660 base = XEXP (addr, 0);
661 disp = XEXP (addr, 1);
662 }
663 else
664 return CRX_INVALID;
665 break;
db869733 666
e95cfa3b
PW
667 case PLUS:
668 /* Scaled index and <= 22-bit disp. */
669 retval = CRX_SCALED_INDX;
670 base = XEXP (XEXP (addr, 0), 1);
671 disp = XEXP (addr, 1);
672 if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 22))
673 return CRX_INVALID;
674 switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
675 {
676 case REG:
677 /* Scaled index with scale = 0 and <= 22-bit disp. */
678 index = XEXP (XEXP (addr, 0), 0);
679 scale = 1;
680 break;
681
682 case MULT:
683 /* Scaled index with scale >= 0 and <= 22-bit disp. */
684 index = XEXP (XEXP (XEXP (addr, 0), 0), 0);
685 scale_rtx = XEXP (XEXP (XEXP (addr, 0), 0), 1);
686 if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1)
687 return CRX_INVALID;
688 break;
db869733 689
e95cfa3b
PW
690 default:
691 return CRX_INVALID;
692 }
693 break;
694
695 case MULT:
696 /* Scaled index with scale >= 0 */
697 retval = CRX_SCALED_INDX;
698 base = XEXP (addr, 1);
699 index = XEXP (XEXP (addr, 0), 0);
700 scale_rtx = XEXP (XEXP (addr, 0), 1);
701 /* Scaled index with scale >= 0 and <= 22-bit disp. */
702 if ((scale = SCALE_FOR_INDEX_P (scale_rtx)) == -1)
703 return CRX_INVALID;
704 break;
705
706 default:
707 return CRX_INVALID;
708 }
709 break;
710
711 case POST_INC:
712 case POST_DEC:
713 /* Simple post-increment */
714 retval = CRX_POST_INC;
715 base = XEXP (addr, 0);
716 side_effect = addr;
717 break;
718
719 case POST_MODIFY:
720 /* Generic post-increment with <= 12-bit disp. */
721 retval = CRX_POST_INC;
722 base = XEXP (addr, 0);
723 side_effect = XEXP (addr, 1);
724 if (base != XEXP (side_effect, 0))
725 return CRX_INVALID;
726 switch (GET_CODE (side_effect))
727 {
728 case PLUS:
729 case MINUS:
730 disp = XEXP (side_effect, 1);
731 if (!RTX_SIGNED_INT_FITS_N_BITS (disp, 12))
732 return CRX_INVALID;
733 break;
734
735 default:
736 /* CRX only supports PLUS and MINUS */
737 return CRX_INVALID;
738 }
739 break;
740
741 default:
742 return CRX_INVALID;
db869733
PW
743 }
744
f8d0a23d
RH
745 if (base)
746 {
747 base = crx_addr_reg (base);
748 if (!base)
749 return CRX_INVALID;
750 }
751 if (index)
752 {
753 index = crx_addr_reg (index);
754 if (!index)
755 return CRX_INVALID;
756 }
e95cfa3b
PW
757
758 out->base = base;
759 out->index = index;
760 out->disp = disp;
761 out->scale = scale;
762 out->side_effect = side_effect;
763
764 return retval;
765}
766
c6c3dba9 767bool
e95cfa3b 768crx_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
c6c3dba9 769 rtx addr, bool strict)
e95cfa3b
PW
770{
771 enum crx_addrtype addrtype;
772 struct crx_address address;
773
774 if (TARGET_DEBUG_ADDR)
775 {
776 fprintf (stderr,
777 "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n",
778 GET_MODE_NAME (mode), strict);
779 debug_rtx (addr);
780 }
781
782 addrtype = crx_decompose_address (addr, &address);
783
784 if (addrtype == CRX_POST_INC && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
785 return FALSE;
786
787 if (TARGET_DEBUG_ADDR)
db869733 788 {
e95cfa3b
PW
789 const char *typestr;
790 switch (addrtype)
db869733 791 {
e95cfa3b
PW
792 case CRX_INVALID:
793 typestr = "Invalid";
794 break;
795 case CRX_REG_REL:
796 typestr = "Register relative";
797 break;
798 case CRX_POST_INC:
799 typestr = "Post-increment";
800 break;
801 case CRX_SCALED_INDX:
802 typestr = "Scaled index";
803 break;
804 case CRX_ABSOLUTE:
805 typestr = "Absolute";
806 break;
807 default:
808 abort ();
db869733 809 }
e95cfa3b 810 fprintf (stderr, "CRX Address type: %s\n", typestr);
db869733 811 }
e95cfa3b
PW
812
813 if (addrtype == CRX_INVALID)
814 return FALSE;
db869733 815
e95cfa3b
PW
816 if (strict)
817 {
818 if (address.base && !REGNO_OK_FOR_BASE_P (REGNO (address.base)))
819 {
820 if (TARGET_DEBUG_ADDR)
821 fprintf (stderr, "Base register not strict\n");
822 return FALSE;
823 }
824 if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
825 {
826 if (TARGET_DEBUG_ADDR)
827 fprintf (stderr, "Index register not strict\n");
828 return FALSE;
829 }
830 }
831
832 return TRUE;
db869733
PW
833}
834
835/* ROUTINES TO COMPUTE COSTS */
836/* ------------------------- */
837
e95cfa3b
PW
838/* Return cost of the memory address x. */
839
840static int
f40751dd 841crx_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
e95cfa3b
PW
842{
843 enum crx_addrtype addrtype;
844 struct crx_address address;
845
846 int cost = 2;
847
848 addrtype = crx_decompose_address (addr, &address);
849
850 gcc_assert (addrtype != CRX_INVALID);
851
852 /* An absolute address causes a 3-word instruction */
853 if (addrtype == CRX_ABSOLUTE)
854 cost+=2;
855
57b51d4d 856 /* Post-modifying addresses are more powerful. */
e95cfa3b
PW
857 if (addrtype == CRX_POST_INC)
858 cost-=2;
859
860 /* Attempt to minimize number of registers in the address. */
861 if (address.base)
862 cost++;
863
864 if (address.index && address.scale == 1)
865 cost+=5;
866
55d61dba
PW
867 if (address.disp && !INT_CST4 (INTVAL (address.disp)))
868 cost+=2;
869
870 if (TARGET_DEBUG_ADDR)
871 {
872 fprintf (stderr, "\n======\nTARGET_ADDRESS_COST = %d\n", cost);
873 debug_rtx (addr);
874 }
875
e95cfa3b
PW
876 return cost;
877}
878
db869733 879/* Return the cost of moving data of mode MODE between a register of class
0a2aaacc 880 * RCLASS and memory; IN is zero if the value is to be written to memory,
a4d05547
KH
881 * nonzero if it is to be read in. This cost is relative to those in
882 * REGISTER_MOVE_COST. */
db869733
PW
883
884int
885crx_memory_move_cost (enum machine_mode mode,
0a2aaacc 886 enum reg_class rclass ATTRIBUTE_UNUSED,
db869733
PW
887 int in ATTRIBUTE_UNUSED)
888{
889 /* One LD or ST takes twice the time of a simple reg-reg move */
0a2aaacc 890 if (reg_classes_intersect_p (rclass, GENERAL_REGS))
db869733 891 {
e95cfa3b 892 /* printf ("GENERAL_REGS LD/ST = %d\n", 4 * HARD_REGNO_NREGS (0, mode));*/
db869733
PW
893 return 4 * HARD_REGNO_NREGS (0, mode);
894 }
0a2aaacc 895 else if (reg_classes_intersect_p (rclass, HILO_REGS))
db869733
PW
896 {
897 /* HILO to memory and vice versa */
e95cfa3b
PW
898 /* printf ("HILO_REGS %s = %d\n", in ? "LD" : "ST",
899 (REGISTER_MOVE_COST (mode,
db869733
PW
900 in ? GENERAL_REGS : HILO_REGS,
901 in ? HILO_REGS : GENERAL_REGS) + 4)
902 * HARD_REGNO_NREGS (0, mode)); */
e95cfa3b 903 return (REGISTER_MOVE_COST (mode,
db869733
PW
904 in ? GENERAL_REGS : HILO_REGS,
905 in ? HILO_REGS : GENERAL_REGS) + 4)
906 * HARD_REGNO_NREGS (0, mode);
907 }
908 else /* default (like in i386) */
909 {
e95cfa3b 910 /* printf ("ANYREGS = 100\n"); */
db869733
PW
911 return 100;
912 }
913}
914
915/* INSTRUCTION OUTPUT */
916/* ------------------ */
917
db869733
PW
918/* Check if a const_double is ok for crx store-immediate instructions */
919
920int
921crx_const_double_ok (rtx op)
922{
923 if (GET_MODE (op) == DFmode)
924 {
925 REAL_VALUE_TYPE r;
926 long l[2];
927 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
928 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
e95cfa3b
PW
929 return (UNSIGNED_INT_FITS_N_BITS (l[0], 4) &&
930 UNSIGNED_INT_FITS_N_BITS (l[1], 4)) ? 1 : 0;
db869733
PW
931 }
932
933 if (GET_MODE (op) == SFmode)
934 {
935 REAL_VALUE_TYPE r;
936 long l;
937 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
938 REAL_VALUE_TO_TARGET_SINGLE (r, l);
e95cfa3b 939 return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
db869733
PW
940 }
941
942 return (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4) &&
943 UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4)) ? 1 : 0;
944}
945
946/* Implements the macro PRINT_OPERAND defined in crx.h. */
947
948void
949crx_print_operand (FILE * file, rtx x, int code)
950{
951 switch (code)
952 {
953 case 'p' :
954 if (GET_CODE (x) == REG) {
955 if (GET_MODE (x) == DImode || GET_MODE (x) == DFmode)
956 {
957 int regno = REGNO (x);
958 if (regno + 1 >= SP_REGNUM) abort ();
959 fprintf (file, "{%s, %s}", reg_names[regno], reg_names[regno + 1]);
960 return;
961 }
962 else
963 {
964 if (REGNO (x) >= SP_REGNUM) abort ();
965 fprintf (file, "%s", reg_names[REGNO (x)]);
966 return;
967 }
968 }
969
970 case 'd' :
971 {
972 const char *crx_cmp_str;
973 switch (GET_CODE (x))
e95cfa3b 974 { /* MD: compare (reg, reg or imm) but CRX: cmp (reg or imm, reg)
db869733
PW
975 * -> swap all non symmetric ops */
976 case EQ : crx_cmp_str = "eq"; break;
977 case NE : crx_cmp_str = "ne"; break;
978 case GT : crx_cmp_str = "lt"; break;
979 case GTU : crx_cmp_str = "lo"; break;
980 case LT : crx_cmp_str = "gt"; break;
981 case LTU : crx_cmp_str = "hi"; break;
982 case GE : crx_cmp_str = "le"; break;
983 case GEU : crx_cmp_str = "ls"; break;
984 case LE : crx_cmp_str = "ge"; break;
985 case LEU : crx_cmp_str = "hs"; break;
986 default : abort ();
987 }
988 fprintf (file, "%s", crx_cmp_str);
989 return;
990 }
991
992 case 'H':
993 /* Print high part of a double precision value. */
994 switch (GET_CODE (x))
995 {
996 case CONST_DOUBLE:
997 if (GET_MODE (x) == SFmode) abort ();
998 if (GET_MODE (x) == DFmode)
999 {
1000 /* High part of a DF const. */
1001 REAL_VALUE_TYPE r;
1002 long l[2];
1003
1004 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1005 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
1006
1007 fprintf (file, "$0x%lx", l[1]);
1008 return;
1009 }
1010
1011 /* -- Fallthrough to handle DI consts -- */
1012
1013 case CONST_INT:
1014 {
1015 rtx high, low;
1016 split_double (x, &low, &high);
1017 putc ('$', file);
1018 output_addr_const (file, high);
1019 return;
1020 }
1021
1022 case REG:
1023 if (REGNO (x) + 1 >= FIRST_PSEUDO_REGISTER) abort ();
1024 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1025 return;
1026
1027 case MEM:
1028 /* Adjust memory address to high part. */
1029 {
1030 rtx adj_mem = x;
1031 adj_mem = adjust_address (adj_mem, GET_MODE (adj_mem), 4);
1032
1033 output_memory_reference_mode = GET_MODE (adj_mem);
1034 output_address (XEXP (adj_mem, 0));
1035 return;
1036 }
1037
1038 default:
1039 abort ();
1040 }
1041
1042 case 'L':
1043 /* Print low part of a double precision value. */
1044 switch (GET_CODE (x))
1045 {
1046 case CONST_DOUBLE:
1047 if (GET_MODE (x) == SFmode) abort ();
1048 if (GET_MODE (x) == DFmode)
1049 {
1050 /* High part of a DF const. */
1051 REAL_VALUE_TYPE r;
1052 long l[2];
1053
1054 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1055 REAL_VALUE_TO_TARGET_DOUBLE (r, l);
1056
1057 fprintf (file, "$0x%lx", l[0]);
1058 return;
1059 }
1060
1061 /* -- Fallthrough to handle DI consts -- */
1062
1063 case CONST_INT:
1064 {
1065 rtx high, low;
1066 split_double (x, &low, &high);
1067 putc ('$', file);
1068 output_addr_const (file, low);
1069 return;
1070 }
1071
1072 case REG:
1073 fprintf (file, "%s", reg_names[REGNO (x)]);
1074 return;
1075
1076 case MEM:
1077 output_memory_reference_mode = GET_MODE (x);
1078 output_address (XEXP (x, 0));
1079 return;
1080
1081 default:
1082 abort ();
1083 }
1084
1085 case 0 : /* default */
e95cfa3b 1086 switch (GET_CODE (x))
db869733
PW
1087 {
1088 case REG:
1089 fprintf (file, "%s", reg_names[REGNO (x)]);
1090 return;
1091
1092 case MEM:
1093 output_memory_reference_mode = GET_MODE (x);
1094 output_address (XEXP (x, 0));
1095 return;
1096
1097 case CONST_DOUBLE:
1098 {
1099 REAL_VALUE_TYPE r;
1100 long l;
1101
1102 /* Always use H and L for double precision - see above */
e95cfa3b 1103 gcc_assert (GET_MODE (x) == SFmode);
db869733
PW
1104
1105 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1106 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1107
1108 fprintf (file, "$0x%lx", l);
1109 return;
1110 }
1111
1112 default:
1113 putc ('$', file);
1114 output_addr_const (file, x);
1115 return;
1116 }
1117
1118 default:
1119 output_operand_lossage ("invalid %%xn code");
1120 }
1121
1122 abort ();
1123}
1124
1125/* Implements the macro PRINT_OPERAND_ADDRESS defined in crx.h. */
1126
1127void
1128crx_print_operand_address (FILE * file, rtx addr)
1129{
e95cfa3b
PW
1130 enum crx_addrtype addrtype;
1131 struct crx_address address;
1132
1133 int offset;
1134
1135 addrtype = crx_decompose_address (addr, &address);
1136
1137 if (address.disp)
1138 offset = INTVAL (address.disp);
1139 else
1140 offset = 0;
db869733 1141
e95cfa3b 1142 switch (addrtype)
db869733 1143 {
e95cfa3b
PW
1144 case CRX_REG_REL:
1145 fprintf (file, "%d(%s)", offset, reg_names[REGNO (address.base)]);
1146 return;
1147
1148 case CRX_POST_INC:
1149 switch (GET_CODE (address.side_effect))
db869733 1150 {
e95cfa3b 1151 case PLUS:
db869733 1152 break;
e95cfa3b
PW
1153 case MINUS:
1154 offset = -offset;
db869733 1155 break;
e95cfa3b
PW
1156 case POST_INC:
1157 offset = GET_MODE_SIZE (output_memory_reference_mode);
db869733 1158 break;
e95cfa3b
PW
1159 case POST_DEC:
1160 offset = -GET_MODE_SIZE (output_memory_reference_mode);
db869733 1161 break;
e95cfa3b
PW
1162 default:
1163 abort ();
db869733 1164 }
e95cfa3b
PW
1165 fprintf (file, "%d(%s)+", offset, reg_names[REGNO (address.base)]);
1166 return;
1167
1168 case CRX_SCALED_INDX:
1169 fprintf (file, "%d(%s, %s, %d)", offset, reg_names[REGNO (address.base)],
1170 reg_names[REGNO (address.index)], address.scale);
1171 return;
1172
1173 case CRX_ABSOLUTE:
1174 output_addr_const (file, address.disp);
1175 return;
1176
db869733 1177 default:
e95cfa3b 1178 abort ();
db869733 1179 }
db869733
PW
1180}
1181
1182
1183/*****************************************************************************/
1184/* MACHINE DESCRIPTION HELPER-FUNCTIONS */
1185/*****************************************************************************/
1186
1187void crx_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase,
1188 rtx tmp_reg, unsigned HOST_WIDE_INT *offset_p)
1189{
1190 rtx addr, mem;
1191 unsigned HOST_WIDE_INT offset = *offset_p;
1192
1193 /* Load */
1194 addr = plus_constant (src, offset);
1195 mem = adjust_automodify_address (srcbase, SImode, addr, offset);
1196 emit_move_insn (tmp_reg, mem);
1197
1198 /* Store */
1199 addr = plus_constant (dst, offset);
1200 mem = adjust_automodify_address (dstbase, SImode, addr, offset);
1201 emit_move_insn (mem, tmp_reg);
1202
1203 *offset_p = offset + 4;
1204}
1205
1206int
1207crx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp)
1208{
1209 unsigned HOST_WIDE_INT count = 0, offset, si_moves, i;
1210 HOST_WIDE_INT align = 0;
1211
1212 rtx src, dst;
1213 rtx tmp_reg;
1214
1215 if (GET_CODE (align_exp) == CONST_INT)
1216 { /* Only if aligned */
1217 align = INTVAL (align_exp);
e95cfa3b
PW
1218 if (align & 3)
1219 return 0;
db869733
PW
1220 }
1221
1222 if (GET_CODE (count_exp) == CONST_INT)
1223 { /* No more than 16 SImode moves */
1224 count = INTVAL (count_exp);
e95cfa3b
PW
1225 if (count > 64)
1226 return 0;
db869733
PW
1227 }
1228
e95cfa3b 1229 tmp_reg = gen_reg_rtx (SImode);
db869733
PW
1230
1231 /* Create psrs for the src and dest pointers */
1232 dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0));
1233 if (dst != XEXP (dstbase, 0))
1234 dstbase = replace_equiv_address_nv (dstbase, dst);
1235 src = copy_to_mode_reg (Pmode, XEXP (srcbase, 0));
1236 if (src != XEXP (srcbase, 0))
1237 srcbase = replace_equiv_address_nv (srcbase, src);
1238
1239 offset = 0;
1240
1241 /* Emit SImode moves */
1242 si_moves = count >> 2;
1243 for (i = 0; i < si_moves; i++)
1244 crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
1245
1246 /* Special cases */
1247 if (count & 3)
1248 {
1249 offset = count - 4;
1250 crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);
1251 }
1252
1253 gcc_assert (offset == count);
1254
1255 return 1;
1256}
1257
db869733
PW
1258static void
1259mpushpop_str (char *stringbuffer, const char *mnemonic, char *mask)
1260{
e95cfa3b 1261 if (strlen (mask) > 2 || crx_interrupt_function_p ()) /* needs 2-word instr. */
db869733
PW
1262 sprintf (stringbuffer, "\n\t%s\tsp, {%s}", mnemonic, mask);
1263 else /* single word instruction */
1264 sprintf (stringbuffer, "\n\t%s\t%s", mnemonic, mask);
1265}
1266
1267/* Called from crx.md. The return value depends on the parameter push_or_pop:
1268 * When push_or_pop is zero -> string for push instructions of prologue.
1269 * When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1270 * Relies on the assumptions:
1271 * 1. RA is the last register to be saved.
1272 * 2. The maximal value of the counter is MAX_COUNT. */
1273
1274char *
1275crx_prepare_push_pop_string (int push_or_pop)
1276{
1277 /* j is the number of registers being saved, takes care that there won't be
1278 * more than 8 in one push/pop instruction */
1279
1280 /* For the register mask string */
1281 static char mask_str[50];
1282
1283 /* i is the index of save_regs[], going from 0 until last_reg_to_save */
1284 int i = 0;
1285
1286 int ra_in_bitmask = 0;
1287
1288 char *return_str;
1289
1290 /* For reversing on the push instructions if there are more than one. */
1291 char *temp_str;
1292
1293 return_str = (char *) xmalloc (120);
1294 temp_str = (char *) xmalloc (120);
1295
1296 /* Initialize */
1297 memset (return_str, 0, 3);
1298
1299 while (i <= last_reg_to_save)
1300 {
1301 /* Prepare mask for one instruction. */
1302 mask_str[0] = 0;
1303
1304 if (i <= SP_REGNUM)
1305 { /* Add regs unit full or SP register reached */
1306 int j = 0;
1307 while (j < MAX_COUNT && i <= SP_REGNUM)
1308 {
1309 if (save_regs[i])
1310 {
1311 /* TODO to use ra_in_bitmask for detecting last pop is not
1312 * smart it prevents things like: popret r5 */
1313 if (i == RETURN_ADDRESS_REGNUM) ra_in_bitmask = 1;
1314 if (j > 0) strcat (mask_str, ", ");
1315 strcat (mask_str, reg_names[i]);
1316 ++j;
1317 }
1318 ++i;
1319 }
1320 }
1321 else
1322 {
1323 /* Handle hi/lo savings */
1324 while (i <= last_reg_to_save)
1325 {
1326 if (save_regs[i])
1327 {
1328 strcat (mask_str, "lo, hi");
1329 i = last_reg_to_save + 1;
1330 break;
1331 }
1332 ++i;
1333 }
1334 }
1335
e95cfa3b 1336 if (strlen (mask_str) == 0) continue;
db869733
PW
1337
1338 if (push_or_pop == 1)
1339 {
1340 if (crx_interrupt_function_p ())
1341 mpushpop_str (temp_str, "popx", mask_str);
1342 else
1343 {
1344 if (ra_in_bitmask)
1345 {
1346 mpushpop_str (temp_str, "popret", mask_str);
1347 ra_in_bitmask = 0;
1348 }
1349 else mpushpop_str (temp_str, "pop", mask_str);
1350 }
1351
1352 strcat (return_str, temp_str);
1353 }
1354 else
1355 {
1356 /* push - We need to reverse the order of the instructions if there
1357 * are more than one. (since the pop will not be reversed in the
1358 * epilogue */
1359 if (crx_interrupt_function_p ())
1360 mpushpop_str (temp_str, "pushx", mask_str);
1361 else
1362 mpushpop_str (temp_str, "push", mask_str);
1363 strcat (temp_str, return_str);
1364 strcpy (strcat (return_str, "\t"), temp_str);
1365 }
1366
1367 }
1368
1369 if (push_or_pop == 1)
1370 {
1371 /* pop */
1372 if (crx_interrupt_function_p ())
1373 strcat (return_str, "\n\tretx\n");
1374
1375 else if (!FUNC_IS_NORETURN_P (current_function_decl)
1376 && !save_regs[RETURN_ADDRESS_REGNUM])
1377 strcat (return_str, "\n\tjump\tra\n");
1378 }
1379
1380 /* Skip the newline and the tab in the start of return_str. */
1381 return_str += 2;
1382 return return_str;
1383}
1384
1385/* CompactRISC CRX Architecture stack layout:
1386
1387 0 +---------------------
1388 |
1389 .
1390 .
1391 |
1392 +==================== Sp(x)=Ap(x+1)
1393 A | Args for functions
1394 | | called by X and Dynamically
1395 | | Dynamic allocations allocated and
1396 | | (alloca, variable deallocated
1397 Stack | length arrays).
1398 grows +-------------------- Fp(x)
a4174ebf 1399 down| | Local variables of X
db869733
PW
1400 ward| +--------------------
1401 | | Regs saved for X-1
1402 | +==================== Sp(x-1)=Ap(x)
1403 | Args for func X
1404 | pushed by X-1
1405 +-------------------- Fp(x-1)
1406 |
1407 |
1408 V
1409
1410*/
1411
1412void
1413crx_expand_prologue (void)
1414{
1415 crx_compute_frame ();
1416 crx_compute_save_regs ();
1417
1418 /* If there is no need in push and adjustment to sp, return. */
1419 if (size_for_adjusting_sp + sum_regs == 0)
1420 return;
1421
1422 if (last_reg_to_save != -1)
1423 /* If there are registers to push. */
1424 emit_insn (gen_push_for_prologue (GEN_INT (sum_regs)));
1425
1426 if (size_for_adjusting_sp > 0)
1427 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
e95cfa3b 1428 GEN_INT (-size_for_adjusting_sp)));
db869733
PW
1429
1430 if (frame_pointer_needed)
1431 /* Initialize the frame pointer with the value of the stack pointer
1432 * pointing now to the locals. */
1433 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1434}
1435
1436/* Generate insn that updates the stack for local variables and padding for
1437 * registers we save. - Generate the appropriate return insn. */
1438
1439void
1440crx_expand_epilogue (void)
1441{
db869733
PW
1442 /* Nonzero if we need to return and pop only RA. This will generate a
1443 * different insn. This differentiate is for the peepholes for call as last
1444 * statement in function. */
1445 int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM]
1446 && (sum_regs == UNITS_PER_WORD));
1447
db869733
PW
1448 if (frame_pointer_needed)
1449 /* Restore the stack pointer with the frame pointers value */
1450 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
1451
1452 if (size_for_adjusting_sp > 0)
1453 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1454 GEN_INT (size_for_adjusting_sp)));
1455
1456 if (crx_interrupt_function_p ())
1457 emit_jump_insn (gen_interrupt_return ());
1458 else if (last_reg_to_save == -1)
1459 /* Nothing to pop */
1460 /* Don't output jump for interrupt routine, only retx. */
1461 emit_jump_insn (gen_indirect_jump_return ());
1462 else if (only_popret_RA)
1463 emit_jump_insn (gen_popret_RA_return ());
1464 else
1465 emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));
1466}