1 /* Output routines for CR16 processor.
2 Copyright (C) 2012-2015 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"
29 #include "fold-const.h"
30 #include "stor-layout.h"
34 #include "hard-reg-set.h"
35 #include "insn-config.h"
36 #include "conditions.h"
38 #include "insn-codes.h"
39 #include "insn-attr.h"
52 #include "diagnostic-core.h"
54 #include "dominance.h"
60 #include "cfgcleanup.h"
61 #include "basic-block.h"
63 #include "target-def.h"
69 /* Maximum number of register used for passing parameters. */
70 #define MAX_REG_FOR_PASSING_ARGS 6
72 /* Minimum number register used for passing parameters. */
73 #define MIN_REG_FOR_PASSING_ARGS 2
75 /* The maximum count of words supported in the assembly of the architecture in
76 a push/pop instruction. */
79 /* Predicate is true if the current function is a 'noreturn' function,
80 i.e. it is qualified as volatile. */
81 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
83 /* Predicate that holds when we need to save registers even for 'noreturn'
84 functions, to accommodate for unwinding. */
85 #define MUST_SAVE_REGS_P() \
86 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
88 /* Nonzero if the rtx X is a signed const int of n bits. */
89 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
90 ((GET_CODE (X) == CONST_INT \
91 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
93 /* Nonzero if the rtx X is an unsigned const int of n bits. */
94 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
95 ((GET_CODE (X) == CONST_INT \
96 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
98 /* Structure for stack computations. */
100 /* variable definitions in the struture
101 args_size Number of bytes saved on the stack for local
104 reg_size Number of bytes saved on the stack for
105 non-scratch registers
107 total_size The sum of 2 sizes: locals vars and padding byte
108 for saving the registers. Used in expand_prologue()
109 and expand_epilogue()
111 last_reg_to_save Will hold the number of the last register the
112 prologue saves, -1 if no register is saved
114 save_regs[16] Each object in the array is a register number.
115 Mark 1 for registers that need to be saved
117 num_regs Number of registers saved
119 initialized Non-zero if frame size already calculated, not
122 function_makes_calls Does the function make calls ? not used yet. */
124 struct cr16_frame_info
126 unsigned long var_size
;
127 unsigned long args_size
;
128 unsigned int reg_size
;
129 unsigned long total_size
;
130 long last_reg_to_save
;
131 long save_regs
[FIRST_PSEUDO_REGISTER
];
134 int function_makes_calls
;
137 /* Current frame information calculated by cr16_compute_frame_size. */
138 static struct cr16_frame_info current_frame_info
;
140 /* Static Variables. */
142 /* Data model that was supplied by user via command line option
143 This will be overridden in case of invalid combination
144 of core and data model options are supplied. */
145 static enum data_model_type data_model
= DM_DEFAULT
;
147 /* TARGETM Function Prototypes and forward declarations */
148 static void cr16_print_operand (FILE *, rtx
, int);
149 static void cr16_print_operand_address (FILE *, rtx
);
151 /* Stack layout and calling conventions. */
152 #undef TARGET_STRUCT_VALUE_RTX
153 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
154 #undef TARGET_RETURN_IN_MEMORY
155 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
157 /* Target-specific uses of '__attribute__'. */
158 #undef TARGET_ATTRIBUTE_TABLE
159 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
160 #undef TARGET_NARROW_VOLATILE_BITFIELD
161 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
164 #undef TARGET_UNWIND_WORD_MODE
165 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
167 /* Override Options. */
168 #undef TARGET_OPTION_OVERRIDE
169 #define TARGET_OPTION_OVERRIDE cr16_override_options
171 /* Conditional register usuage. */
172 #undef TARGET_CONDITIONAL_REGISTER_USAGE
173 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
175 /* Controlling register spills. */
176 #undef TARGET_CLASS_LIKELY_SPILLED_P
177 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
179 /* Passing function arguments. */
180 #undef TARGET_FUNCTION_ARG
181 #define TARGET_FUNCTION_ARG cr16_function_arg
182 #undef TARGET_FUNCTION_ARG_ADVANCE
183 #define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
184 #undef TARGET_RETURN_POPS_ARGS
185 #define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
187 /* Initialize the GCC target structure. */
188 #undef TARGET_FRAME_POINTER_REQUIRED
189 #define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required
190 #undef TARGET_CAN_ELIMINATE
191 #define TARGET_CAN_ELIMINATE cr16_can_eliminate
192 #undef TARGET_LEGITIMIZE_ADDRESS
193 #define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address
194 #undef TARGET_LEGITIMATE_CONSTANT_P
195 #define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p
196 #undef TARGET_LEGITIMATE_ADDRESS_P
197 #define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p
199 /* Returning function value. */
200 #undef TARGET_FUNCTION_VALUE
201 #define TARGET_FUNCTION_VALUE cr16_function_value
202 #undef TARGET_LIBCALL_VALUE
203 #define TARGET_LIBCALL_VALUE cr16_libcall_value
204 #undef TARGET_FUNCTION_VALUE_REGNO_P
205 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
207 /* printing the values. */
208 #undef TARGET_PRINT_OPERAND
209 #define TARGET_PRINT_OPERAND cr16_print_operand
210 #undef TARGET_PRINT_OPERAND_ADDRESS
211 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
213 /* Relative costs of operations. */
214 #undef TARGET_ADDRESS_COST
215 #define TARGET_ADDRESS_COST cr16_address_cost
216 #undef TARGET_REGISTER_MOVE_COST
217 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
218 #undef TARGET_MEMORY_MOVE_COST
219 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
221 /* Table of machine attributes. */
222 static const struct attribute_spec cr16_attribute_table
[] = {
223 /* ISRs have special prologue and epilogue requirements. */
224 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
225 affects_type_identity }. */
226 {"interrupt", 0, 0, false, true, true, NULL
, false},
227 {NULL
, 0, 0, false, false, false, NULL
, false}
230 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
231 .?byte directive along with @c is not understood by assembler.
232 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
233 as TARGET_ASM_ALIGNED_xx_OP. */
234 #undef TARGET_ASM_UNALIGNED_HI_OP
235 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
236 #undef TARGET_ASM_UNALIGNED_SI_OP
237 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
238 #undef TARGET_ASM_UNALIGNED_DI_OP
239 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
241 /* Target hook implementations. */
243 /* Implements hook TARGET_RETURN_IN_MEMORY. */
245 cr16_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
247 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
248 return ((size
== -1) || (size
> 8));
251 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
253 cr16_class_likely_spilled_p (reg_class_t rclass
)
255 if ((rclass
) == SHORT_REGS
|| (rclass
) == DOUBLE_BASE_REGS
256 || (rclass
) == LONG_REGS
|| (rclass
) == GENERAL_REGS
)
263 cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
,
264 tree funtype ATTRIBUTE_UNUSED
,
265 int size ATTRIBUTE_UNUSED
)
270 /* Returns true if data model selected via command line option
271 is same as function argument. */
273 cr16_is_data_model (enum data_model_type model
)
275 return (model
== data_model
);
278 /* Parse relevant options and override. */
280 cr16_override_options (void)
282 /* Disable -fdelete-null-pointer-checks option for CR16 target.
283 Programs which rely on NULL pointer dereferences _not_ halting the
284 program may not work properly with this option. So disable this
286 flag_delete_null_pointer_checks
= 0;
288 /* FIXME: To avoid spill_failure ICE during exception handling,
289 * disable cse_fllow_jumps. The spill error occurs when compiler
290 * can't find a suitable candidate in GENERAL_REGS class to reload
292 * Need to find a better way of avoiding this situation. */
294 flag_cse_follow_jumps
= 0;
296 /* If -fpic option, data_model == DM_FAR. */
297 if (flag_pic
== NEAR_PIC
)
302 /* The only option we want to examine is data model option. */
305 if (strcmp (cr16_data_model
, "medium") == 0)
306 data_model
= DM_DEFAULT
;
307 else if (strcmp (cr16_data_model
, "near") == 0)
308 data_model
= DM_NEAR
;
309 else if (strcmp (cr16_data_model
, "far") == 0)
314 error ("data-model=far not valid for cr16c architecture");
317 error ("invalid data model option -mdata-model=%s", cr16_data_model
);
320 data_model
= DM_DEFAULT
;
323 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
325 cr16_conditional_register_usage (void)
329 fixed_regs
[12] = call_used_regs
[12] = 1;
333 /* Stack layout and calling conventions routines. */
335 /* Return nonzero if the current function being compiled is an interrupt
336 function as specified by the "interrupt" attribute. */
338 cr16_interrupt_function_p (void)
342 attributes
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
343 return (lookup_attribute ("interrupt", attributes
) != NULL_TREE
);
346 /* Compute values for the array current_frame_info.save_regs and the variable
347 current_frame_info.reg_size. The index of current_frame_info.save_regs
348 is numbers of register, each will get 1 if we need to save it in the
349 current function, 0 if not. current_frame_info.reg_size is the total sum
350 of the registers being saved. */
352 cr16_compute_save_regs (void)
356 /* Initialize here so in case the function is no-return it will be -1. */
357 current_frame_info
.last_reg_to_save
= -1;
359 /* Initialize the number of bytes to be saved. */
360 current_frame_info
.reg_size
= 0;
362 /* No need to save any registers if the function never returns. */
363 if (FUNC_IS_NORETURN_P (current_function_decl
) && !MUST_SAVE_REGS_P ())
366 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
368 if (fixed_regs
[regno
])
370 current_frame_info
.save_regs
[regno
] = 0;
374 /* If this reg is used and not call-used (except RA), save it. */
375 if (cr16_interrupt_function_p ())
377 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
378 /* This is a volatile reg in a non-leaf interrupt routine - save
379 it for the sake of its sons. */
380 current_frame_info
.save_regs
[regno
] = 1;
381 else if (df_regs_ever_live_p (regno
))
382 /* This reg is used - save it. */
383 current_frame_info
.save_regs
[regno
] = 1;
385 /* This reg is not used, and is not a volatile - don't save. */
386 current_frame_info
.save_regs
[regno
] = 0;
390 /* If this reg is used and not call-used (except RA), save it. */
391 if (df_regs_ever_live_p (regno
)
392 && (!call_used_regs
[regno
] || regno
== RETURN_ADDRESS_REGNUM
))
393 current_frame_info
.save_regs
[regno
] = 1;
395 current_frame_info
.save_regs
[regno
] = 0;
399 /* Save registers so the exception handler can modify them. */
400 if (crtl
->calls_eh_return
)
406 regno
= EH_RETURN_DATA_REGNO (i
);
407 if (INVALID_REGNUM
== regno
)
409 current_frame_info
.save_regs
[regno
] = 1;
413 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
414 if (current_frame_info
.save_regs
[regno
] == 1)
416 current_frame_info
.last_reg_to_save
= regno
;
417 if (regno
>= CR16_FIRST_DWORD_REGISTER
)
418 current_frame_info
.reg_size
+= CR16_UNITS_PER_DWORD
;
420 current_frame_info
.reg_size
+= UNITS_PER_WORD
;
424 /* Compute the size of the local area and the size to be adjusted by the
425 prologue and epilogue. */
427 cr16_compute_frame (void)
429 /* For aligning the local variables. */
430 int stack_alignment
= STACK_BOUNDARY
/ BITS_PER_UNIT
;
433 /* Padding needed for each element of the frame. */
434 current_frame_info
.var_size
= get_frame_size ();
436 /* Align to the stack alignment. */
437 padding_locals
= current_frame_info
.var_size
% stack_alignment
;
439 padding_locals
= stack_alignment
- padding_locals
;
441 current_frame_info
.var_size
+= padding_locals
;
442 current_frame_info
.total_size
= current_frame_info
.var_size
443 + (ACCUMULATE_OUTGOING_ARGS
444 ? crtl
->outgoing_args_size
: 0);
447 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
449 cr16_initial_elimination_offset (int from
, int to
)
451 /* Compute this since we need to use current_frame_info.reg_size. */
452 cr16_compute_save_regs ();
454 /* Compute this since we need to use current_frame_info.var_size. */
455 cr16_compute_frame ();
457 if (((from
) == FRAME_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
458 return (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0);
459 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == FRAME_POINTER_REGNUM
))
460 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
);
461 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
462 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
463 + (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0));
468 /* Register Usage. */
470 /* Return the class number of the smallest class containing reg number REGNO.
471 This could be a conditional expression or could index an array. */
473 cr16_regno_reg_class (int regno
)
475 if ((regno
>= 0) && (regno
< CR16_FIRST_DWORD_REGISTER
))
478 if ((regno
>= CR16_FIRST_DWORD_REGISTER
) && (regno
< FIRST_PSEUDO_REGISTER
))
484 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
486 cr16_hard_regno_mode_ok (int regno
, machine_mode mode
)
488 if ((GET_MODE_SIZE (mode
) >= 4) && (regno
== 11))
491 if (mode
== DImode
|| mode
== DFmode
)
493 if ((regno
> 8) || (regno
& 1))
499 && ((regno
>= 12) && (GET_MODE_SIZE (mode
) < 4 )))
502 /* CC can only hold CCmode values. */
503 if (GET_MODE_CLASS (mode
) == MODE_CC
)
508 /* Returns register number for function return value.*/
509 static inline unsigned int
510 cr16_ret_register (void)
515 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
517 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED
,
518 int incoming ATTRIBUTE_UNUSED
)
520 return gen_rtx_REG (Pmode
, cr16_ret_register ());
523 /* Returning function value. */
525 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
527 cr16_function_value_regno_p (const unsigned int regno
)
529 return (regno
== cr16_ret_register ());
532 /* Create an RTX representing the place where a
533 library function returns a value of mode MODE. */
535 cr16_libcall_value (machine_mode mode
,
536 const_rtx func ATTRIBUTE_UNUSED
)
538 return gen_rtx_REG (mode
, cr16_ret_register ());
541 /* Create an RTX representing the place where a
542 function returns a value of data type VALTYPE. */
544 cr16_function_value (const_tree type
,
545 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
546 bool outgoing ATTRIBUTE_UNUSED
)
548 return gen_rtx_REG (TYPE_MODE (type
), cr16_ret_register ());
551 /* Passing function arguments. */
553 /* If enough param regs are available for passing the param of type TYPE return
554 the number of registers needed else 0. */
556 enough_regs_for_param (CUMULATIVE_ARGS
* cum
, const_tree type
,
563 type_size
= GET_MODE_BITSIZE (mode
);
565 type_size
= int_size_in_bytes (type
) * BITS_PER_UNIT
;
567 remaining_size
= BITS_PER_WORD
* (MAX_REG_FOR_PASSING_ARGS
568 - (MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) +
571 /* Any variable which is too big to pass in two registers, will pass on
573 if ((remaining_size
>= type_size
) && (type_size
<= 2 * BITS_PER_WORD
))
574 return (type_size
+ BITS_PER_WORD
- 1) / BITS_PER_WORD
;
579 /* Implements the macro FUNCTION_ARG defined in cr16.h. */
581 cr16_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
582 const_tree type
, bool named ATTRIBUTE_UNUSED
)
584 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
585 cum
->last_parm_in_reg
= 0;
587 /* function_arg () is called with this type just after all the args have
588 had their registers assigned. The rtx that function_arg returns from
589 this type is supposed to pass to 'gen_call' but currently it is not
590 implemented (see macro GEN_CALL). */
591 if (type
== void_type_node
)
594 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
599 /* Enable structures that need padding bytes at the end to pass to a
600 function in registers. */
601 if (enough_regs_for_param (cum
, type
, mode
) != 0)
603 cum
->last_parm_in_reg
= 1;
604 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
608 if ((MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) > MAX_REG_FOR_PASSING_ARGS
)
612 if (enough_regs_for_param (cum
, type
, mode
) != 0)
614 cum
->last_parm_in_reg
= 1;
615 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
622 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
624 cr16_init_cumulative_args (CUMULATIVE_ARGS
* cum
, tree fntype
,
625 rtx libfunc ATTRIBUTE_UNUSED
)
627 tree param
, next_param
;
631 /* Determine if this function has variable arguments. This is indicated by
632 the last argument being 'void_type_mode' if there are no variable
633 arguments. Change here for a different vararg. */
634 for (param
= (fntype
) ? TYPE_ARG_TYPES (fntype
) : 0;
635 param
!= NULL_TREE
; param
= next_param
)
637 next_param
= TREE_CHAIN (param
);
638 if ((next_param
== NULL_TREE
) && (TREE_VALUE (param
) != void_type_node
))
646 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
648 cr16_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
649 const_tree type
, bool named ATTRIBUTE_UNUSED
)
651 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
653 /* l holds the number of registers required. */
654 int l
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
656 /* If the parameter isn't passed on a register don't advance cum. */
657 if (!cum
->last_parm_in_reg
)
660 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
663 if ((mode
== SImode
) || (mode
== HImode
)
664 || (mode
== QImode
) || (mode
== DImode
))
671 else if ((mode
== SFmode
) || (mode
== DFmode
))
673 else if ((mode
) == BLKmode
)
675 if ((l
= enough_regs_for_param (cum
, type
, mode
)) != 0)
681 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
682 Return nonzero if N is a register used for passing parameters. */
684 cr16_function_arg_regno_p (int n
)
686 return ((n
<= MAX_REG_FOR_PASSING_ARGS
) && (n
>= MIN_REG_FOR_PASSING_ARGS
));
690 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
691 defined in cr16.h. */
693 /* Helper function to check if is a valid base register that can
696 cr16_addr_reg_p (rtx addr_reg
)
700 if (REG_P (addr_reg
))
702 else if ((GET_CODE (addr_reg
) == SUBREG
)
703 && REG_P (SUBREG_REG (addr_reg
))
704 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg
)))
706 reg
= SUBREG_REG (addr_reg
);
710 if (GET_MODE (reg
) != Pmode
)
716 /* Helper functions: Created specifically for decomposing operand of CONST
717 Recursively look into expression x for code or data symbol.
718 The function expects the expression to contain combination of
719 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
720 LABEL_REF, CONST_INT, (PLUS or MINUS)
723 All other combinations will result in code = -1 and data = ILLEGAL_DM
725 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
726 0 DM_FAR SYMBOL_REF was found and it was far data reference.
727 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
728 1 ILLEGAL_DM LABEL_REF was found.
729 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
731 cr16_decompose_const (rtx x
, int *code
, enum data_model_type
*data
,
736 switch (GET_CODE (x
))
739 *code
= SYMBOL_REF_FUNCTION_P (x
) ? 2 : 0;
740 /* 2 indicates func sym. */
743 if (CR16_TARGET_DATA_NEAR
)
745 else if (CR16_TARGET_DATA_MEDIUM
)
747 else if (CR16_TARGET_DATA_FAR
)
750 /* This will be used only for printing
751 the qualifier. This call is (may be)
752 made by cr16_print_operand_address. */
755 /* This call is (may be) made by
756 cr16_legitimate_address_p. */
763 /* 1 - indicates non-function symbol. */
769 /* Look into the tree nodes. */
770 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
771 cr16_decompose_const (XEXP (x
, 1), code
, data
, treat_as_const
);
772 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
773 cr16_decompose_const (XEXP (x
, 0), code
, data
, treat_as_const
);
781 This function decomposes the address returns the type of address
782 as defined in enum cr16_addrtype. It also fills the parameter *out.
783 The decomposed address can be used for two purposes. One to
784 check if the address is valid and second to print the address
787 Following tables list valid address supported in CR16C/C+ architectures.
789 aN : Absoulte address N-bit address
790 R : One 16-bit register
791 RP : Consecutive two 16-bit registers or one 32-bit register
792 I : One 32-bit register
793 dispN : Signed displacement of N-bits
795 ----Code addresses----
797 disp9 : CR16_ABSOLUTE (disp)
798 disp17 : CR16_ABSOLUTE (disp)
799 disp25 : CR16_ABSOLUTE (disp)
800 RP + disp25 : CR16_REGP_REL (base, disp)
803 RP : CR16_REGP_REL (base, disp=0)
804 a24 : CR16_ABSOLUTE (disp)
806 ----Data addresses----
807 a20 : CR16_ABSOLUTE (disp) near (1M)
808 a24 : CR16_ABSOLUTE (disp) medium (16M)
809 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
810 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
811 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
812 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
813 I : *** Valid but port does not support this
814 I + a20 : *** Valid but port does not support this
815 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
816 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
818 Decomposing Data model in case of absolute address.
820 Target Option Address type Resultant Data ref type
821 ---------------------- ------------ -----------------------
822 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
823 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
824 CR16_TARGET_MODEL_NEAR ABS24 Invalid
825 CR16_TARGET_MODEL_NEAR IMM32 Invalid
827 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
828 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
829 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
830 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
832 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
833 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
834 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
835 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
837 cr16_decompose_address (rtx addr
, struct cr16_address
*out
,
838 bool debug_print
, bool treat_as_const
)
840 rtx base
= NULL_RTX
, disp
= NULL_RTX
, index
= NULL_RTX
;
841 enum data_model_type data
= ILLEGAL_DM
;
843 enum cr16_addrtype retval
= CR16_INVALID
;
845 switch (GET_CODE (addr
))
848 /* Absolute address (known at compile time). */
851 fprintf (stderr
, "\ncode:%d", code
);
856 fprintf (stderr
, "\ndisp:");
860 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
864 fprintf (stderr
, "\ndata:%d", data
);
865 retval
= CR16_ABSOLUTE
;
867 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 24))
869 if (!CR16_TARGET_DATA_NEAR
)
873 fprintf (stderr
, "\ndata:%d", data
);
874 retval
= CR16_ABSOLUTE
;
877 return CR16_INVALID
; /* ABS24 is not support in NEAR model. */
884 /* A CONST is an expression of PLUS or MINUS with
885 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
886 result of assembly-time arithmetic computation. */
887 retval
= CR16_ABSOLUTE
;
889 /* Call the helper function to check the validity. */
890 cr16_decompose_const (XEXP (addr
, 0), &code
, &data
, treat_as_const
);
891 if ((code
== 0) && (data
== ILLEGAL_DM
))
892 /* CONST is not valid code or data address. */
896 fprintf (stderr
, "\ndisp:");
898 fprintf (stderr
, "\ncode:%d", code
);
899 fprintf (stderr
, "\ndata:%d", data
);
904 retval
= CR16_ABSOLUTE
;
906 /* 1 - indicates non-function symbol. */
910 fprintf (stderr
, "\ndisp:");
912 fprintf (stderr
, "\ncode:%d", code
);
917 /* Absolute address (known at link time). */
918 retval
= CR16_ABSOLUTE
;
920 /* This is a code address if symbol_ref is a function. */
921 /* 2 indicates func sym. */
922 code
= SYMBOL_REF_FUNCTION_P (addr
) ? 2 : 0;
925 fprintf (stderr
, "\ndisp:");
927 fprintf (stderr
, "\ncode:%d", code
);
929 /* If not function ref then check if valid data ref. */
932 if (CR16_TARGET_DATA_NEAR
)
934 else if (CR16_TARGET_DATA_MEDIUM
)
936 else if (CR16_TARGET_DATA_FAR
)
939 /* This will be used only for printing the
940 qualifier. This call is (may be) made
941 by cr16_print_operand_address. */
944 /* This call is (may be) made by
945 cr16_legitimate_address_p. */
952 fprintf (stderr
, "\ndata:%d", data
);
957 /* Register relative address. */
958 /* Assume REG fits in a single register. */
959 retval
= CR16_REG_REL
;
960 if (GET_MODE_BITSIZE (GET_MODE (addr
)) > BITS_PER_WORD
)
961 if (!LONG_REG_P (REGNO (addr
)))
962 /* REG will result in reg pair. */
963 retval
= CR16_REGP_REL
;
967 fprintf (stderr
, "\nbase:");
973 switch (GET_CODE (XEXP (addr
, 0)))
978 /* All Reg relative addresses having a displacement needs
979 to fit in 20-bits. */
980 disp
= XEXP (addr
, 1);
983 fprintf (stderr
, "\ndisp:");
986 switch (GET_CODE (XEXP (addr
, 1)))
989 /* Shall fit in 20-bits. */
990 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
994 fprintf (stderr
, "\ncode:%d", code
);
998 switch (XINT (XEXP (addr
, 1), 1))
1000 case UNSPEC_LIBRARY_OFFSET
:
1009 /* This is also a valid expression for address.
1010 However, we cannot ascertain if the resultant
1011 displacement will be valid 20-bit value. Therefore,
1012 lets not allow such an expression for now. This will
1013 be updated when we find a way to validate this
1014 expression as legitimate address.
1015 Till then fall through CR16_INVALID. */
1017 return CR16_INVALID
;
1020 /* Now check if REG can fit into single or pair regs. */
1021 retval
= CR16_REG_REL
;
1022 base
= XEXP (addr
, 0);
1025 fprintf (stderr
, "\nbase:");
1028 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr
, 0)))) > BITS_PER_WORD
)
1030 if (!LONG_REG_P (REGNO ((XEXP (addr
, 0)))))
1031 /* REG will result in reg pair. */
1032 retval
= CR16_REGP_REL
;
1046 Check if the operand 1 is valid index register. */
1049 fprintf (stderr
, "\ndata:%d", data
);
1050 switch (GET_CODE (XEXP (addr
, 1)))
1054 if (!REG_OK_FOR_INDEX_P (XEXP (addr
, 1)))
1055 return CR16_INVALID
;
1056 /* OK. REG is a valid index register. */
1057 index
= XEXP (addr
, 1);
1060 fprintf (stderr
, "\nindex:");
1065 return CR16_INVALID
;
1067 /* Check if operand 0 of operand 0 is REGP. */
1068 switch (GET_CODE (XEXP (XEXP (addr
, 0), 0)))
1072 /* Now check if REG is a REGP and not in LONG regs. */
1073 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr
, 0), 0)))
1076 if (REGNO (XEXP (XEXP (addr
, 0), 0))
1077 >= CR16_FIRST_DWORD_REGISTER
)
1078 return CR16_INVALID
;
1079 base
= XEXP (XEXP (addr
, 0), 0);
1082 fprintf (stderr
, "\nbase:");
1087 return CR16_INVALID
;
1090 return CR16_INVALID
;
1092 /* Now check if the operand 1 of operand 0 is const_int. */
1093 if (GET_CODE (XEXP (XEXP (addr
, 0), 1)) == CONST_INT
)
1095 disp
= XEXP (XEXP (addr
, 0), 1);
1098 fprintf (stderr
, "\ndisp:");
1101 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
1102 return CR16_INVALID
;
1105 return CR16_INVALID
;
1106 retval
= CR16_INDEX_REGP_REL
;
1109 return CR16_INVALID
;
1114 return CR16_INVALID
;
1117 /* Check if the base and index registers are valid. */
1118 if (base
&& !(cr16_addr_reg_p (base
)))
1119 return CR16_INVALID
;
1120 if (base
&& !(CR16_REG_OK_FOR_BASE_P (base
)))
1121 return CR16_INVALID
;
1122 if (index
&& !(REG_OK_FOR_INDEX_P (index
)))
1123 return CR16_INVALID
;
1125 /* Write the decomposition to out parameter. */
1135 /* Return non-zero value if 'x' is legitimate PIC operand
1136 when generating PIC code. */
1138 legitimate_pic_operand_p (rtx x
)
1140 switch (GET_CODE (x
))
1149 /* REVISIT: Use something like symbol_referenced_p. */
1150 if (GET_CODE (XEXP (x
, 0)) == PLUS
1151 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
1152 || GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
)
1153 && (GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
))
1157 return legitimate_pic_operand_p (XEXP (x
, 0));
1165 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
1167 Input Output (-f pic) Output (-f PIC)
1170 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
1172 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
1174 NOTE: @BRO is added using unspec:BRO
1175 NOTE: @GOT is added using unspec:GOT. */
1177 legitimize_pic_address (rtx orig
, machine_mode mode ATTRIBUTE_UNUSED
,
1180 /* First handle a simple SYMBOL_REF or LABEL_REF. */
1181 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1184 reg
= gen_reg_rtx (Pmode
);
1186 if (flag_pic
== NEAR_PIC
)
1188 /* Unspec to handle -fpic option. */
1189 emit_insn (gen_unspec_bro_addr (reg
, orig
));
1190 emit_insn (gen_addsi3 (reg
, reg
, pic_offset_table_rtx
));
1192 else if (flag_pic
== FAR_PIC
)
1194 /* Unspec to handle -fPIC option. */
1195 emit_insn (gen_unspec_got_addr (reg
, orig
));
1199 else if (GET_CODE (orig
) == CONST
)
1201 /* To handle (symbol + offset). */
1204 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1205 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1210 gcc_assert (can_create_pseudo_p ());
1211 reg
= gen_reg_rtx (Pmode
);
1214 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
1216 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1217 offset
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1218 base
== reg
? 0 : reg
);
1220 /* REVISIT: Optimize for const-offsets. */
1221 emit_insn (gen_addsi3 (reg
, base
, offset
));
1228 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
1230 cr16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1231 rtx addr
, bool strict
)
1233 enum cr16_addrtype addrtype
;
1234 struct cr16_address address
;
1236 if (TARGET_DEBUG_ADDR
)
1239 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
1240 GET_MODE_NAME (mode
), strict
);
1243 addrtype
= cr16_decompose_address (addr
, &address
,
1244 (TARGET_DEBUG_ADDR
? 1 : 0), FALSE
);
1246 if (TARGET_DEBUG_ADDR
)
1248 const char *typestr
;
1253 typestr
= "invalid";
1256 typestr
= "absolute";
1259 typestr
= "register relative";
1262 typestr
= "register pair relative";
1264 case CR16_INDEX_REGP_REL
:
1265 typestr
= "index + register pair relative";
1270 fprintf (stderr
, "\ncr16 address type: %s\n", typestr
);
1273 if (addrtype
== CR16_INVALID
)
1279 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address
.base
), mode
))
1281 if (TARGET_DEBUG_ADDR
)
1282 fprintf (stderr
, "base register not strict\n");
1285 if (address
.index
&& !REGNO_OK_FOR_INDEX_P (REGNO (address
.index
)))
1287 if (TARGET_DEBUG_ADDR
)
1288 fprintf (stderr
, "index register not strict\n");
1293 /* Return true if addressing mode is register relative. */
1296 if (addrtype
== CR16_REG_REL
|| addrtype
== CR16_REGP_REL
)
1305 /* Routines to compute costs. */
1307 /* Return cost of the memory address x. */
1309 cr16_address_cost (rtx addr
, machine_mode mode ATTRIBUTE_UNUSED
,
1310 addr_space_t as ATTRIBUTE_UNUSED
,
1311 bool speed ATTRIBUTE_UNUSED
)
1313 enum cr16_addrtype addrtype
;
1314 struct cr16_address address
;
1317 addrtype
= cr16_decompose_address (addr
, &address
, 0, FALSE
);
1319 gcc_assert (addrtype
!= CR16_INVALID
);
1321 /* CR16_ABSOLUTE : 3
1322 CR16_REG_REL (disp !=0) : 4
1323 CR16_REG_REL (disp ==0) : 5
1324 CR16_REGP_REL (disp !=0) : 6
1325 CR16_REGP_REL (disp ==0) : 7
1326 CR16_INDEX_REGP_REL (disp !=0) : 8
1327 CR16_INDEX_REGP_REL (disp ==0) : 9. */
1341 case CR16_INDEX_REGP_REL
:
1349 if (TARGET_DEBUG_ADDR
)
1351 fprintf (stderr
, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost
);
1359 /* Implement `TARGET_REGISTER_MOVE_COST'. */
1361 cr16_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED
,
1362 reg_class_t from ATTRIBUTE_UNUSED
, reg_class_t to
)
1364 return (to
!= GENERAL_REGS
? 8 : 2);
1367 /* Implement `TARGET_MEMORY_MOVE_COST'. */
1369 /* Return the cost of moving data of mode MODE between a register of class
1370 CLASS and memory; IN is zero if the value is to be written to memory,
1371 nonzero if it is to be read in. This cost is relative to those in
1372 REGISTER_MOVE_COST. */
1374 cr16_memory_move_cost (machine_mode mode
,
1375 reg_class_t rclass ATTRIBUTE_UNUSED
,
1376 bool in ATTRIBUTE_UNUSED
)
1378 /* One LD or ST takes twice the time of a simple reg-reg move. */
1379 if (reg_classes_intersect_p (rclass
, GENERAL_REGS
))
1380 return (4 * HARD_REGNO_NREGS (0, mode
));
1385 /* Instruction output. */
1387 /* Check if a const_double is ok for cr16 store-immediate instructions. */
1389 cr16_const_double_ok (rtx op
)
1391 if (GET_MODE (op
) == SFmode
)
1395 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1396 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1397 return UNSIGNED_INT_FITS_N_BITS (l
, 4) ? 1 : 0;
1400 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op
), 4)) &&
1401 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op
), 4))) ? 1 : 0;
1404 /* Returns bit position of first 0 or 1 bit.
1405 It is safe to assume val as 16-bit wide. */
1407 cr16_operand_bit_pos (int val
, int bitval
)
1413 for (i
= 0; i
< 16; i
++)
1419 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
1421 cr16_print_operand (FILE * file
, rtx x
, int code
)
1423 int ptr_dereference
= 0;
1429 const char *cr16_cmp_str
;
1430 switch (GET_CODE (x
))
1432 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
1433 -> swap all non symmetric ops. */
1435 cr16_cmp_str
= "eq";
1438 cr16_cmp_str
= "ne";
1441 cr16_cmp_str
= "lt";
1444 cr16_cmp_str
= "lo";
1447 cr16_cmp_str
= "gt";
1450 cr16_cmp_str
= "hi";
1453 cr16_cmp_str
= "le";
1456 cr16_cmp_str
= "ls";
1459 cr16_cmp_str
= "ge";
1462 cr16_cmp_str
= "hs";
1467 fprintf (file
, "%s", cr16_cmp_str
);
1475 if (GET_CODE (x
) == REG
)
1477 /* For Push instructions, we should not print register pairs. */
1478 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1484 /* Print the immediate address for bal
1485 'b' is used instead of 'a' to avoid compiler calling
1486 the GO_IF_LEGITIMATE_ADDRESS which cannot
1487 perform checks on const_int code addresses as it
1488 assumes all const_int are data addresses. */
1489 fprintf (file
, "0x%lx", INTVAL (x
));
1493 /* Print bit position of first 0. */
1494 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 0));
1498 /* Print bit position of first 1. */
1499 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 1));
1502 /* 'g' is used for implicit mem: dereference. */
1503 ptr_dereference
= 1;
1507 switch (GET_CODE (x
))
1510 if (GET_MODE_BITSIZE (GET_MODE (x
)) > BITS_PER_WORD
)
1512 if (LONG_REG_P (REGNO (x
)))
1513 fprintf (file
, "(%s)", reg_names
[REGNO (x
)]);
1515 fprintf (file
, "(%s,%s)", reg_names
[REGNO (x
) + 1],
1516 reg_names
[REGNO (x
)]);
1519 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1523 output_address (XEXP (x
, 0));
1531 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1532 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1534 fprintf (file
, "$0x%lx", l
);
1539 fprintf (file
, "$%ld", INTVAL (x
));
1543 switch (XINT (x
, 1))
1551 if (!ptr_dereference
)
1555 cr16_print_operand_address (file
, x
);
1559 output_operand_lossage ("invalid %%xn code");
1565 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
1568 cr16_print_operand_address (FILE * file
, rtx addr
)
1570 enum cr16_addrtype addrtype
;
1571 struct cr16_address address
;
1573 /* Decompose the address. Also ask it to treat address as constant. */
1574 addrtype
= cr16_decompose_address (addr
, &address
, 0, TRUE
);
1576 if (address
.disp
&& GET_CODE (address
.disp
) == UNSPEC
)
1586 if (GET_CODE (address
.disp
) == UNSPEC
)
1587 cr16_print_operand (file
, address
.disp
, 0);
1589 output_addr_const (file
, address
.disp
);
1592 fprintf (file
, "0");
1593 fprintf (file
, "(%s)", reg_names
[REGNO (address
.base
)]);
1598 output_addr_const (file
, address
.disp
);
1600 fprintf (file
, "0");
1603 case CR16_INDEX_REGP_REL
:
1604 fprintf (file
, "[%s]", reg_names
[REGNO (address
.index
)]);
1609 if (GET_CODE (address
.disp
) == UNSPEC
)
1610 cr16_print_operand (file
, address
.disp
, 0);
1612 output_addr_const (file
, address
.disp
);
1615 fprintf (file
, "0");
1616 fprintf (file
, "(%s,%s)", reg_names
[REGNO (address
.base
) + 1],
1617 reg_names
[REGNO (address
.base
)]);
1623 /* Add qualifiers to the address expression that was just printed. */
1624 if (flag_pic
< NEAR_PIC
&& address
.code
== 0)
1626 if (address
.data
== DM_FAR
)
1627 /* Addr contains SYMBOL_REF & far data ptr. */
1628 fprintf (file
, "@l");
1629 else if (address
.data
== DM_DEFAULT
)
1630 /* Addr contains SYMBOL_REF & medium data ptr. */
1631 fprintf (file
, "@m");
1632 /* Addr contains SYMBOL_REF & medium data ptr. */
1633 else if (address
.data
== DM_NEAR
)
1634 /* Addr contains SYMBOL_REF & near data ptr. */
1635 fprintf (file
, "@s");
1637 else if (flag_pic
== NEAR_PIC
1638 && (address
.code
== 0) && (address
.data
== DM_FAR
1639 || address
.data
== DM_DEFAULT
1640 || address
.data
== DM_NEAR
))
1642 fprintf (file
, "@l");
1644 else if (flag_pic
== NEAR_PIC
&& address
.code
== 2)
1646 fprintf (file
, "pic");
1648 else if (flag_pic
== NEAR_PIC
&& address
.code
== 1)
1650 fprintf (file
, "@cpic");
1653 else if (flag_pic
== FAR_PIC
&& address
.code
== 2)
1655 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
1656 address ! GOTc tells assembler this symbol is a text-address
1657 This needs to be fixed in such a way that this offset is done
1658 only in the case where an address is being used for indirect jump
1659 or call. Determining the potential usage of loadd is of course not
1660 possible always. Eventually, this has to be fixed in the
1662 fprintf (file
, "GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1664 else if (flag_pic
== FAR_PIC
&& address
.code
== 1)
1666 fprintf (file
, "@cGOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1669 else if (flag_pic
== FAR_PIC
&&
1670 (address
.data
== DM_FAR
|| address
.data
== DM_DEFAULT
1671 || address
.data
== DM_NEAR
))
1673 fprintf (file
, "@GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1677 /* Machine description helper functions. */
1679 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
1680 When push_or_pop is zero -> string for push instructions of prologue.
1681 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1682 Relies on the assumptions:
1683 1. RA is the last register to be saved.
1684 2. The maximal value of the counter is MAX_COUNT. */
1686 cr16_prepare_push_pop_string (int push_or_pop
)
1688 /* j is the number of registers being saved, takes care that there won't be
1689 more than 8 in one push/pop instruction. */
1691 /* For the register mask string. */
1692 static char one_inst_str
[50];
1694 /* i is the index of current_frame_info.save_regs[], going from 0 until
1695 current_frame_info.last_reg_to_save. */
1701 /* For reversing on the push instructions if there are more than one. */
1704 return_str
= (char *) xmalloc (160);
1705 temp_str
= (char *) xmalloc (160);
1708 memset (return_str
, 0, 3);
1711 while (i
<= current_frame_info
.last_reg_to_save
)
1713 /* Prepare mask for one instruction. */
1714 one_inst_str
[0] = 0;
1716 /* To count number of words in one instruction. */
1720 while ((word_cnt
< MAX_COUNT
)
1721 && (i
<= current_frame_info
.last_reg_to_save
))
1723 /* For each non consecutive save register,
1724 a new instruction shall be generated. */
1725 if (!current_frame_info
.save_regs
[i
])
1727 /* Move to next reg and break. */
1732 if (i
== RETURN_ADDRESS_REGNUM
)
1736 /* Check especially if adding 2 does not cross the MAX_COUNT. */
1737 if ((word_cnt
+ ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2))
1740 /* Increase word count by 2 for long registers except RA. */
1741 word_cnt
+= ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2);
1746 /* No need to generate any instruction as
1747 no register or RA needs to be saved. */
1748 if ((word_cnt
== 0) && (print_ra
== 0))
1751 /* Now prepare the instruction operands. */
1754 sprintf (one_inst_str
, "$%d, %s", word_cnt
, reg_names
[start_reg
]);
1756 strcat (one_inst_str
, ", ra");
1759 strcat (one_inst_str
, "ra");
1761 if (push_or_pop
== 1)
1763 /* Pop instruction. */
1764 if (print_ra
&& !cr16_interrupt_function_p ()
1765 && !crtl
->calls_eh_return
)
1766 /* Print popret if RA is saved and its not a interrupt
1768 strcpy (temp_str
, "\n\tpopret\t");
1770 strcpy (temp_str
, "\n\tpop\t");
1772 strcat (temp_str
, one_inst_str
);
1774 /* Add the pop instruction list. */
1775 strcat (return_str
, temp_str
);
1779 /* Push instruction. */
1780 strcpy (temp_str
, "\n\tpush\t");
1781 strcat (temp_str
, one_inst_str
);
1783 /* We need to reverse the order of the instructions if there
1784 are more than one. (since the pop will not be reversed in
1786 strcat (temp_str
, return_str
);
1787 strcpy (return_str
, temp_str
);
1791 if (push_or_pop
== 1)
1794 if (cr16_interrupt_function_p ())
1795 strcat (return_str
, "\n\tretx\n");
1796 else if (crtl
->calls_eh_return
)
1798 /* Add stack adjustment before returning to exception handler
1799 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
1800 strcat (return_str
, "\n\taddd\t (r5, r4), (sp)\t\n");
1801 strcat (return_str
, "\n\tjump\t (ra)\n");
1803 /* But before anything else, undo the adjustment addition done in
1804 cr16_expand_epilogue (). */
1805 strcpy (temp_str
, "\n\tsubd\t (r5, r4), (sp)\t\n");
1806 strcat (temp_str
, return_str
);
1807 strcpy (return_str
, temp_str
);
1809 else if (!FUNC_IS_NORETURN_P (current_function_decl
)
1810 && !(current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]))
1811 strcat (return_str
, "\n\tjump\t (ra)\n");
1814 /* Skip the newline and the tab in the start of return_str. */
1820 /* Generate DWARF2 annotation for multi-push instruction. */
1822 cr16_create_dwarf_for_multi_push (rtx insn
)
1824 rtx dwarf
, reg
, tmp
;
1825 int i
, j
, from
, to
, word_cnt
, dwarf_par_index
, inc
;
1827 int num_regs
= 0, offset
= 0, split_here
= 0, total_push_bytes
= 0;
1829 for (i
= 0; i
<= current_frame_info
.last_reg_to_save
; ++i
)
1831 if (current_frame_info
.save_regs
[i
])
1834 if (i
< CR16_FIRST_DWORD_REGISTER
)
1835 total_push_bytes
+= 2;
1837 total_push_bytes
+= 4;
1844 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (num_regs
+ 1));
1845 dwarf_par_index
= num_regs
;
1847 from
= current_frame_info
.last_reg_to_save
+ 1;
1848 to
= current_frame_info
.last_reg_to_save
;
1851 for (i
= current_frame_info
.last_reg_to_save
; i
>= 0;)
1853 if (!current_frame_info
.save_regs
[i
] || 0 == i
|| split_here
)
1855 /* This block of regs is pushed in one instruction. */
1856 if (0 == i
&& current_frame_info
.save_regs
[i
])
1859 for (j
= to
; j
>= from
; --j
)
1861 if (j
< CR16_FIRST_DWORD_REGISTER
)
1871 reg
= gen_rtx_REG (mode
, j
);
1873 tmp
= gen_rtx_SET (gen_frame_mem (mode
,
1875 (Pmode
, stack_pointer_rtx
,
1876 total_push_bytes
- offset
)),
1878 RTX_FRAME_RELATED_P (tmp
) = 1;
1879 XVECEXP (dwarf
, 0, dwarf_par_index
--) = tmp
;
1888 if (i
!= RETURN_ADDRESS_REGNUM
)
1890 inc
= (i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2;
1891 if (word_cnt
+ inc
>= MAX_COUNT
|| FRAME_POINTER_REGNUM
== i
)
1903 tmp
= gen_rtx_SET (stack_pointer_rtx
,
1904 gen_rtx_PLUS (SImode
, stack_pointer_rtx
,
1905 GEN_INT (-offset
)));
1906 RTX_FRAME_RELATED_P (tmp
) = 1;
1907 XVECEXP (dwarf
, 0, 0) = tmp
;
1909 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, dwarf
);
1913 CompactRISC CR16 Architecture stack layout:
1915 0 +---------------------
1920 +==================== Sp (x) = Ap (x+1)
1921 A | Args for functions
1922 | | called by X and Dynamically
1923 | | Dynamic allocations allocated and
1924 | | (alloca, variable deallocated
1925 Stack | length arrays).
1926 grows +-------------------- Fp (x)
1927 down| | Local variables of X
1928 ward| +--------------------
1929 | | Regs saved for X-1
1930 | +==================== Sp (x-1) = Ap (x)
1933 +-------------------- Fp (x-1)
1939 cr16_expand_prologue (void)
1943 cr16_compute_frame ();
1944 cr16_compute_save_regs ();
1946 /* If there is no need in push and adjustment to sp, return. */
1947 if ((current_frame_info
.total_size
+ current_frame_info
.reg_size
) == 0)
1950 if (current_frame_info
.last_reg_to_save
!= -1)
1952 /* If there are registers to push. */
1953 insn
= emit_insn (gen_push_for_prologue
1954 (GEN_INT (current_frame_info
.reg_size
)));
1955 cr16_create_dwarf_for_multi_push (insn
);
1956 RTX_FRAME_RELATED_P (insn
) = 1;
1960 if (current_frame_info
.total_size
> 0)
1962 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1963 GEN_INT (-current_frame_info
.total_size
)));
1964 RTX_FRAME_RELATED_P (insn
) = 1;
1967 if (frame_pointer_needed
)
1969 /* Initialize the frame pointer with the value of the stack pointer
1970 pointing now to the locals. */
1971 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1975 /* Generate insn that updates the stack for local variables and padding
1976 for registers we save. - Generate the appropriate return insn. */
1978 cr16_expand_epilogue (void)
1982 /* Nonzero if we need to return and pop only RA. This will generate a
1983 different insn. This differentiate is for the peepholes for call as
1984 last statement in function. */
1985 int only_popret_RA
= (current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]
1986 && (current_frame_info
.reg_size
1987 == CR16_UNITS_PER_DWORD
));
1989 if (frame_pointer_needed
)
1991 /* Restore the stack pointer with the frame pointers value. */
1992 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
1995 if (current_frame_info
.total_size
> 0)
1997 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1998 GEN_INT (current_frame_info
.total_size
)));
1999 RTX_FRAME_RELATED_P (insn
) = 1;
2002 if (crtl
->calls_eh_return
)
2004 /* Add this here so that (r5, r4) is actually loaded with the adjustment
2005 value; otherwise, the load might be optimized away...
2006 NOTE: remember to subtract the adjustment before popping the regs
2007 and add it back before returning. */
2008 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
2009 EH_RETURN_STACKADJ_RTX
));
2012 if (cr16_interrupt_function_p ())
2014 insn
= emit_jump_insn (gen_interrupt_return ());
2015 RTX_FRAME_RELATED_P (insn
) = 1;
2017 else if (crtl
->calls_eh_return
)
2019 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
2020 insn
= emit_jump_insn (gen_pop_and_popret_return
2021 (GEN_INT (current_frame_info
.reg_size
)));
2022 RTX_FRAME_RELATED_P (insn
) = 1;
2024 else if (current_frame_info
.last_reg_to_save
== -1)
2025 /* Nothing to pop. */
2026 /* Don't output jump for interrupt routine, only retx. */
2027 emit_jump_insn (gen_jump_return ());
2028 else if (only_popret_RA
)
2030 insn
= emit_jump_insn (gen_popret_RA_return ());
2031 RTX_FRAME_RELATED_P (insn
) = 1;
2035 insn
= emit_jump_insn (gen_pop_and_popret_return
2036 (GEN_INT (current_frame_info
.reg_size
)));
2037 RTX_FRAME_RELATED_P (insn
) = 1;
2041 /* Implements FRAME_POINTER_REQUIRED. */
2043 cr16_frame_pointer_required (void)
2045 return (cfun
->calls_alloca
|| crtl
->calls_eh_return
2046 || cfun
->has_nonlocal_label
|| crtl
->calls_eh_return
);
2050 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
2052 return (to
== STACK_POINTER_REGNUM
? !frame_pointer_needed
: true);
2056 /* A C compound statement that attempts to replace X with
2057 a valid memory address for an operand of mode MODE. WIN
2058 will be a C statement label elsewhere in the code.
2059 X will always be the result of a call to break_out_memory_refs (),
2060 and OLDX will be the operand that was given to that function to
2062 The code generated by this macro should not alter the
2063 substructure of X. If it transforms X into a more legitimate form,
2064 it should assign X (which will always be a C variable) a new value. */
2066 cr16_legitimize_address (rtx x
, rtx orig_x ATTRIBUTE_UNUSED
,
2067 machine_mode mode ATTRIBUTE_UNUSED
)
2070 return legitimize_pic_address (orig_x
, mode
, NULL_RTX
);
2075 /* Implement TARGET_LEGITIMATE_CONSTANT_P
2076 Nonzero if X is a legitimate constant for an immediate
2077 operand on the target machine. You can assume that X
2078 satisfies CONSTANT_P. In cr16c treat legitimize float
2079 constant as an immediate operand. */
2081 cr16_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
,
2082 rtx x ATTRIBUTE_UNUSED
)
2088 notice_update_cc (rtx exp
)
2090 if (GET_CODE (exp
) == SET
)
2092 /* Jumps do not alter the cc's. */
2093 if (SET_DEST (exp
) == pc_rtx
)
2096 /* Moving register or memory into a register:
2097 it doesn't alter the cc's, but it might invalidate
2098 the RTX's which we remember the cc's came from.
2099 (Note that moving a constant 0 or 1 MAY set the cc's). */
2100 if (REG_P (SET_DEST (exp
))
2101 && (REG_P (SET_SRC (exp
)) || GET_CODE (SET_SRC (exp
)) == MEM
))
2106 /* Moving register into memory doesn't alter the cc's.
2107 It may invalidate the RTX's which we remember the cc's came from. */
2108 if (GET_CODE (SET_DEST (exp
)) == MEM
&& REG_P (SET_SRC (exp
)))
2119 cr16_unwind_word_mode (void)
2124 /* Helper function for md file. This function is used to emit arithmetic
2125 DI instructions. The argument "num" decides which instruction to be
2128 cr16_emit_add_sub_di (rtx
*operands
, enum rtx_code code
)
2134 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2135 hi0_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 4);
2136 hi1_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 6);
2138 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2139 hi0_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 4);
2140 hi1_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 6);
2146 output_asm_insn ("addd\t%1, %0", lo_op
) ;
2147 output_asm_insn ("addcw\t%1, %0", hi0_op
) ;
2148 output_asm_insn ("addcw\t%1, %0", hi1_op
) ;
2153 output_asm_insn ("subd\t%1, %0", lo_op
) ;
2154 output_asm_insn ("subcw\t%1, %0", hi0_op
) ;
2155 output_asm_insn ("subcw\t%1, %0", hi1_op
) ;
2166 /* Helper function for md file. This function is used to emit logical
2167 DI instructions. The argument "num" decides which instruction to be
2170 cr16_emit_logical_di (rtx
*operands
, enum rtx_code code
)
2175 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2176 hi_op
[0] = simplify_gen_subreg (SImode
, operands
[0], DImode
, 4);
2178 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2179 hi_op
[1] = simplify_gen_subreg (SImode
, operands
[2], DImode
, 4);
2185 output_asm_insn ("andd\t%1, %0", lo_op
) ;
2186 output_asm_insn ("andd\t%1, %0", hi_op
) ;
2191 output_asm_insn ("ord\t%1, %0", lo_op
) ;
2192 output_asm_insn ("ord\t%1, %0", hi_op
) ;
2197 output_asm_insn ("xord\t%1, %0", lo_op
) ;
2198 output_asm_insn ("xord\t%1, %0", hi_op
) ;
2208 /* Initialize 'targetm' variable which contains pointers to functions
2209 and data relating to the target machine. */
2211 struct gcc_target targetm
= TARGET_INITIALIZER
;