1 /* Output routines for CR16 processor.
2 Copyright (C) 2012-2013 Free Software Foundation, Inc.
3 Contributed by KPIT Cummins Infosystems Limited.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "stor-layout.h"
31 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
35 #include "insn-codes.h"
36 #include "insn-attr.h"
43 #include "diagnostic-core.h"
44 #include "basic-block.h"
46 #include "target-def.h"
51 /* Maximum number of register used for passing parameters. */
52 #define MAX_REG_FOR_PASSING_ARGS 6
54 /* Minimum number register used for passing parameters. */
55 #define MIN_REG_FOR_PASSING_ARGS 2
57 /* The maximum count of words supported in the assembly of the architecture in
58 a push/pop instruction. */
61 /* Predicate is true if the current function is a 'noreturn' function,
62 i.e. it is qualified as volatile. */
63 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
65 /* Predicate that holds when we need to save registers even for 'noreturn'
66 functions, to accommodate for unwinding. */
67 #define MUST_SAVE_REGS_P() \
68 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
70 /* Nonzero if the rtx X is a signed const int of n bits. */
71 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
72 ((GET_CODE (X) == CONST_INT \
73 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
75 /* Nonzero if the rtx X is an unsigned const int of n bits. */
76 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
77 ((GET_CODE (X) == CONST_INT \
78 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
80 /* Structure for stack computations. */
82 /* variable definitions in the struture
83 args_size Number of bytes saved on the stack for local
86 reg_size Number of bytes saved on the stack for
89 total_size The sum of 2 sizes: locals vars and padding byte
90 for saving the registers. Used in expand_prologue()
93 last_reg_to_save Will hold the number of the last register the
94 prologue saves, -1 if no register is saved
96 save_regs[16] Each object in the array is a register number.
97 Mark 1 for registers that need to be saved
99 num_regs Number of registers saved
101 initialized Non-zero if frame size already calculated, not
104 function_makes_calls Does the function make calls ? not used yet. */
106 struct cr16_frame_info
108 unsigned long var_size
;
109 unsigned long args_size
;
110 unsigned int reg_size
;
111 unsigned long total_size
;
112 long last_reg_to_save
;
113 long save_regs
[FIRST_PSEUDO_REGISTER
];
116 int function_makes_calls
;
119 /* Current frame information calculated by cr16_compute_frame_size. */
120 static struct cr16_frame_info current_frame_info
;
122 /* Static Variables. */
124 /* Data model that was supplied by user via command line option
125 This will be overridden in case of invalid combination
126 of core and data model options are supplied. */
127 static enum data_model_type data_model
= DM_DEFAULT
;
129 /* TARGETM Function Prototypes and forward declarations */
130 static void cr16_print_operand (FILE *, rtx
, int);
131 static void cr16_print_operand_address (FILE *, rtx
);
133 /* Stack layout and calling conventions. */
134 #undef TARGET_STRUCT_VALUE_RTX
135 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
136 #undef TARGET_RETURN_IN_MEMORY
137 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
139 /* Target-specific uses of '__attribute__'. */
140 #undef TARGET_ATTRIBUTE_TABLE
141 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
142 #undef TARGET_NARROW_VOLATILE_BITFIELD
143 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
146 #undef TARGET_UNWIND_WORD_MODE
147 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
149 /* Override Options. */
150 #undef TARGET_OPTION_OVERRIDE
151 #define TARGET_OPTION_OVERRIDE cr16_override_options
153 /* Conditional register usuage. */
154 #undef TARGET_CONDITIONAL_REGISTER_USAGE
155 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
157 /* Controlling register spills. */
158 #undef TARGET_CLASS_LIKELY_SPILLED_P
159 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
161 /* Passing function arguments. */
162 #undef TARGET_FUNCTION_ARG
163 #define TARGET_FUNCTION_ARG cr16_function_arg
164 #undef TARGET_FUNCTION_ARG_ADVANCE
165 #define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
166 #undef TARGET_RETURN_POPS_ARGS
167 #define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
169 /* Initialize the GCC target structure. */
170 #undef TARGET_FRAME_POINTER_REQUIRED
171 #define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required
172 #undef TARGET_CAN_ELIMINATE
173 #define TARGET_CAN_ELIMINATE cr16_can_eliminate
174 #undef TARGET_LEGITIMIZE_ADDRESS
175 #define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address
176 #undef TARGET_LEGITIMATE_CONSTANT_P
177 #define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p
178 #undef TARGET_LEGITIMATE_ADDRESS_P
179 #define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p
181 /* Returning function value. */
182 #undef TARGET_FUNCTION_VALUE
183 #define TARGET_FUNCTION_VALUE cr16_function_value
184 #undef TARGET_LIBCALL_VALUE
185 #define TARGET_LIBCALL_VALUE cr16_libcall_value
186 #undef TARGET_FUNCTION_VALUE_REGNO_P
187 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
189 /* printing the values. */
190 #undef TARGET_PRINT_OPERAND
191 #define TARGET_PRINT_OPERAND cr16_print_operand
192 #undef TARGET_PRINT_OPERAND_ADDRESS
193 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
195 /* Relative costs of operations. */
196 #undef TARGET_ADDRESS_COST
197 #define TARGET_ADDRESS_COST cr16_address_cost
198 #undef TARGET_REGISTER_MOVE_COST
199 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
200 #undef TARGET_MEMORY_MOVE_COST
201 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
203 /* Table of machine attributes. */
204 static const struct attribute_spec cr16_attribute_table
[] = {
205 /* ISRs have special prologue and epilogue requirements. */
206 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
207 affects_type_identity }. */
208 {"interrupt", 0, 0, false, true, true, NULL
, false},
209 {NULL
, 0, 0, false, false, false, NULL
, false}
212 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
213 .?byte directive along with @c is not understood by assembler.
214 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
215 as TARGET_ASM_ALIGNED_xx_OP. */
216 #undef TARGET_ASM_UNALIGNED_HI_OP
217 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
218 #undef TARGET_ASM_UNALIGNED_SI_OP
219 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
220 #undef TARGET_ASM_UNALIGNED_DI_OP
221 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
223 /* Target hook implementations. */
225 /* Implements hook TARGET_RETURN_IN_MEMORY. */
227 cr16_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
229 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
230 return ((size
== -1) || (size
> 8));
233 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
235 cr16_class_likely_spilled_p (reg_class_t rclass
)
237 if ((rclass
) == SHORT_REGS
|| (rclass
) == DOUBLE_BASE_REGS
238 || (rclass
) == LONG_REGS
|| (rclass
) == GENERAL_REGS
)
245 cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
,
246 tree funtype ATTRIBUTE_UNUSED
,
247 int size ATTRIBUTE_UNUSED
)
252 /* Returns true if data model selected via command line option
253 is same as function argument. */
255 cr16_is_data_model (enum data_model_type model
)
257 return (model
== data_model
);
260 /* Parse relevant options and override. */
262 cr16_override_options (void)
264 /* Disable -fdelete-null-pointer-checks option for CR16 target.
265 Programs which rely on NULL pointer dereferences _not_ halting the
266 program may not work properly with this option. So disable this
268 flag_delete_null_pointer_checks
= 0;
270 /* FIXME: To avoid spill_failure ICE during exception handling,
271 * disable cse_fllow_jumps. The spill error occurs when compiler
272 * can't find a suitable candidate in GENERAL_REGS class to reload
274 * Need to find a better way of avoiding this situation. */
276 flag_cse_follow_jumps
= 0;
278 /* If -fpic option, data_model == DM_FAR. */
279 if (flag_pic
== NEAR_PIC
)
284 /* The only option we want to examine is data model option. */
287 if (strcmp (cr16_data_model
, "medium") == 0)
288 data_model
= DM_DEFAULT
;
289 else if (strcmp (cr16_data_model
, "near") == 0)
290 data_model
= DM_NEAR
;
291 else if (strcmp (cr16_data_model
, "far") == 0)
296 error ("data-model=far not valid for cr16c architecture");
299 error ("invalid data model option -mdata-model=%s", cr16_data_model
);
302 data_model
= DM_DEFAULT
;
305 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
307 cr16_conditional_register_usage (void)
311 fixed_regs
[12] = call_used_regs
[12] = 1;
315 /* Stack layout and calling conventions routines. */
317 /* Return nonzero if the current function being compiled is an interrupt
318 function as specified by the "interrupt" attribute. */
320 cr16_interrupt_function_p (void)
324 attributes
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
325 return (lookup_attribute ("interrupt", attributes
) != NULL_TREE
);
328 /* Compute values for the array current_frame_info.save_regs and the variable
329 current_frame_info.reg_size. The index of current_frame_info.save_regs
330 is numbers of register, each will get 1 if we need to save it in the
331 current function, 0 if not. current_frame_info.reg_size is the total sum
332 of the registers being saved. */
334 cr16_compute_save_regs (void)
338 /* Initialize here so in case the function is no-return it will be -1. */
339 current_frame_info
.last_reg_to_save
= -1;
341 /* Initialize the number of bytes to be saved. */
342 current_frame_info
.reg_size
= 0;
344 /* No need to save any registers if the function never returns. */
345 if (FUNC_IS_NORETURN_P (current_function_decl
) && !MUST_SAVE_REGS_P ())
348 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
350 if (fixed_regs
[regno
])
352 current_frame_info
.save_regs
[regno
] = 0;
356 /* If this reg is used and not call-used (except RA), save it. */
357 if (cr16_interrupt_function_p ())
359 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
360 /* This is a volatile reg in a non-leaf interrupt routine - save
361 it for the sake of its sons. */
362 current_frame_info
.save_regs
[regno
] = 1;
363 else if (df_regs_ever_live_p (regno
))
364 /* This reg is used - save it. */
365 current_frame_info
.save_regs
[regno
] = 1;
367 /* This reg is not used, and is not a volatile - don't save. */
368 current_frame_info
.save_regs
[regno
] = 0;
372 /* If this reg is used and not call-used (except RA), save it. */
373 if (df_regs_ever_live_p (regno
)
374 && (!call_used_regs
[regno
] || regno
== RETURN_ADDRESS_REGNUM
))
375 current_frame_info
.save_regs
[regno
] = 1;
377 current_frame_info
.save_regs
[regno
] = 0;
381 /* Save registers so the exception handler can modify them. */
382 if (crtl
->calls_eh_return
)
388 regno
= EH_RETURN_DATA_REGNO (i
);
389 if (INVALID_REGNUM
== regno
)
391 current_frame_info
.save_regs
[regno
] = 1;
395 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
396 if (current_frame_info
.save_regs
[regno
] == 1)
398 current_frame_info
.last_reg_to_save
= regno
;
399 if (regno
>= CR16_FIRST_DWORD_REGISTER
)
400 current_frame_info
.reg_size
+= CR16_UNITS_PER_DWORD
;
402 current_frame_info
.reg_size
+= UNITS_PER_WORD
;
406 /* Compute the size of the local area and the size to be adjusted by the
407 prologue and epilogue. */
409 cr16_compute_frame (void)
411 /* For aligning the local variables. */
412 int stack_alignment
= STACK_BOUNDARY
/ BITS_PER_UNIT
;
415 /* Padding needed for each element of the frame. */
416 current_frame_info
.var_size
= get_frame_size ();
418 /* Align to the stack alignment. */
419 padding_locals
= current_frame_info
.var_size
% stack_alignment
;
421 padding_locals
= stack_alignment
- padding_locals
;
423 current_frame_info
.var_size
+= padding_locals
;
424 current_frame_info
.total_size
= current_frame_info
.var_size
425 + (ACCUMULATE_OUTGOING_ARGS
426 ? crtl
->outgoing_args_size
: 0);
429 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
431 cr16_initial_elimination_offset (int from
, int to
)
433 /* Compute this since we need to use current_frame_info.reg_size. */
434 cr16_compute_save_regs ();
436 /* Compute this since we need to use current_frame_info.var_size. */
437 cr16_compute_frame ();
439 if (((from
) == FRAME_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
440 return (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0);
441 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == FRAME_POINTER_REGNUM
))
442 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
);
443 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
444 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
445 + (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0));
450 /* Register Usage. */
452 /* Return the class number of the smallest class containing reg number REGNO.
453 This could be a conditional expression or could index an array. */
455 cr16_regno_reg_class (int regno
)
457 if ((regno
>= 0) && (regno
< CR16_FIRST_DWORD_REGISTER
))
460 if ((regno
>= CR16_FIRST_DWORD_REGISTER
) && (regno
< FIRST_PSEUDO_REGISTER
))
466 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
468 cr16_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
470 if ((GET_MODE_SIZE (mode
) >= 4) && (regno
== 11))
473 if (mode
== DImode
|| mode
== DFmode
)
475 if ((regno
> 8) || (regno
& 1))
481 && ((regno
>= 12) && (GET_MODE_SIZE (mode
) < 4 )))
484 /* CC can only hold CCmode values. */
485 if (GET_MODE_CLASS (mode
) == MODE_CC
)
490 /* Returns register number for function return value.*/
491 static inline unsigned int
492 cr16_ret_register (void)
497 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
499 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED
,
500 int incoming ATTRIBUTE_UNUSED
)
502 return gen_rtx_REG (Pmode
, cr16_ret_register ());
505 /* Returning function value. */
507 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
509 cr16_function_value_regno_p (const unsigned int regno
)
511 return (regno
== cr16_ret_register ());
514 /* Create an RTX representing the place where a
515 library function returns a value of mode MODE. */
517 cr16_libcall_value (enum machine_mode mode
,
518 const_rtx func ATTRIBUTE_UNUSED
)
520 return gen_rtx_REG (mode
, cr16_ret_register ());
523 /* Create an RTX representing the place where a
524 function returns a value of data type VALTYPE. */
526 cr16_function_value (const_tree type
,
527 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
528 bool outgoing ATTRIBUTE_UNUSED
)
530 return gen_rtx_REG (TYPE_MODE (type
), cr16_ret_register ());
533 /* Passing function arguments. */
535 /* If enough param regs are available for passing the param of type TYPE return
536 the number of registers needed else 0. */
538 enough_regs_for_param (CUMULATIVE_ARGS
* cum
, const_tree type
,
539 enum machine_mode mode
)
545 type_size
= GET_MODE_BITSIZE (mode
);
547 type_size
= int_size_in_bytes (type
) * BITS_PER_UNIT
;
549 remaining_size
= BITS_PER_WORD
* (MAX_REG_FOR_PASSING_ARGS
550 - (MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) +
553 /* Any variable which is too big to pass in two registers, will pass on
555 if ((remaining_size
>= type_size
) && (type_size
<= 2 * BITS_PER_WORD
))
556 return (type_size
+ BITS_PER_WORD
- 1) / BITS_PER_WORD
;
561 /* Implements the macro FUNCTION_ARG defined in cr16.h. */
563 cr16_function_arg (cumulative_args_t cum_v
, enum machine_mode mode
,
564 const_tree type
, bool named ATTRIBUTE_UNUSED
)
566 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
567 cum
->last_parm_in_reg
= 0;
569 /* function_arg () is called with this type just after all the args have
570 had their registers assigned. The rtx that function_arg returns from
571 this type is supposed to pass to 'gen_call' but currently it is not
572 implemented (see macro GEN_CALL). */
573 if (type
== void_type_node
)
576 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
581 /* Enable structures that need padding bytes at the end to pass to a
582 function in registers. */
583 if (enough_regs_for_param (cum
, type
, mode
) != 0)
585 cum
->last_parm_in_reg
= 1;
586 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
590 if ((MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) > MAX_REG_FOR_PASSING_ARGS
)
594 if (enough_regs_for_param (cum
, type
, mode
) != 0)
596 cum
->last_parm_in_reg
= 1;
597 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
604 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
606 cr16_init_cumulative_args (CUMULATIVE_ARGS
* cum
, tree fntype
,
607 rtx libfunc ATTRIBUTE_UNUSED
)
609 tree param
, next_param
;
613 /* Determine if this function has variable arguments. This is indicated by
614 the last argument being 'void_type_mode' if there are no variable
615 arguments. Change here for a different vararg. */
616 for (param
= (fntype
) ? TYPE_ARG_TYPES (fntype
) : 0;
617 param
!= NULL_TREE
; param
= next_param
)
619 next_param
= TREE_CHAIN (param
);
620 if ((next_param
== NULL_TREE
) && (TREE_VALUE (param
) != void_type_node
))
628 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
630 cr16_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
,
631 const_tree type
, bool named ATTRIBUTE_UNUSED
)
633 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
635 /* l holds the number of registers required. */
636 int l
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
638 /* If the parameter isn't passed on a register don't advance cum. */
639 if (!cum
->last_parm_in_reg
)
642 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
645 if ((mode
== SImode
) || (mode
== HImode
)
646 || (mode
== QImode
) || (mode
== DImode
))
653 else if ((mode
== SFmode
) || (mode
== DFmode
))
655 else if ((mode
) == BLKmode
)
657 if ((l
= enough_regs_for_param (cum
, type
, mode
)) != 0)
663 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
664 Return nonzero if N is a register used for passing parameters. */
666 cr16_function_arg_regno_p (int n
)
668 return ((n
<= MAX_REG_FOR_PASSING_ARGS
) && (n
>= MIN_REG_FOR_PASSING_ARGS
));
672 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
673 defined in cr16.h. */
675 /* Helper function to check if is a valid base register that can
678 cr16_addr_reg_p (rtx addr_reg
)
682 if (REG_P (addr_reg
))
684 else if ((GET_CODE (addr_reg
) == SUBREG
)
685 && REG_P (SUBREG_REG (addr_reg
))
686 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg
)))
688 reg
= SUBREG_REG (addr_reg
);
692 if (GET_MODE (reg
) != Pmode
)
698 /* Helper functions: Created specifically for decomposing operand of CONST
699 Recursively look into expression x for code or data symbol.
700 The function expects the expression to contain combination of
701 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
702 LABEL_REF, CONST_INT, (PLUS or MINUS)
705 All other combinations will result in code = -1 and data = ILLEGAL_DM
707 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
708 0 DM_FAR SYMBOL_REF was found and it was far data reference.
709 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
710 1 ILLEGAL_DM LABEL_REF was found.
711 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
713 cr16_decompose_const (rtx x
, int *code
, enum data_model_type
*data
,
718 switch (GET_CODE (x
))
721 *code
= SYMBOL_REF_FUNCTION_P (x
) ? 2 : 0;
722 /* 2 indicates func sym. */
725 if (CR16_TARGET_DATA_NEAR
)
727 else if (CR16_TARGET_DATA_MEDIUM
)
729 else if (CR16_TARGET_DATA_FAR
)
732 /* This will be used only for printing
733 the qualifier. This call is (may be)
734 made by cr16_print_operand_address. */
737 /* This call is (may be) made by
738 cr16_legitimate_address_p. */
745 /* 1 - indicates non-function symbol. */
751 /* Look into the tree nodes. */
752 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
753 cr16_decompose_const (XEXP (x
, 1), code
, data
, treat_as_const
);
754 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
755 cr16_decompose_const (XEXP (x
, 0), code
, data
, treat_as_const
);
763 This function decomposes the address returns the type of address
764 as defined in enum cr16_addrtype. It also fills the parameter *out.
765 The decomposed address can be used for two purposes. One to
766 check if the address is valid and second to print the address
769 Following tables list valid address supported in CR16C/C+ architectures.
771 aN : Absoulte address N-bit address
772 R : One 16-bit register
773 RP : Consecutive two 16-bit registers or one 32-bit register
774 I : One 32-bit register
775 dispN : Signed displacement of N-bits
777 ----Code addresses----
779 disp9 : CR16_ABSOLUTE (disp)
780 disp17 : CR16_ABSOLUTE (disp)
781 disp25 : CR16_ABSOLUTE (disp)
782 RP + disp25 : CR16_REGP_REL (base, disp)
785 RP : CR16_REGP_REL (base, disp=0)
786 a24 : CR16_ABSOLUTE (disp)
788 ----Data addresses----
789 a20 : CR16_ABSOLUTE (disp) near (1M)
790 a24 : CR16_ABSOLUTE (disp) medium (16M)
791 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
792 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
793 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
794 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
795 I : *** Valid but port does not support this
796 I + a20 : *** Valid but port does not support this
797 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
798 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
800 Decomposing Data model in case of absolute address.
802 Target Option Address type Resultant Data ref type
803 ---------------------- ------------ -----------------------
804 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
805 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
806 CR16_TARGET_MODEL_NEAR ABS24 Invalid
807 CR16_TARGET_MODEL_NEAR IMM32 Invalid
809 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
810 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
811 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
812 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
814 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
815 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
816 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
817 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
819 cr16_decompose_address (rtx addr
, struct cr16_address
*out
,
820 bool debug_print
, bool treat_as_const
)
822 rtx base
= NULL_RTX
, disp
= NULL_RTX
, index
= NULL_RTX
;
823 enum data_model_type data
= ILLEGAL_DM
;
825 enum cr16_addrtype retval
= CR16_INVALID
;
827 switch (GET_CODE (addr
))
830 /* Absolute address (known at compile time). */
833 fprintf (stderr
, "\ncode:%d", code
);
838 fprintf (stderr
, "\ndisp:");
842 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
846 fprintf (stderr
, "\ndata:%d", data
);
847 retval
= CR16_ABSOLUTE
;
849 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 24))
851 if (!CR16_TARGET_DATA_NEAR
)
855 fprintf (stderr
, "\ndata:%d", data
);
856 retval
= CR16_ABSOLUTE
;
859 return CR16_INVALID
; /* ABS24 is not support in NEAR model. */
866 /* A CONST is an expression of PLUS or MINUS with
867 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
868 result of assembly-time arithmetic computation. */
869 retval
= CR16_ABSOLUTE
;
871 /* Call the helper function to check the validity. */
872 cr16_decompose_const (XEXP (addr
, 0), &code
, &data
, treat_as_const
);
873 if ((code
== 0) && (data
== ILLEGAL_DM
))
874 /* CONST is not valid code or data address. */
878 fprintf (stderr
, "\ndisp:");
880 fprintf (stderr
, "\ncode:%d", code
);
881 fprintf (stderr
, "\ndata:%d", data
);
886 retval
= CR16_ABSOLUTE
;
888 /* 1 - indicates non-function symbol. */
892 fprintf (stderr
, "\ndisp:");
894 fprintf (stderr
, "\ncode:%d", code
);
899 /* Absolute address (known at link time). */
900 retval
= CR16_ABSOLUTE
;
902 /* This is a code address if symbol_ref is a function. */
903 /* 2 indicates func sym. */
904 code
= SYMBOL_REF_FUNCTION_P (addr
) ? 2 : 0;
907 fprintf (stderr
, "\ndisp:");
909 fprintf (stderr
, "\ncode:%d", code
);
911 /* If not function ref then check if valid data ref. */
914 if (CR16_TARGET_DATA_NEAR
)
916 else if (CR16_TARGET_DATA_MEDIUM
)
918 else if (CR16_TARGET_DATA_FAR
)
921 /* This will be used only for printing the
922 qualifier. This call is (may be) made
923 by cr16_print_operand_address. */
926 /* This call is (may be) made by
927 cr16_legitimate_address_p. */
934 fprintf (stderr
, "\ndata:%d", data
);
939 /* Register relative address. */
940 /* Assume REG fits in a single register. */
941 retval
= CR16_REG_REL
;
942 if (GET_MODE_BITSIZE (GET_MODE (addr
)) > BITS_PER_WORD
)
943 if (!LONG_REG_P (REGNO (addr
)))
944 /* REG will result in reg pair. */
945 retval
= CR16_REGP_REL
;
949 fprintf (stderr
, "\nbase:");
955 switch (GET_CODE (XEXP (addr
, 0)))
960 /* All Reg relative addresses having a displacement needs
961 to fit in 20-bits. */
962 disp
= XEXP (addr
, 1);
965 fprintf (stderr
, "\ndisp:");
968 switch (GET_CODE (XEXP (addr
, 1)))
971 /* Shall fit in 20-bits. */
972 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
976 fprintf (stderr
, "\ncode:%d", code
);
980 switch (XINT (XEXP (addr
, 1), 1))
982 case UNSPEC_LIBRARY_OFFSET
:
991 /* This is also a valid expression for address.
992 However, we cannot ascertain if the resultant
993 displacement will be valid 20-bit value. Therefore,
994 lets not allow such an expression for now. This will
995 be updated when we find a way to validate this
996 expression as legitimate address.
997 Till then fall through CR16_INVALID. */
1002 /* Now check if REG can fit into single or pair regs. */
1003 retval
= CR16_REG_REL
;
1004 base
= XEXP (addr
, 0);
1007 fprintf (stderr
, "\nbase:");
1010 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr
, 0)))) > BITS_PER_WORD
)
1012 if (!LONG_REG_P (REGNO ((XEXP (addr
, 0)))))
1013 /* REG will result in reg pair. */
1014 retval
= CR16_REGP_REL
;
1028 Check if the operand 1 is valid index register. */
1031 fprintf (stderr
, "\ndata:%d", data
);
1032 switch (GET_CODE (XEXP (addr
, 1)))
1036 if (!REG_OK_FOR_INDEX_P (XEXP (addr
, 1)))
1037 return CR16_INVALID
;
1038 /* OK. REG is a valid index register. */
1039 index
= XEXP (addr
, 1);
1042 fprintf (stderr
, "\nindex:");
1047 return CR16_INVALID
;
1049 /* Check if operand 0 of operand 0 is REGP. */
1050 switch (GET_CODE (XEXP (XEXP (addr
, 0), 0)))
1054 /* Now check if REG is a REGP and not in LONG regs. */
1055 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr
, 0), 0)))
1058 if (REGNO (XEXP (XEXP (addr
, 0), 0))
1059 >= CR16_FIRST_DWORD_REGISTER
)
1060 return CR16_INVALID
;
1061 base
= XEXP (XEXP (addr
, 0), 0);
1064 fprintf (stderr
, "\nbase:");
1069 return CR16_INVALID
;
1072 return CR16_INVALID
;
1074 /* Now check if the operand 1 of operand 0 is const_int. */
1075 if (GET_CODE (XEXP (XEXP (addr
, 0), 1)) == CONST_INT
)
1077 disp
= XEXP (XEXP (addr
, 0), 1);
1080 fprintf (stderr
, "\ndisp:");
1083 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
1084 return CR16_INVALID
;
1087 return CR16_INVALID
;
1088 retval
= CR16_INDEX_REGP_REL
;
1091 return CR16_INVALID
;
1096 return CR16_INVALID
;
1099 /* Check if the base and index registers are valid. */
1100 if (base
&& !(cr16_addr_reg_p (base
)))
1101 return CR16_INVALID
;
1102 if (base
&& !(CR16_REG_OK_FOR_BASE_P (base
)))
1103 return CR16_INVALID
;
1104 if (index
&& !(REG_OK_FOR_INDEX_P (index
)))
1105 return CR16_INVALID
;
1107 /* Write the decomposition to out parameter. */
1117 /* Return non-zero value if 'x' is legitimate PIC operand
1118 when generating PIC code. */
1120 legitimate_pic_operand_p (rtx x
)
1122 switch (GET_CODE (x
))
1131 /* REVISIT: Use something like symbol_referenced_p. */
1132 if (GET_CODE (XEXP (x
, 0)) == PLUS
1133 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
1134 || GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
)
1135 && (GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
))
1139 return legitimate_pic_operand_p (XEXP (x
, 0));
1147 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
1149 Input Output (-f pic) Output (-f PIC)
1152 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
1154 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
1156 NOTE: @BRO is added using unspec:BRO
1157 NOTE: @GOT is added using unspec:GOT. */
1159 legitimize_pic_address (rtx orig
, enum machine_mode mode ATTRIBUTE_UNUSED
,
1162 /* First handle a simple SYMBOL_REF or LABEL_REF. */
1163 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1166 reg
= gen_reg_rtx (Pmode
);
1168 if (flag_pic
== NEAR_PIC
)
1170 /* Unspec to handle -fpic option. */
1171 emit_insn (gen_unspec_bro_addr (reg
, orig
));
1172 emit_insn (gen_addsi3 (reg
, reg
, pic_offset_table_rtx
));
1174 else if (flag_pic
== FAR_PIC
)
1176 /* Unspec to handle -fPIC option. */
1177 emit_insn (gen_unspec_got_addr (reg
, orig
));
1181 else if (GET_CODE (orig
) == CONST
)
1183 /* To handle (symbol + offset). */
1186 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1187 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1192 gcc_assert (can_create_pseudo_p ());
1193 reg
= gen_reg_rtx (Pmode
);
1196 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
1198 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1199 offset
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1200 base
== reg
? 0 : reg
);
1202 /* REVISIT: Optimize for const-offsets. */
1203 emit_insn (gen_addsi3 (reg
, base
, offset
));
1210 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
1212 cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
1213 rtx addr
, bool strict
)
1215 enum cr16_addrtype addrtype
;
1216 struct cr16_address address
;
1218 if (TARGET_DEBUG_ADDR
)
1221 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
1222 GET_MODE_NAME (mode
), strict
);
1225 addrtype
= cr16_decompose_address (addr
, &address
,
1226 (TARGET_DEBUG_ADDR
? 1 : 0), FALSE
);
1228 if (TARGET_DEBUG_ADDR
)
1230 const char *typestr
;
1235 typestr
= "invalid";
1238 typestr
= "absolute";
1241 typestr
= "register relative";
1244 typestr
= "register pair relative";
1246 case CR16_INDEX_REGP_REL
:
1247 typestr
= "index + register pair relative";
1252 fprintf (stderr
, "\ncr16 address type: %s\n", typestr
);
1255 if (addrtype
== CR16_INVALID
)
1261 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address
.base
), mode
))
1263 if (TARGET_DEBUG_ADDR
)
1264 fprintf (stderr
, "base register not strict\n");
1267 if (address
.index
&& !REGNO_OK_FOR_INDEX_P (REGNO (address
.index
)))
1269 if (TARGET_DEBUG_ADDR
)
1270 fprintf (stderr
, "index register not strict\n");
1275 /* Return true if addressing mode is register relative. */
1278 if (addrtype
== CR16_REG_REL
|| addrtype
== CR16_REGP_REL
)
1287 /* Routines to compute costs. */
1289 /* Return cost of the memory address x. */
1291 cr16_address_cost (rtx addr
, enum machine_mode mode ATTRIBUTE_UNUSED
,
1292 addr_space_t as ATTRIBUTE_UNUSED
,
1293 bool speed ATTRIBUTE_UNUSED
)
1295 enum cr16_addrtype addrtype
;
1296 struct cr16_address address
;
1299 addrtype
= cr16_decompose_address (addr
, &address
, 0, FALSE
);
1301 gcc_assert (addrtype
!= CR16_INVALID
);
1303 /* CR16_ABSOLUTE : 3
1304 CR16_REG_REL (disp !=0) : 4
1305 CR16_REG_REL (disp ==0) : 5
1306 CR16_REGP_REL (disp !=0) : 6
1307 CR16_REGP_REL (disp ==0) : 7
1308 CR16_INDEX_REGP_REL (disp !=0) : 8
1309 CR16_INDEX_REGP_REL (disp ==0) : 9. */
1323 case CR16_INDEX_REGP_REL
:
1331 if (TARGET_DEBUG_ADDR
)
1333 fprintf (stderr
, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost
);
1341 /* Implement `TARGET_REGISTER_MOVE_COST'. */
1343 cr16_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
1344 reg_class_t from ATTRIBUTE_UNUSED
, reg_class_t to
)
1346 return (to
!= GENERAL_REGS
? 8 : 2);
1349 /* Implement `TARGET_MEMORY_MOVE_COST'. */
1351 /* Return the cost of moving data of mode MODE between a register of class
1352 CLASS and memory; IN is zero if the value is to be written to memory,
1353 nonzero if it is to be read in. This cost is relative to those in
1354 REGISTER_MOVE_COST. */
1356 cr16_memory_move_cost (enum machine_mode mode
,
1357 reg_class_t rclass ATTRIBUTE_UNUSED
,
1358 bool in ATTRIBUTE_UNUSED
)
1360 /* One LD or ST takes twice the time of a simple reg-reg move. */
1361 if (reg_classes_intersect_p (rclass
, GENERAL_REGS
))
1362 return (4 * HARD_REGNO_NREGS (0, mode
));
1367 /* Instruction output. */
1369 /* Check if a const_double is ok for cr16 store-immediate instructions. */
1371 cr16_const_double_ok (rtx op
)
1373 if (GET_MODE (op
) == SFmode
)
1377 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1378 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1379 return UNSIGNED_INT_FITS_N_BITS (l
, 4) ? 1 : 0;
1382 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op
), 4)) &&
1383 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op
), 4))) ? 1 : 0;
1386 /* Returns bit position of first 0 or 1 bit.
1387 It is safe to assume val as 16-bit wide. */
1389 cr16_operand_bit_pos (int val
, int bitval
)
1395 for (i
= 0; i
< 16; i
++)
1401 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
1403 cr16_print_operand (FILE * file
, rtx x
, int code
)
1405 int ptr_dereference
= 0;
1411 const char *cr16_cmp_str
;
1412 switch (GET_CODE (x
))
1414 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
1415 -> swap all non symmetric ops. */
1417 cr16_cmp_str
= "eq";
1420 cr16_cmp_str
= "ne";
1423 cr16_cmp_str
= "lt";
1426 cr16_cmp_str
= "lo";
1429 cr16_cmp_str
= "gt";
1432 cr16_cmp_str
= "hi";
1435 cr16_cmp_str
= "le";
1438 cr16_cmp_str
= "ls";
1441 cr16_cmp_str
= "ge";
1444 cr16_cmp_str
= "hs";
1449 fprintf (file
, "%s", cr16_cmp_str
);
1457 if (GET_CODE (x
) == REG
)
1459 /* For Push instructions, we should not print register pairs. */
1460 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1466 /* Print the immediate address for bal
1467 'b' is used instead of 'a' to avoid compiler calling
1468 the GO_IF_LEGITIMATE_ADDRESS which cannot
1469 perform checks on const_int code addresses as it
1470 assumes all const_int are data addresses. */
1471 fprintf (file
, "0x%lx", INTVAL (x
));
1475 /* Print bit position of first 0. */
1476 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 0));
1480 /* Print bit position of first 1. */
1481 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 1));
1484 /* 'g' is used for implicit mem: dereference. */
1485 ptr_dereference
= 1;
1489 switch (GET_CODE (x
))
1492 if (GET_MODE_BITSIZE (GET_MODE (x
)) > BITS_PER_WORD
)
1494 if (LONG_REG_P (REGNO (x
)))
1495 fprintf (file
, "(%s)", reg_names
[REGNO (x
)]);
1497 fprintf (file
, "(%s,%s)", reg_names
[REGNO (x
) + 1],
1498 reg_names
[REGNO (x
)]);
1501 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1505 output_address (XEXP (x
, 0));
1513 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1514 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1516 fprintf (file
, "$0x%lx", l
);
1521 fprintf (file
, "$%ld", INTVAL (x
));
1525 switch (XINT (x
, 1))
1533 if (!ptr_dereference
)
1537 cr16_print_operand_address (file
, x
);
1541 output_operand_lossage ("invalid %%xn code");
1547 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
1550 cr16_print_operand_address (FILE * file
, rtx addr
)
1552 enum cr16_addrtype addrtype
;
1553 struct cr16_address address
;
1555 /* Decompose the address. Also ask it to treat address as constant. */
1556 addrtype
= cr16_decompose_address (addr
, &address
, 0, TRUE
);
1558 if (address
.disp
&& GET_CODE (address
.disp
) == UNSPEC
)
1568 if (GET_CODE (address
.disp
) == UNSPEC
)
1569 cr16_print_operand (file
, address
.disp
, 0);
1571 output_addr_const (file
, address
.disp
);
1574 fprintf (file
, "0");
1575 fprintf (file
, "(%s)", reg_names
[REGNO (address
.base
)]);
1580 output_addr_const (file
, address
.disp
);
1582 fprintf (file
, "0");
1585 case CR16_INDEX_REGP_REL
:
1586 fprintf (file
, "[%s]", reg_names
[REGNO (address
.index
)]);
1591 if (GET_CODE (address
.disp
) == UNSPEC
)
1592 cr16_print_operand (file
, address
.disp
, 0);
1594 output_addr_const (file
, address
.disp
);
1597 fprintf (file
, "0");
1598 fprintf (file
, "(%s,%s)", reg_names
[REGNO (address
.base
) + 1],
1599 reg_names
[REGNO (address
.base
)]);
1605 /* Add qualifiers to the address expression that was just printed. */
1606 if (flag_pic
< NEAR_PIC
&& address
.code
== 0)
1608 if (address
.data
== DM_FAR
)
1609 /* Addr contains SYMBOL_REF & far data ptr. */
1610 fprintf (file
, "@l");
1611 else if (address
.data
== DM_DEFAULT
)
1612 /* Addr contains SYMBOL_REF & medium data ptr. */
1613 fprintf (file
, "@m");
1614 /* Addr contains SYMBOL_REF & medium data ptr. */
1615 else if (address
.data
== DM_NEAR
)
1616 /* Addr contains SYMBOL_REF & near data ptr. */
1617 fprintf (file
, "@s");
1619 else if (flag_pic
== NEAR_PIC
1620 && (address
.code
== 0) && (address
.data
== DM_FAR
1621 || address
.data
== DM_DEFAULT
1622 || address
.data
== DM_NEAR
))
1624 fprintf (file
, "@l");
1626 else if (flag_pic
== NEAR_PIC
&& address
.code
== 2)
1628 fprintf (file
, "pic");
1630 else if (flag_pic
== NEAR_PIC
&& address
.code
== 1)
1632 fprintf (file
, "@cpic");
1635 else if (flag_pic
== FAR_PIC
&& address
.code
== 2)
1637 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
1638 address ! GOTc tells assembler this symbol is a text-address
1639 This needs to be fixed in such a way that this offset is done
1640 only in the case where an address is being used for indirect jump
1641 or call. Determining the potential usage of loadd is of course not
1642 possible always. Eventually, this has to be fixed in the
1644 fprintf (file
, "GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1646 else if (flag_pic
== FAR_PIC
&& address
.code
== 1)
1648 fprintf (file
, "@cGOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1651 else if (flag_pic
== FAR_PIC
&&
1652 (address
.data
== DM_FAR
|| address
.data
== DM_DEFAULT
1653 || address
.data
== DM_NEAR
))
1655 fprintf (file
, "@GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1659 /* Machine description helper functions. */
1661 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
1662 When push_or_pop is zero -> string for push instructions of prologue.
1663 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1664 Relies on the assumptions:
1665 1. RA is the last register to be saved.
1666 2. The maximal value of the counter is MAX_COUNT. */
1668 cr16_prepare_push_pop_string (int push_or_pop
)
1670 /* j is the number of registers being saved, takes care that there won't be
1671 more than 8 in one push/pop instruction. */
1673 /* For the register mask string. */
1674 static char one_inst_str
[50];
1676 /* i is the index of current_frame_info.save_regs[], going from 0 until
1677 current_frame_info.last_reg_to_save. */
1683 /* For reversing on the push instructions if there are more than one. */
1686 return_str
= (char *) xmalloc (160);
1687 temp_str
= (char *) xmalloc (160);
1690 memset (return_str
, 0, 3);
1693 while (i
<= current_frame_info
.last_reg_to_save
)
1695 /* Prepare mask for one instruction. */
1696 one_inst_str
[0] = 0;
1698 /* To count number of words in one instruction. */
1702 while ((word_cnt
< MAX_COUNT
)
1703 && (i
<= current_frame_info
.last_reg_to_save
))
1705 /* For each non consecutive save register,
1706 a new instruction shall be generated. */
1707 if (!current_frame_info
.save_regs
[i
])
1709 /* Move to next reg and break. */
1714 if (i
== RETURN_ADDRESS_REGNUM
)
1718 /* Check especially if adding 2 does not cross the MAX_COUNT. */
1719 if ((word_cnt
+ ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2))
1722 /* Increase word count by 2 for long registers except RA. */
1723 word_cnt
+= ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2);
1728 /* No need to generate any instruction as
1729 no register or RA needs to be saved. */
1730 if ((word_cnt
== 0) && (print_ra
== 0))
1733 /* Now prepare the instruction operands. */
1736 sprintf (one_inst_str
, "$%d, %s", word_cnt
, reg_names
[start_reg
]);
1738 strcat (one_inst_str
, ", ra");
1741 strcat (one_inst_str
, "ra");
1743 if (push_or_pop
== 1)
1745 /* Pop instruction. */
1746 if (print_ra
&& !cr16_interrupt_function_p ()
1747 && !crtl
->calls_eh_return
)
1748 /* Print popret if RA is saved and its not a interrupt
1750 strcpy (temp_str
, "\n\tpopret\t");
1752 strcpy (temp_str
, "\n\tpop\t");
1754 strcat (temp_str
, one_inst_str
);
1756 /* Add the pop instruction list. */
1757 strcat (return_str
, temp_str
);
1761 /* Push instruction. */
1762 strcpy (temp_str
, "\n\tpush\t");
1763 strcat (temp_str
, one_inst_str
);
1765 /* We need to reverse the order of the instructions if there
1766 are more than one. (since the pop will not be reversed in
1768 strcat (temp_str
, return_str
);
1769 strcpy (return_str
, temp_str
);
1773 if (push_or_pop
== 1)
1776 if (cr16_interrupt_function_p ())
1777 strcat (return_str
, "\n\tretx\n");
1778 else if (crtl
->calls_eh_return
)
1780 /* Add stack adjustment before returning to exception handler
1781 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
1782 strcat (return_str
, "\n\taddd\t (r5, r4), (sp)\t\n");
1783 strcat (return_str
, "\n\tjump\t (ra)\n");
1785 /* But before anything else, undo the adjustment addition done in
1786 cr16_expand_epilogue (). */
1787 strcpy (temp_str
, "\n\tsubd\t (r5, r4), (sp)\t\n");
1788 strcat (temp_str
, return_str
);
1789 strcpy (return_str
, temp_str
);
1791 else if (!FUNC_IS_NORETURN_P (current_function_decl
)
1792 && !(current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]))
1793 strcat (return_str
, "\n\tjump\t (ra)\n");
1796 /* Skip the newline and the tab in the start of return_str. */
1802 /* Generate DWARF2 annotation for multi-push instruction. */
1804 cr16_create_dwarf_for_multi_push (rtx insn
)
1806 rtx dwarf
, reg
, tmp
;
1807 int i
, j
, from
, to
, word_cnt
, dwarf_par_index
, inc
;
1808 enum machine_mode mode
;
1809 int num_regs
= 0, offset
= 0, split_here
= 0, total_push_bytes
= 0;
1811 for (i
= 0; i
<= current_frame_info
.last_reg_to_save
; ++i
)
1813 if (current_frame_info
.save_regs
[i
])
1816 if (i
< CR16_FIRST_DWORD_REGISTER
)
1817 total_push_bytes
+= 2;
1819 total_push_bytes
+= 4;
1826 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (num_regs
+ 1));
1827 dwarf_par_index
= num_regs
;
1829 from
= current_frame_info
.last_reg_to_save
+ 1;
1830 to
= current_frame_info
.last_reg_to_save
;
1833 for (i
= current_frame_info
.last_reg_to_save
; i
>= 0;)
1835 if (!current_frame_info
.save_regs
[i
] || 0 == i
|| split_here
)
1837 /* This block of regs is pushed in one instruction. */
1838 if (0 == i
&& current_frame_info
.save_regs
[i
])
1841 for (j
= to
; j
>= from
; --j
)
1843 if (j
< CR16_FIRST_DWORD_REGISTER
)
1853 reg
= gen_rtx_REG (mode
, j
);
1855 tmp
= gen_rtx_SET (VOIDmode
,
1856 gen_frame_mem (mode
,
1858 (Pmode
, stack_pointer_rtx
,
1859 total_push_bytes
- offset
)),
1861 RTX_FRAME_RELATED_P (tmp
) = 1;
1862 XVECEXP (dwarf
, 0, dwarf_par_index
--) = tmp
;
1871 if (i
!= RETURN_ADDRESS_REGNUM
)
1873 inc
= (i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2;
1874 if (word_cnt
+ inc
>= MAX_COUNT
|| FRAME_POINTER_REGNUM
== i
)
1886 tmp
= gen_rtx_SET (SImode
, stack_pointer_rtx
,
1887 gen_rtx_PLUS (SImode
, stack_pointer_rtx
,
1888 GEN_INT (-offset
)));
1889 RTX_FRAME_RELATED_P (tmp
) = 1;
1890 XVECEXP (dwarf
, 0, 0) = tmp
;
1892 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, dwarf
);
1896 CompactRISC CR16 Architecture stack layout:
1898 0 +---------------------
1903 +==================== Sp (x) = Ap (x+1)
1904 A | Args for functions
1905 | | called by X and Dynamically
1906 | | Dynamic allocations allocated and
1907 | | (alloca, variable deallocated
1908 Stack | length arrays).
1909 grows +-------------------- Fp (x)
1910 down| | Local variables of X
1911 ward| +--------------------
1912 | | Regs saved for X-1
1913 | +==================== Sp (x-1) = Ap (x)
1916 +-------------------- Fp (x-1)
1922 cr16_expand_prologue (void)
1926 cr16_compute_frame ();
1927 cr16_compute_save_regs ();
1929 /* If there is no need in push and adjustment to sp, return. */
1930 if ((current_frame_info
.total_size
+ current_frame_info
.reg_size
) == 0)
1933 if (current_frame_info
.last_reg_to_save
!= -1)
1935 /* If there are registers to push. */
1936 insn
= emit_insn (gen_push_for_prologue
1937 (GEN_INT (current_frame_info
.reg_size
)));
1938 cr16_create_dwarf_for_multi_push (insn
);
1939 RTX_FRAME_RELATED_P (insn
) = 1;
1943 if (current_frame_info
.total_size
> 0)
1945 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1946 GEN_INT (-current_frame_info
.total_size
)));
1947 RTX_FRAME_RELATED_P (insn
) = 1;
1950 if (frame_pointer_needed
)
1952 /* Initialize the frame pointer with the value of the stack pointer
1953 pointing now to the locals. */
1954 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1958 /* Generate insn that updates the stack for local variables and padding
1959 for registers we save. - Generate the appropriate return insn. */
1961 cr16_expand_epilogue (void)
1965 /* Nonzero if we need to return and pop only RA. This will generate a
1966 different insn. This differentiate is for the peepholes for call as
1967 last statement in function. */
1968 int only_popret_RA
= (current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]
1969 && (current_frame_info
.reg_size
1970 == CR16_UNITS_PER_DWORD
));
1972 if (frame_pointer_needed
)
1974 /* Restore the stack pointer with the frame pointers value. */
1975 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
1978 if (current_frame_info
.total_size
> 0)
1980 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1981 GEN_INT (current_frame_info
.total_size
)));
1982 RTX_FRAME_RELATED_P (insn
) = 1;
1985 if (crtl
->calls_eh_return
)
1987 /* Add this here so that (r5, r4) is actually loaded with the adjustment
1988 value; otherwise, the load might be optimized away...
1989 NOTE: remember to subtract the adjustment before popping the regs
1990 and add it back before returning. */
1991 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1992 EH_RETURN_STACKADJ_RTX
));
1995 if (cr16_interrupt_function_p ())
1997 insn
= emit_jump_insn (gen_interrupt_return ());
1998 RTX_FRAME_RELATED_P (insn
) = 1;
2000 else if (crtl
->calls_eh_return
)
2002 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
2003 insn
= emit_jump_insn (gen_pop_and_popret_return
2004 (GEN_INT (current_frame_info
.reg_size
)));
2005 RTX_FRAME_RELATED_P (insn
) = 1;
2007 else if (current_frame_info
.last_reg_to_save
== -1)
2008 /* Nothing to pop. */
2009 /* Don't output jump for interrupt routine, only retx. */
2010 emit_jump_insn (gen_jump_return ());
2011 else if (only_popret_RA
)
2013 insn
= emit_jump_insn (gen_popret_RA_return ());
2014 RTX_FRAME_RELATED_P (insn
) = 1;
2018 insn
= emit_jump_insn (gen_pop_and_popret_return
2019 (GEN_INT (current_frame_info
.reg_size
)));
2020 RTX_FRAME_RELATED_P (insn
) = 1;
2024 /* Implements FRAME_POINTER_REQUIRED. */
2026 cr16_frame_pointer_required (void)
2028 return (cfun
->calls_alloca
|| crtl
->calls_eh_return
2029 || cfun
->has_nonlocal_label
|| crtl
->calls_eh_return
);
2033 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
2035 return (to
== STACK_POINTER_REGNUM
? !frame_pointer_needed
: true);
2039 /* A C compound statement that attempts to replace X with
2040 a valid memory address for an operand of mode MODE. WIN
2041 will be a C statement label elsewhere in the code.
2042 X will always be the result of a call to break_out_memory_refs (),
2043 and OLDX will be the operand that was given to that function to
2045 The code generated by this macro should not alter the
2046 substructure of X. If it transforms X into a more legitimate form,
2047 it should assign X (which will always be a C variable) a new value. */
2049 cr16_legitimize_address (rtx x
, rtx orig_x ATTRIBUTE_UNUSED
,
2050 enum machine_mode mode ATTRIBUTE_UNUSED
)
2053 return legitimize_pic_address (orig_x
, mode
, NULL_RTX
);
2058 /* Implement TARGET_LEGITIMATE_CONSTANT_P
2059 Nonzero if X is a legitimate constant for an immediate
2060 operand on the target machine. You can assume that X
2061 satisfies CONSTANT_P. In cr16c treat legitimize float
2062 constant as an immediate operand. */
2064 cr16_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
2065 rtx x ATTRIBUTE_UNUSED
)
2071 notice_update_cc (rtx exp
)
2073 if (GET_CODE (exp
) == SET
)
2075 /* Jumps do not alter the cc's. */
2076 if (SET_DEST (exp
) == pc_rtx
)
2079 /* Moving register or memory into a register:
2080 it doesn't alter the cc's, but it might invalidate
2081 the RTX's which we remember the cc's came from.
2082 (Note that moving a constant 0 or 1 MAY set the cc's). */
2083 if (REG_P (SET_DEST (exp
))
2084 && (REG_P (SET_SRC (exp
)) || GET_CODE (SET_SRC (exp
)) == MEM
))
2089 /* Moving register into memory doesn't alter the cc's.
2090 It may invalidate the RTX's which we remember the cc's came from. */
2091 if (GET_CODE (SET_DEST (exp
)) == MEM
&& REG_P (SET_SRC (exp
)))
2101 static enum machine_mode
2102 cr16_unwind_word_mode (void)
2107 /* Helper function for md file. This function is used to emit arithmetic
2108 DI instructions. The argument "num" decides which instruction to be
2111 cr16_emit_add_sub_di (rtx
*operands
, enum rtx_code code
)
2117 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2118 hi0_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 4);
2119 hi1_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 6);
2121 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2122 hi0_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 4);
2123 hi1_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 6);
2129 output_asm_insn ("addd\t%1, %0", lo_op
) ;
2130 output_asm_insn ("addcw\t%1, %0", hi0_op
) ;
2131 output_asm_insn ("addcw\t%1, %0", hi1_op
) ;
2136 output_asm_insn ("subd\t%1, %0", lo_op
) ;
2137 output_asm_insn ("subcw\t%1, %0", hi0_op
) ;
2138 output_asm_insn ("subcw\t%1, %0", hi1_op
) ;
2149 /* Helper function for md file. This function is used to emit logical
2150 DI instructions. The argument "num" decides which instruction to be
2153 cr16_emit_logical_di (rtx
*operands
, enum rtx_code code
)
2158 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2159 hi_op
[0] = simplify_gen_subreg (SImode
, operands
[0], DImode
, 4);
2161 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2162 hi_op
[1] = simplify_gen_subreg (SImode
, operands
[2], DImode
, 4);
2168 output_asm_insn ("andd\t%1, %0", lo_op
) ;
2169 output_asm_insn ("andd\t%1, %0", hi_op
) ;
2174 output_asm_insn ("ord\t%1, %0", lo_op
) ;
2175 output_asm_insn ("ord\t%1, %0", hi_op
) ;
2180 output_asm_insn ("xord\t%1, %0", lo_op
) ;
2181 output_asm_insn ("xord\t%1, %0", hi_op
) ;
2191 /* Initialize 'targetm' variable which contains pointers to functions
2192 and data relating to the target machine. */
2194 struct gcc_target targetm
= TARGET_INITIALIZER
;