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"
66 #include "target-def.h"
70 /* Maximum number of register used for passing parameters. */
71 #define MAX_REG_FOR_PASSING_ARGS 6
73 /* Minimum number register used for passing parameters. */
74 #define MIN_REG_FOR_PASSING_ARGS 2
76 /* The maximum count of words supported in the assembly of the architecture in
77 a push/pop instruction. */
80 /* Predicate is true if the current function is a 'noreturn' function,
81 i.e. it is qualified as volatile. */
82 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
84 /* Predicate that holds when we need to save registers even for 'noreturn'
85 functions, to accommodate for unwinding. */
86 #define MUST_SAVE_REGS_P() \
87 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
89 /* Nonzero if the rtx X is a signed const int of n bits. */
90 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
91 ((GET_CODE (X) == CONST_INT \
92 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
94 /* Nonzero if the rtx X is an unsigned const int of n bits. */
95 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
96 ((GET_CODE (X) == CONST_INT \
97 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
99 /* Structure for stack computations. */
101 /* variable definitions in the struture
102 args_size Number of bytes saved on the stack for local
105 reg_size Number of bytes saved on the stack for
106 non-scratch registers
108 total_size The sum of 2 sizes: locals vars and padding byte
109 for saving the registers. Used in expand_prologue()
110 and expand_epilogue()
112 last_reg_to_save Will hold the number of the last register the
113 prologue saves, -1 if no register is saved
115 save_regs[16] Each object in the array is a register number.
116 Mark 1 for registers that need to be saved
118 num_regs Number of registers saved
120 initialized Non-zero if frame size already calculated, not
123 function_makes_calls Does the function make calls ? not used yet. */
125 struct cr16_frame_info
127 unsigned long var_size
;
128 unsigned long args_size
;
129 unsigned int reg_size
;
130 unsigned long total_size
;
131 long last_reg_to_save
;
132 long save_regs
[FIRST_PSEUDO_REGISTER
];
135 int function_makes_calls
;
138 /* Current frame information calculated by cr16_compute_frame_size. */
139 static struct cr16_frame_info current_frame_info
;
141 /* Static Variables. */
143 /* Data model that was supplied by user via command line option
144 This will be overridden in case of invalid combination
145 of core and data model options are supplied. */
146 static enum data_model_type data_model
= DM_DEFAULT
;
148 /* TARGETM Function Prototypes and forward declarations */
149 static void cr16_print_operand (FILE *, rtx
, int);
150 static void cr16_print_operand_address (FILE *, rtx
);
152 /* Stack layout and calling conventions. */
153 #undef TARGET_STRUCT_VALUE_RTX
154 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
155 #undef TARGET_RETURN_IN_MEMORY
156 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
158 /* Target-specific uses of '__attribute__'. */
159 #undef TARGET_ATTRIBUTE_TABLE
160 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
161 #undef TARGET_NARROW_VOLATILE_BITFIELD
162 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
165 #undef TARGET_UNWIND_WORD_MODE
166 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
168 /* Override Options. */
169 #undef TARGET_OPTION_OVERRIDE
170 #define TARGET_OPTION_OVERRIDE cr16_override_options
172 /* Conditional register usuage. */
173 #undef TARGET_CONDITIONAL_REGISTER_USAGE
174 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
176 /* Controlling register spills. */
177 #undef TARGET_CLASS_LIKELY_SPILLED_P
178 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
180 /* Passing function arguments. */
181 #undef TARGET_FUNCTION_ARG
182 #define TARGET_FUNCTION_ARG cr16_function_arg
183 #undef TARGET_FUNCTION_ARG_ADVANCE
184 #define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
185 #undef TARGET_RETURN_POPS_ARGS
186 #define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
188 /* Initialize the GCC target structure. */
189 #undef TARGET_FRAME_POINTER_REQUIRED
190 #define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required
191 #undef TARGET_CAN_ELIMINATE
192 #define TARGET_CAN_ELIMINATE cr16_can_eliminate
193 #undef TARGET_LEGITIMIZE_ADDRESS
194 #define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address
195 #undef TARGET_LEGITIMATE_CONSTANT_P
196 #define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p
197 #undef TARGET_LEGITIMATE_ADDRESS_P
198 #define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p
200 /* Returning function value. */
201 #undef TARGET_FUNCTION_VALUE
202 #define TARGET_FUNCTION_VALUE cr16_function_value
203 #undef TARGET_LIBCALL_VALUE
204 #define TARGET_LIBCALL_VALUE cr16_libcall_value
205 #undef TARGET_FUNCTION_VALUE_REGNO_P
206 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
208 /* printing the values. */
209 #undef TARGET_PRINT_OPERAND
210 #define TARGET_PRINT_OPERAND cr16_print_operand
211 #undef TARGET_PRINT_OPERAND_ADDRESS
212 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
214 /* Relative costs of operations. */
215 #undef TARGET_ADDRESS_COST
216 #define TARGET_ADDRESS_COST cr16_address_cost
217 #undef TARGET_REGISTER_MOVE_COST
218 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
219 #undef TARGET_MEMORY_MOVE_COST
220 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
222 /* Table of machine attributes. */
223 static const struct attribute_spec cr16_attribute_table
[] = {
224 /* ISRs have special prologue and epilogue requirements. */
225 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
226 affects_type_identity }. */
227 {"interrupt", 0, 0, false, true, true, NULL
, false},
228 {NULL
, 0, 0, false, false, false, NULL
, false}
231 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
232 .?byte directive along with @c is not understood by assembler.
233 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
234 as TARGET_ASM_ALIGNED_xx_OP. */
235 #undef TARGET_ASM_UNALIGNED_HI_OP
236 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
237 #undef TARGET_ASM_UNALIGNED_SI_OP
238 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
239 #undef TARGET_ASM_UNALIGNED_DI_OP
240 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
242 /* Target hook implementations. */
244 /* Implements hook TARGET_RETURN_IN_MEMORY. */
246 cr16_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
248 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
249 return ((size
== -1) || (size
> 8));
252 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
254 cr16_class_likely_spilled_p (reg_class_t rclass
)
256 if ((rclass
) == SHORT_REGS
|| (rclass
) == DOUBLE_BASE_REGS
257 || (rclass
) == LONG_REGS
|| (rclass
) == GENERAL_REGS
)
264 cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
,
265 tree funtype ATTRIBUTE_UNUSED
,
266 int size ATTRIBUTE_UNUSED
)
271 /* Returns true if data model selected via command line option
272 is same as function argument. */
274 cr16_is_data_model (enum data_model_type model
)
276 return (model
== data_model
);
279 /* Parse relevant options and override. */
281 cr16_override_options (void)
283 /* Disable -fdelete-null-pointer-checks option for CR16 target.
284 Programs which rely on NULL pointer dereferences _not_ halting the
285 program may not work properly with this option. So disable this
287 flag_delete_null_pointer_checks
= 0;
289 /* FIXME: To avoid spill_failure ICE during exception handling,
290 * disable cse_fllow_jumps. The spill error occurs when compiler
291 * can't find a suitable candidate in GENERAL_REGS class to reload
293 * Need to find a better way of avoiding this situation. */
295 flag_cse_follow_jumps
= 0;
297 /* If -fpic option, data_model == DM_FAR. */
298 if (flag_pic
== NEAR_PIC
)
303 /* The only option we want to examine is data model option. */
306 if (strcmp (cr16_data_model
, "medium") == 0)
307 data_model
= DM_DEFAULT
;
308 else if (strcmp (cr16_data_model
, "near") == 0)
309 data_model
= DM_NEAR
;
310 else if (strcmp (cr16_data_model
, "far") == 0)
315 error ("data-model=far not valid for cr16c architecture");
318 error ("invalid data model option -mdata-model=%s", cr16_data_model
);
321 data_model
= DM_DEFAULT
;
324 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
326 cr16_conditional_register_usage (void)
330 fixed_regs
[12] = call_used_regs
[12] = 1;
334 /* Stack layout and calling conventions routines. */
336 /* Return nonzero if the current function being compiled is an interrupt
337 function as specified by the "interrupt" attribute. */
339 cr16_interrupt_function_p (void)
343 attributes
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
344 return (lookup_attribute ("interrupt", attributes
) != NULL_TREE
);
347 /* Compute values for the array current_frame_info.save_regs and the variable
348 current_frame_info.reg_size. The index of current_frame_info.save_regs
349 is numbers of register, each will get 1 if we need to save it in the
350 current function, 0 if not. current_frame_info.reg_size is the total sum
351 of the registers being saved. */
353 cr16_compute_save_regs (void)
357 /* Initialize here so in case the function is no-return it will be -1. */
358 current_frame_info
.last_reg_to_save
= -1;
360 /* Initialize the number of bytes to be saved. */
361 current_frame_info
.reg_size
= 0;
363 /* No need to save any registers if the function never returns. */
364 if (FUNC_IS_NORETURN_P (current_function_decl
) && !MUST_SAVE_REGS_P ())
367 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
369 if (fixed_regs
[regno
])
371 current_frame_info
.save_regs
[regno
] = 0;
375 /* If this reg is used and not call-used (except RA), save it. */
376 if (cr16_interrupt_function_p ())
378 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
379 /* This is a volatile reg in a non-leaf interrupt routine - save
380 it for the sake of its sons. */
381 current_frame_info
.save_regs
[regno
] = 1;
382 else if (df_regs_ever_live_p (regno
))
383 /* This reg is used - save it. */
384 current_frame_info
.save_regs
[regno
] = 1;
386 /* This reg is not used, and is not a volatile - don't save. */
387 current_frame_info
.save_regs
[regno
] = 0;
391 /* If this reg is used and not call-used (except RA), save it. */
392 if (df_regs_ever_live_p (regno
)
393 && (!call_used_regs
[regno
] || regno
== RETURN_ADDRESS_REGNUM
))
394 current_frame_info
.save_regs
[regno
] = 1;
396 current_frame_info
.save_regs
[regno
] = 0;
400 /* Save registers so the exception handler can modify them. */
401 if (crtl
->calls_eh_return
)
407 regno
= EH_RETURN_DATA_REGNO (i
);
408 if (INVALID_REGNUM
== regno
)
410 current_frame_info
.save_regs
[regno
] = 1;
414 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
415 if (current_frame_info
.save_regs
[regno
] == 1)
417 current_frame_info
.last_reg_to_save
= regno
;
418 if (regno
>= CR16_FIRST_DWORD_REGISTER
)
419 current_frame_info
.reg_size
+= CR16_UNITS_PER_DWORD
;
421 current_frame_info
.reg_size
+= UNITS_PER_WORD
;
425 /* Compute the size of the local area and the size to be adjusted by the
426 prologue and epilogue. */
428 cr16_compute_frame (void)
430 /* For aligning the local variables. */
431 int stack_alignment
= STACK_BOUNDARY
/ BITS_PER_UNIT
;
434 /* Padding needed for each element of the frame. */
435 current_frame_info
.var_size
= get_frame_size ();
437 /* Align to the stack alignment. */
438 padding_locals
= current_frame_info
.var_size
% stack_alignment
;
440 padding_locals
= stack_alignment
- padding_locals
;
442 current_frame_info
.var_size
+= padding_locals
;
443 current_frame_info
.total_size
= current_frame_info
.var_size
444 + (ACCUMULATE_OUTGOING_ARGS
445 ? crtl
->outgoing_args_size
: 0);
448 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
450 cr16_initial_elimination_offset (int from
, int to
)
452 /* Compute this since we need to use current_frame_info.reg_size. */
453 cr16_compute_save_regs ();
455 /* Compute this since we need to use current_frame_info.var_size. */
456 cr16_compute_frame ();
458 if (((from
) == FRAME_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
459 return (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0);
460 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == FRAME_POINTER_REGNUM
))
461 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
);
462 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
463 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
464 + (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0));
469 /* Register Usage. */
471 /* Return the class number of the smallest class containing reg number REGNO.
472 This could be a conditional expression or could index an array. */
474 cr16_regno_reg_class (int regno
)
476 if ((regno
>= 0) && (regno
< CR16_FIRST_DWORD_REGISTER
))
479 if ((regno
>= CR16_FIRST_DWORD_REGISTER
) && (regno
< FIRST_PSEUDO_REGISTER
))
485 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
487 cr16_hard_regno_mode_ok (int regno
, machine_mode mode
)
489 if ((GET_MODE_SIZE (mode
) >= 4) && (regno
== 11))
492 if (mode
== DImode
|| mode
== DFmode
)
494 if ((regno
> 8) || (regno
& 1))
500 && ((regno
>= 12) && (GET_MODE_SIZE (mode
) < 4 )))
503 /* CC can only hold CCmode values. */
504 if (GET_MODE_CLASS (mode
) == MODE_CC
)
509 /* Returns register number for function return value.*/
510 static inline unsigned int
511 cr16_ret_register (void)
516 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
518 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED
,
519 int incoming ATTRIBUTE_UNUSED
)
521 return gen_rtx_REG (Pmode
, cr16_ret_register ());
524 /* Returning function value. */
526 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
528 cr16_function_value_regno_p (const unsigned int regno
)
530 return (regno
== cr16_ret_register ());
533 /* Create an RTX representing the place where a
534 library function returns a value of mode MODE. */
536 cr16_libcall_value (machine_mode mode
,
537 const_rtx func ATTRIBUTE_UNUSED
)
539 return gen_rtx_REG (mode
, cr16_ret_register ());
542 /* Create an RTX representing the place where a
543 function returns a value of data type VALTYPE. */
545 cr16_function_value (const_tree type
,
546 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
547 bool outgoing ATTRIBUTE_UNUSED
)
549 return gen_rtx_REG (TYPE_MODE (type
), cr16_ret_register ());
552 /* Passing function arguments. */
554 /* If enough param regs are available for passing the param of type TYPE return
555 the number of registers needed else 0. */
557 enough_regs_for_param (CUMULATIVE_ARGS
* cum
, const_tree type
,
564 type_size
= GET_MODE_BITSIZE (mode
);
566 type_size
= int_size_in_bytes (type
) * BITS_PER_UNIT
;
568 remaining_size
= BITS_PER_WORD
* (MAX_REG_FOR_PASSING_ARGS
569 - (MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) +
572 /* Any variable which is too big to pass in two registers, will pass on
574 if ((remaining_size
>= type_size
) && (type_size
<= 2 * BITS_PER_WORD
))
575 return (type_size
+ BITS_PER_WORD
- 1) / BITS_PER_WORD
;
580 /* Implements the macro FUNCTION_ARG defined in cr16.h. */
582 cr16_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
583 const_tree type
, bool named ATTRIBUTE_UNUSED
)
585 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
586 cum
->last_parm_in_reg
= 0;
588 /* function_arg () is called with this type just after all the args have
589 had their registers assigned. The rtx that function_arg returns from
590 this type is supposed to pass to 'gen_call' but currently it is not
591 implemented (see macro GEN_CALL). */
592 if (type
== void_type_node
)
595 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
600 /* Enable structures that need padding bytes at the end to pass to a
601 function in registers. */
602 if (enough_regs_for_param (cum
, type
, mode
) != 0)
604 cum
->last_parm_in_reg
= 1;
605 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
609 if ((MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) > MAX_REG_FOR_PASSING_ARGS
)
613 if (enough_regs_for_param (cum
, type
, mode
) != 0)
615 cum
->last_parm_in_reg
= 1;
616 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
623 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
625 cr16_init_cumulative_args (CUMULATIVE_ARGS
* cum
, tree fntype
,
626 rtx libfunc ATTRIBUTE_UNUSED
)
628 tree param
, next_param
;
632 /* Determine if this function has variable arguments. This is indicated by
633 the last argument being 'void_type_mode' if there are no variable
634 arguments. Change here for a different vararg. */
635 for (param
= (fntype
) ? TYPE_ARG_TYPES (fntype
) : 0;
636 param
!= NULL_TREE
; param
= next_param
)
638 next_param
= TREE_CHAIN (param
);
639 if ((next_param
== NULL_TREE
) && (TREE_VALUE (param
) != void_type_node
))
647 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
649 cr16_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
650 const_tree type
, bool named ATTRIBUTE_UNUSED
)
652 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
654 /* l holds the number of registers required. */
655 int l
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
657 /* If the parameter isn't passed on a register don't advance cum. */
658 if (!cum
->last_parm_in_reg
)
661 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
664 if ((mode
== SImode
) || (mode
== HImode
)
665 || (mode
== QImode
) || (mode
== DImode
))
672 else if ((mode
== SFmode
) || (mode
== DFmode
))
674 else if ((mode
) == BLKmode
)
676 if ((l
= enough_regs_for_param (cum
, type
, mode
)) != 0)
682 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
683 Return nonzero if N is a register used for passing parameters. */
685 cr16_function_arg_regno_p (int n
)
687 return ((n
<= MAX_REG_FOR_PASSING_ARGS
) && (n
>= MIN_REG_FOR_PASSING_ARGS
));
691 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
692 defined in cr16.h. */
694 /* Helper function to check if is a valid base register that can
697 cr16_addr_reg_p (rtx addr_reg
)
701 if (REG_P (addr_reg
))
703 else if ((GET_CODE (addr_reg
) == SUBREG
)
704 && REG_P (SUBREG_REG (addr_reg
))
705 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg
)))
707 reg
= SUBREG_REG (addr_reg
);
711 if (GET_MODE (reg
) != Pmode
)
717 /* Helper functions: Created specifically for decomposing operand of CONST
718 Recursively look into expression x for code or data symbol.
719 The function expects the expression to contain combination of
720 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
721 LABEL_REF, CONST_INT, (PLUS or MINUS)
724 All other combinations will result in code = -1 and data = ILLEGAL_DM
726 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
727 0 DM_FAR SYMBOL_REF was found and it was far data reference.
728 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
729 1 ILLEGAL_DM LABEL_REF was found.
730 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
732 cr16_decompose_const (rtx x
, int *code
, enum data_model_type
*data
,
737 switch (GET_CODE (x
))
740 *code
= SYMBOL_REF_FUNCTION_P (x
) ? 2 : 0;
741 /* 2 indicates func sym. */
744 if (CR16_TARGET_DATA_NEAR
)
746 else if (CR16_TARGET_DATA_MEDIUM
)
748 else if (CR16_TARGET_DATA_FAR
)
751 /* This will be used only for printing
752 the qualifier. This call is (may be)
753 made by cr16_print_operand_address. */
756 /* This call is (may be) made by
757 cr16_legitimate_address_p. */
764 /* 1 - indicates non-function symbol. */
770 /* Look into the tree nodes. */
771 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
772 cr16_decompose_const (XEXP (x
, 1), code
, data
, treat_as_const
);
773 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
774 cr16_decompose_const (XEXP (x
, 0), code
, data
, treat_as_const
);
782 This function decomposes the address returns the type of address
783 as defined in enum cr16_addrtype. It also fills the parameter *out.
784 The decomposed address can be used for two purposes. One to
785 check if the address is valid and second to print the address
788 Following tables list valid address supported in CR16C/C+ architectures.
790 aN : Absoulte address N-bit address
791 R : One 16-bit register
792 RP : Consecutive two 16-bit registers or one 32-bit register
793 I : One 32-bit register
794 dispN : Signed displacement of N-bits
796 ----Code addresses----
798 disp9 : CR16_ABSOLUTE (disp)
799 disp17 : CR16_ABSOLUTE (disp)
800 disp25 : CR16_ABSOLUTE (disp)
801 RP + disp25 : CR16_REGP_REL (base, disp)
804 RP : CR16_REGP_REL (base, disp=0)
805 a24 : CR16_ABSOLUTE (disp)
807 ----Data addresses----
808 a20 : CR16_ABSOLUTE (disp) near (1M)
809 a24 : CR16_ABSOLUTE (disp) medium (16M)
810 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
811 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
812 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
813 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
814 I : *** Valid but port does not support this
815 I + a20 : *** Valid but port does not support this
816 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
817 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
819 Decomposing Data model in case of absolute address.
821 Target Option Address type Resultant Data ref type
822 ---------------------- ------------ -----------------------
823 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
824 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
825 CR16_TARGET_MODEL_NEAR ABS24 Invalid
826 CR16_TARGET_MODEL_NEAR IMM32 Invalid
828 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
829 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
830 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
831 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
833 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
834 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
835 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
836 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
838 cr16_decompose_address (rtx addr
, struct cr16_address
*out
,
839 bool debug_print
, bool treat_as_const
)
841 rtx base
= NULL_RTX
, disp
= NULL_RTX
, index
= NULL_RTX
;
842 enum data_model_type data
= ILLEGAL_DM
;
844 enum cr16_addrtype retval
= CR16_INVALID
;
846 switch (GET_CODE (addr
))
849 /* Absolute address (known at compile time). */
852 fprintf (stderr
, "\ncode:%d", code
);
857 fprintf (stderr
, "\ndisp:");
861 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
865 fprintf (stderr
, "\ndata:%d", data
);
866 retval
= CR16_ABSOLUTE
;
868 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 24))
870 if (!CR16_TARGET_DATA_NEAR
)
874 fprintf (stderr
, "\ndata:%d", data
);
875 retval
= CR16_ABSOLUTE
;
878 return CR16_INVALID
; /* ABS24 is not support in NEAR model. */
885 /* A CONST is an expression of PLUS or MINUS with
886 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
887 result of assembly-time arithmetic computation. */
888 retval
= CR16_ABSOLUTE
;
890 /* Call the helper function to check the validity. */
891 cr16_decompose_const (XEXP (addr
, 0), &code
, &data
, treat_as_const
);
892 if ((code
== 0) && (data
== ILLEGAL_DM
))
893 /* CONST is not valid code or data address. */
897 fprintf (stderr
, "\ndisp:");
899 fprintf (stderr
, "\ncode:%d", code
);
900 fprintf (stderr
, "\ndata:%d", data
);
905 retval
= CR16_ABSOLUTE
;
907 /* 1 - indicates non-function symbol. */
911 fprintf (stderr
, "\ndisp:");
913 fprintf (stderr
, "\ncode:%d", code
);
918 /* Absolute address (known at link time). */
919 retval
= CR16_ABSOLUTE
;
921 /* This is a code address if symbol_ref is a function. */
922 /* 2 indicates func sym. */
923 code
= SYMBOL_REF_FUNCTION_P (addr
) ? 2 : 0;
926 fprintf (stderr
, "\ndisp:");
928 fprintf (stderr
, "\ncode:%d", code
);
930 /* If not function ref then check if valid data ref. */
933 if (CR16_TARGET_DATA_NEAR
)
935 else if (CR16_TARGET_DATA_MEDIUM
)
937 else if (CR16_TARGET_DATA_FAR
)
940 /* This will be used only for printing the
941 qualifier. This call is (may be) made
942 by cr16_print_operand_address. */
945 /* This call is (may be) made by
946 cr16_legitimate_address_p. */
953 fprintf (stderr
, "\ndata:%d", data
);
958 /* Register relative address. */
959 /* Assume REG fits in a single register. */
960 retval
= CR16_REG_REL
;
961 if (GET_MODE_BITSIZE (GET_MODE (addr
)) > BITS_PER_WORD
)
962 if (!LONG_REG_P (REGNO (addr
)))
963 /* REG will result in reg pair. */
964 retval
= CR16_REGP_REL
;
968 fprintf (stderr
, "\nbase:");
974 switch (GET_CODE (XEXP (addr
, 0)))
979 /* All Reg relative addresses having a displacement needs
980 to fit in 20-bits. */
981 disp
= XEXP (addr
, 1);
984 fprintf (stderr
, "\ndisp:");
987 switch (GET_CODE (XEXP (addr
, 1)))
990 /* Shall fit in 20-bits. */
991 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
995 fprintf (stderr
, "\ncode:%d", code
);
999 switch (XINT (XEXP (addr
, 1), 1))
1001 case UNSPEC_LIBRARY_OFFSET
:
1010 /* This is also a valid expression for address.
1011 However, we cannot ascertain if the resultant
1012 displacement will be valid 20-bit value. Therefore,
1013 lets not allow such an expression for now. This will
1014 be updated when we find a way to validate this
1015 expression as legitimate address.
1016 Till then fall through CR16_INVALID. */
1018 return CR16_INVALID
;
1021 /* Now check if REG can fit into single or pair regs. */
1022 retval
= CR16_REG_REL
;
1023 base
= XEXP (addr
, 0);
1026 fprintf (stderr
, "\nbase:");
1029 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr
, 0)))) > BITS_PER_WORD
)
1031 if (!LONG_REG_P (REGNO ((XEXP (addr
, 0)))))
1032 /* REG will result in reg pair. */
1033 retval
= CR16_REGP_REL
;
1047 Check if the operand 1 is valid index register. */
1050 fprintf (stderr
, "\ndata:%d", data
);
1051 switch (GET_CODE (XEXP (addr
, 1)))
1055 if (!REG_OK_FOR_INDEX_P (XEXP (addr
, 1)))
1056 return CR16_INVALID
;
1057 /* OK. REG is a valid index register. */
1058 index
= XEXP (addr
, 1);
1061 fprintf (stderr
, "\nindex:");
1066 return CR16_INVALID
;
1068 /* Check if operand 0 of operand 0 is REGP. */
1069 switch (GET_CODE (XEXP (XEXP (addr
, 0), 0)))
1073 /* Now check if REG is a REGP and not in LONG regs. */
1074 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr
, 0), 0)))
1077 if (REGNO (XEXP (XEXP (addr
, 0), 0))
1078 >= CR16_FIRST_DWORD_REGISTER
)
1079 return CR16_INVALID
;
1080 base
= XEXP (XEXP (addr
, 0), 0);
1083 fprintf (stderr
, "\nbase:");
1088 return CR16_INVALID
;
1091 return CR16_INVALID
;
1093 /* Now check if the operand 1 of operand 0 is const_int. */
1094 if (GET_CODE (XEXP (XEXP (addr
, 0), 1)) == CONST_INT
)
1096 disp
= XEXP (XEXP (addr
, 0), 1);
1099 fprintf (stderr
, "\ndisp:");
1102 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
1103 return CR16_INVALID
;
1106 return CR16_INVALID
;
1107 retval
= CR16_INDEX_REGP_REL
;
1110 return CR16_INVALID
;
1115 return CR16_INVALID
;
1118 /* Check if the base and index registers are valid. */
1119 if (base
&& !(cr16_addr_reg_p (base
)))
1120 return CR16_INVALID
;
1121 if (base
&& !(CR16_REG_OK_FOR_BASE_P (base
)))
1122 return CR16_INVALID
;
1123 if (index
&& !(REG_OK_FOR_INDEX_P (index
)))
1124 return CR16_INVALID
;
1126 /* Write the decomposition to out parameter. */
1136 /* Return non-zero value if 'x' is legitimate PIC operand
1137 when generating PIC code. */
1139 legitimate_pic_operand_p (rtx x
)
1141 switch (GET_CODE (x
))
1150 /* REVISIT: Use something like symbol_referenced_p. */
1151 if (GET_CODE (XEXP (x
, 0)) == PLUS
1152 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
1153 || GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
)
1154 && (GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
))
1158 return legitimate_pic_operand_p (XEXP (x
, 0));
1166 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
1168 Input Output (-f pic) Output (-f PIC)
1171 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
1173 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
1175 NOTE: @BRO is added using unspec:BRO
1176 NOTE: @GOT is added using unspec:GOT. */
1178 legitimize_pic_address (rtx orig
, machine_mode mode ATTRIBUTE_UNUSED
,
1181 /* First handle a simple SYMBOL_REF or LABEL_REF. */
1182 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1185 reg
= gen_reg_rtx (Pmode
);
1187 if (flag_pic
== NEAR_PIC
)
1189 /* Unspec to handle -fpic option. */
1190 emit_insn (gen_unspec_bro_addr (reg
, orig
));
1191 emit_insn (gen_addsi3 (reg
, reg
, pic_offset_table_rtx
));
1193 else if (flag_pic
== FAR_PIC
)
1195 /* Unspec to handle -fPIC option. */
1196 emit_insn (gen_unspec_got_addr (reg
, orig
));
1200 else if (GET_CODE (orig
) == CONST
)
1202 /* To handle (symbol + offset). */
1205 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1206 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1211 gcc_assert (can_create_pseudo_p ());
1212 reg
= gen_reg_rtx (Pmode
);
1215 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
1217 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1218 offset
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1219 base
== reg
? 0 : reg
);
1221 /* REVISIT: Optimize for const-offsets. */
1222 emit_insn (gen_addsi3 (reg
, base
, offset
));
1229 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
1231 cr16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1232 rtx addr
, bool strict
)
1234 enum cr16_addrtype addrtype
;
1235 struct cr16_address address
;
1237 if (TARGET_DEBUG_ADDR
)
1240 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
1241 GET_MODE_NAME (mode
), strict
);
1244 addrtype
= cr16_decompose_address (addr
, &address
,
1245 (TARGET_DEBUG_ADDR
? 1 : 0), FALSE
);
1247 if (TARGET_DEBUG_ADDR
)
1249 const char *typestr
;
1254 typestr
= "invalid";
1257 typestr
= "absolute";
1260 typestr
= "register relative";
1263 typestr
= "register pair relative";
1265 case CR16_INDEX_REGP_REL
:
1266 typestr
= "index + register pair relative";
1271 fprintf (stderr
, "\ncr16 address type: %s\n", typestr
);
1274 if (addrtype
== CR16_INVALID
)
1280 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address
.base
), mode
))
1282 if (TARGET_DEBUG_ADDR
)
1283 fprintf (stderr
, "base register not strict\n");
1286 if (address
.index
&& !REGNO_OK_FOR_INDEX_P (REGNO (address
.index
)))
1288 if (TARGET_DEBUG_ADDR
)
1289 fprintf (stderr
, "index register not strict\n");
1294 /* Return true if addressing mode is register relative. */
1297 if (addrtype
== CR16_REG_REL
|| addrtype
== CR16_REGP_REL
)
1306 /* Routines to compute costs. */
1308 /* Return cost of the memory address x. */
1310 cr16_address_cost (rtx addr
, machine_mode mode ATTRIBUTE_UNUSED
,
1311 addr_space_t as ATTRIBUTE_UNUSED
,
1312 bool speed ATTRIBUTE_UNUSED
)
1314 enum cr16_addrtype addrtype
;
1315 struct cr16_address address
;
1318 addrtype
= cr16_decompose_address (addr
, &address
, 0, FALSE
);
1320 gcc_assert (addrtype
!= CR16_INVALID
);
1322 /* CR16_ABSOLUTE : 3
1323 CR16_REG_REL (disp !=0) : 4
1324 CR16_REG_REL (disp ==0) : 5
1325 CR16_REGP_REL (disp !=0) : 6
1326 CR16_REGP_REL (disp ==0) : 7
1327 CR16_INDEX_REGP_REL (disp !=0) : 8
1328 CR16_INDEX_REGP_REL (disp ==0) : 9. */
1342 case CR16_INDEX_REGP_REL
:
1350 if (TARGET_DEBUG_ADDR
)
1352 fprintf (stderr
, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost
);
1360 /* Implement `TARGET_REGISTER_MOVE_COST'. */
1362 cr16_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED
,
1363 reg_class_t from ATTRIBUTE_UNUSED
, reg_class_t to
)
1365 return (to
!= GENERAL_REGS
? 8 : 2);
1368 /* Implement `TARGET_MEMORY_MOVE_COST'. */
1370 /* Return the cost of moving data of mode MODE between a register of class
1371 CLASS and memory; IN is zero if the value is to be written to memory,
1372 nonzero if it is to be read in. This cost is relative to those in
1373 REGISTER_MOVE_COST. */
1375 cr16_memory_move_cost (machine_mode mode
,
1376 reg_class_t rclass ATTRIBUTE_UNUSED
,
1377 bool in ATTRIBUTE_UNUSED
)
1379 /* One LD or ST takes twice the time of a simple reg-reg move. */
1380 if (reg_classes_intersect_p (rclass
, GENERAL_REGS
))
1381 return (4 * HARD_REGNO_NREGS (0, mode
));
1386 /* Instruction output. */
1388 /* Check if a const_double is ok for cr16 store-immediate instructions. */
1390 cr16_const_double_ok (rtx op
)
1392 if (GET_MODE (op
) == SFmode
)
1396 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1397 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1398 return UNSIGNED_INT_FITS_N_BITS (l
, 4) ? 1 : 0;
1401 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op
), 4)) &&
1402 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op
), 4))) ? 1 : 0;
1405 /* Returns bit position of first 0 or 1 bit.
1406 It is safe to assume val as 16-bit wide. */
1408 cr16_operand_bit_pos (int val
, int bitval
)
1414 for (i
= 0; i
< 16; i
++)
1420 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
1422 cr16_print_operand (FILE * file
, rtx x
, int code
)
1424 int ptr_dereference
= 0;
1430 const char *cr16_cmp_str
;
1431 switch (GET_CODE (x
))
1433 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
1434 -> swap all non symmetric ops. */
1436 cr16_cmp_str
= "eq";
1439 cr16_cmp_str
= "ne";
1442 cr16_cmp_str
= "lt";
1445 cr16_cmp_str
= "lo";
1448 cr16_cmp_str
= "gt";
1451 cr16_cmp_str
= "hi";
1454 cr16_cmp_str
= "le";
1457 cr16_cmp_str
= "ls";
1460 cr16_cmp_str
= "ge";
1463 cr16_cmp_str
= "hs";
1468 fprintf (file
, "%s", cr16_cmp_str
);
1476 if (GET_CODE (x
) == REG
)
1478 /* For Push instructions, we should not print register pairs. */
1479 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1485 /* Print the immediate address for bal
1486 'b' is used instead of 'a' to avoid compiler calling
1487 the GO_IF_LEGITIMATE_ADDRESS which cannot
1488 perform checks on const_int code addresses as it
1489 assumes all const_int are data addresses. */
1490 fprintf (file
, "0x%lx", INTVAL (x
));
1494 /* Print bit position of first 0. */
1495 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 0));
1499 /* Print bit position of first 1. */
1500 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 1));
1503 /* 'g' is used for implicit mem: dereference. */
1504 ptr_dereference
= 1;
1508 switch (GET_CODE (x
))
1511 if (GET_MODE_BITSIZE (GET_MODE (x
)) > BITS_PER_WORD
)
1513 if (LONG_REG_P (REGNO (x
)))
1514 fprintf (file
, "(%s)", reg_names
[REGNO (x
)]);
1516 fprintf (file
, "(%s,%s)", reg_names
[REGNO (x
) + 1],
1517 reg_names
[REGNO (x
)]);
1520 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1524 output_address (XEXP (x
, 0));
1532 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1533 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1535 fprintf (file
, "$0x%lx", l
);
1540 fprintf (file
, "$%ld", INTVAL (x
));
1544 switch (XINT (x
, 1))
1552 if (!ptr_dereference
)
1556 cr16_print_operand_address (file
, x
);
1560 output_operand_lossage ("invalid %%xn code");
1566 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
1569 cr16_print_operand_address (FILE * file
, rtx addr
)
1571 enum cr16_addrtype addrtype
;
1572 struct cr16_address address
;
1574 /* Decompose the address. Also ask it to treat address as constant. */
1575 addrtype
= cr16_decompose_address (addr
, &address
, 0, TRUE
);
1577 if (address
.disp
&& GET_CODE (address
.disp
) == UNSPEC
)
1587 if (GET_CODE (address
.disp
) == UNSPEC
)
1588 cr16_print_operand (file
, address
.disp
, 0);
1590 output_addr_const (file
, address
.disp
);
1593 fprintf (file
, "0");
1594 fprintf (file
, "(%s)", reg_names
[REGNO (address
.base
)]);
1599 output_addr_const (file
, address
.disp
);
1601 fprintf (file
, "0");
1604 case CR16_INDEX_REGP_REL
:
1605 fprintf (file
, "[%s]", reg_names
[REGNO (address
.index
)]);
1610 if (GET_CODE (address
.disp
) == UNSPEC
)
1611 cr16_print_operand (file
, address
.disp
, 0);
1613 output_addr_const (file
, address
.disp
);
1616 fprintf (file
, "0");
1617 fprintf (file
, "(%s,%s)", reg_names
[REGNO (address
.base
) + 1],
1618 reg_names
[REGNO (address
.base
)]);
1624 /* Add qualifiers to the address expression that was just printed. */
1625 if (flag_pic
< NEAR_PIC
&& address
.code
== 0)
1627 if (address
.data
== DM_FAR
)
1628 /* Addr contains SYMBOL_REF & far data ptr. */
1629 fprintf (file
, "@l");
1630 else if (address
.data
== DM_DEFAULT
)
1631 /* Addr contains SYMBOL_REF & medium data ptr. */
1632 fprintf (file
, "@m");
1633 /* Addr contains SYMBOL_REF & medium data ptr. */
1634 else if (address
.data
== DM_NEAR
)
1635 /* Addr contains SYMBOL_REF & near data ptr. */
1636 fprintf (file
, "@s");
1638 else if (flag_pic
== NEAR_PIC
1639 && (address
.code
== 0) && (address
.data
== DM_FAR
1640 || address
.data
== DM_DEFAULT
1641 || address
.data
== DM_NEAR
))
1643 fprintf (file
, "@l");
1645 else if (flag_pic
== NEAR_PIC
&& address
.code
== 2)
1647 fprintf (file
, "pic");
1649 else if (flag_pic
== NEAR_PIC
&& address
.code
== 1)
1651 fprintf (file
, "@cpic");
1654 else if (flag_pic
== FAR_PIC
&& address
.code
== 2)
1656 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
1657 address ! GOTc tells assembler this symbol is a text-address
1658 This needs to be fixed in such a way that this offset is done
1659 only in the case where an address is being used for indirect jump
1660 or call. Determining the potential usage of loadd is of course not
1661 possible always. Eventually, this has to be fixed in the
1663 fprintf (file
, "GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1665 else if (flag_pic
== FAR_PIC
&& address
.code
== 1)
1667 fprintf (file
, "@cGOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1670 else if (flag_pic
== FAR_PIC
&&
1671 (address
.data
== DM_FAR
|| address
.data
== DM_DEFAULT
1672 || address
.data
== DM_NEAR
))
1674 fprintf (file
, "@GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1678 /* Machine description helper functions. */
1680 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
1681 When push_or_pop is zero -> string for push instructions of prologue.
1682 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1683 Relies on the assumptions:
1684 1. RA is the last register to be saved.
1685 2. The maximal value of the counter is MAX_COUNT. */
1687 cr16_prepare_push_pop_string (int push_or_pop
)
1689 /* j is the number of registers being saved, takes care that there won't be
1690 more than 8 in one push/pop instruction. */
1692 /* For the register mask string. */
1693 static char one_inst_str
[50];
1695 /* i is the index of current_frame_info.save_regs[], going from 0 until
1696 current_frame_info.last_reg_to_save. */
1702 /* For reversing on the push instructions if there are more than one. */
1705 return_str
= (char *) xmalloc (160);
1706 temp_str
= (char *) xmalloc (160);
1709 memset (return_str
, 0, 3);
1712 while (i
<= current_frame_info
.last_reg_to_save
)
1714 /* Prepare mask for one instruction. */
1715 one_inst_str
[0] = 0;
1717 /* To count number of words in one instruction. */
1721 while ((word_cnt
< MAX_COUNT
)
1722 && (i
<= current_frame_info
.last_reg_to_save
))
1724 /* For each non consecutive save register,
1725 a new instruction shall be generated. */
1726 if (!current_frame_info
.save_regs
[i
])
1728 /* Move to next reg and break. */
1733 if (i
== RETURN_ADDRESS_REGNUM
)
1737 /* Check especially if adding 2 does not cross the MAX_COUNT. */
1738 if ((word_cnt
+ ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2))
1741 /* Increase word count by 2 for long registers except RA. */
1742 word_cnt
+= ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2);
1747 /* No need to generate any instruction as
1748 no register or RA needs to be saved. */
1749 if ((word_cnt
== 0) && (print_ra
== 0))
1752 /* Now prepare the instruction operands. */
1755 sprintf (one_inst_str
, "$%d, %s", word_cnt
, reg_names
[start_reg
]);
1757 strcat (one_inst_str
, ", ra");
1760 strcat (one_inst_str
, "ra");
1762 if (push_or_pop
== 1)
1764 /* Pop instruction. */
1765 if (print_ra
&& !cr16_interrupt_function_p ()
1766 && !crtl
->calls_eh_return
)
1767 /* Print popret if RA is saved and its not a interrupt
1769 strcpy (temp_str
, "\n\tpopret\t");
1771 strcpy (temp_str
, "\n\tpop\t");
1773 strcat (temp_str
, one_inst_str
);
1775 /* Add the pop instruction list. */
1776 strcat (return_str
, temp_str
);
1780 /* Push instruction. */
1781 strcpy (temp_str
, "\n\tpush\t");
1782 strcat (temp_str
, one_inst_str
);
1784 /* We need to reverse the order of the instructions if there
1785 are more than one. (since the pop will not be reversed in
1787 strcat (temp_str
, return_str
);
1788 strcpy (return_str
, temp_str
);
1792 if (push_or_pop
== 1)
1795 if (cr16_interrupt_function_p ())
1796 strcat (return_str
, "\n\tretx\n");
1797 else if (crtl
->calls_eh_return
)
1799 /* Add stack adjustment before returning to exception handler
1800 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
1801 strcat (return_str
, "\n\taddd\t (r5, r4), (sp)\t\n");
1802 strcat (return_str
, "\n\tjump\t (ra)\n");
1804 /* But before anything else, undo the adjustment addition done in
1805 cr16_expand_epilogue (). */
1806 strcpy (temp_str
, "\n\tsubd\t (r5, r4), (sp)\t\n");
1807 strcat (temp_str
, return_str
);
1808 strcpy (return_str
, temp_str
);
1810 else if (!FUNC_IS_NORETURN_P (current_function_decl
)
1811 && !(current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]))
1812 strcat (return_str
, "\n\tjump\t (ra)\n");
1815 /* Skip the newline and the tab in the start of return_str. */
1821 /* Generate DWARF2 annotation for multi-push instruction. */
1823 cr16_create_dwarf_for_multi_push (rtx insn
)
1825 rtx dwarf
, reg
, tmp
;
1826 int i
, j
, from
, to
, word_cnt
, dwarf_par_index
, inc
;
1828 int num_regs
= 0, offset
= 0, split_here
= 0, total_push_bytes
= 0;
1830 for (i
= 0; i
<= current_frame_info
.last_reg_to_save
; ++i
)
1832 if (current_frame_info
.save_regs
[i
])
1835 if (i
< CR16_FIRST_DWORD_REGISTER
)
1836 total_push_bytes
+= 2;
1838 total_push_bytes
+= 4;
1845 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (num_regs
+ 1));
1846 dwarf_par_index
= num_regs
;
1848 from
= current_frame_info
.last_reg_to_save
+ 1;
1849 to
= current_frame_info
.last_reg_to_save
;
1852 for (i
= current_frame_info
.last_reg_to_save
; i
>= 0;)
1854 if (!current_frame_info
.save_regs
[i
] || 0 == i
|| split_here
)
1856 /* This block of regs is pushed in one instruction. */
1857 if (0 == i
&& current_frame_info
.save_regs
[i
])
1860 for (j
= to
; j
>= from
; --j
)
1862 if (j
< CR16_FIRST_DWORD_REGISTER
)
1872 reg
= gen_rtx_REG (mode
, j
);
1874 tmp
= gen_rtx_SET (gen_frame_mem (mode
,
1876 (Pmode
, stack_pointer_rtx
,
1877 total_push_bytes
- offset
)),
1879 RTX_FRAME_RELATED_P (tmp
) = 1;
1880 XVECEXP (dwarf
, 0, dwarf_par_index
--) = tmp
;
1889 if (i
!= RETURN_ADDRESS_REGNUM
)
1891 inc
= (i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2;
1892 if (word_cnt
+ inc
>= MAX_COUNT
|| FRAME_POINTER_REGNUM
== i
)
1904 tmp
= gen_rtx_SET (stack_pointer_rtx
,
1905 gen_rtx_PLUS (SImode
, stack_pointer_rtx
,
1906 GEN_INT (-offset
)));
1907 RTX_FRAME_RELATED_P (tmp
) = 1;
1908 XVECEXP (dwarf
, 0, 0) = tmp
;
1910 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, dwarf
);
1914 CompactRISC CR16 Architecture stack layout:
1916 0 +---------------------
1921 +==================== Sp (x) = Ap (x+1)
1922 A | Args for functions
1923 | | called by X and Dynamically
1924 | | Dynamic allocations allocated and
1925 | | (alloca, variable deallocated
1926 Stack | length arrays).
1927 grows +-------------------- Fp (x)
1928 down| | Local variables of X
1929 ward| +--------------------
1930 | | Regs saved for X-1
1931 | +==================== Sp (x-1) = Ap (x)
1934 +-------------------- Fp (x-1)
1940 cr16_expand_prologue (void)
1944 cr16_compute_frame ();
1945 cr16_compute_save_regs ();
1947 /* If there is no need in push and adjustment to sp, return. */
1948 if ((current_frame_info
.total_size
+ current_frame_info
.reg_size
) == 0)
1951 if (current_frame_info
.last_reg_to_save
!= -1)
1953 /* If there are registers to push. */
1954 insn
= emit_insn (gen_push_for_prologue
1955 (GEN_INT (current_frame_info
.reg_size
)));
1956 cr16_create_dwarf_for_multi_push (insn
);
1957 RTX_FRAME_RELATED_P (insn
) = 1;
1961 if (current_frame_info
.total_size
> 0)
1963 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1964 GEN_INT (-current_frame_info
.total_size
)));
1965 RTX_FRAME_RELATED_P (insn
) = 1;
1968 if (frame_pointer_needed
)
1970 /* Initialize the frame pointer with the value of the stack pointer
1971 pointing now to the locals. */
1972 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1976 /* Generate insn that updates the stack for local variables and padding
1977 for registers we save. - Generate the appropriate return insn. */
1979 cr16_expand_epilogue (void)
1983 /* Nonzero if we need to return and pop only RA. This will generate a
1984 different insn. This differentiate is for the peepholes for call as
1985 last statement in function. */
1986 int only_popret_RA
= (current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]
1987 && (current_frame_info
.reg_size
1988 == CR16_UNITS_PER_DWORD
));
1990 if (frame_pointer_needed
)
1992 /* Restore the stack pointer with the frame pointers value. */
1993 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
1996 if (current_frame_info
.total_size
> 0)
1998 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1999 GEN_INT (current_frame_info
.total_size
)));
2000 RTX_FRAME_RELATED_P (insn
) = 1;
2003 if (crtl
->calls_eh_return
)
2005 /* Add this here so that (r5, r4) is actually loaded with the adjustment
2006 value; otherwise, the load might be optimized away...
2007 NOTE: remember to subtract the adjustment before popping the regs
2008 and add it back before returning. */
2009 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
2010 EH_RETURN_STACKADJ_RTX
));
2013 if (cr16_interrupt_function_p ())
2015 insn
= emit_jump_insn (gen_interrupt_return ());
2016 RTX_FRAME_RELATED_P (insn
) = 1;
2018 else if (crtl
->calls_eh_return
)
2020 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
2021 insn
= emit_jump_insn (gen_pop_and_popret_return
2022 (GEN_INT (current_frame_info
.reg_size
)));
2023 RTX_FRAME_RELATED_P (insn
) = 1;
2025 else if (current_frame_info
.last_reg_to_save
== -1)
2026 /* Nothing to pop. */
2027 /* Don't output jump for interrupt routine, only retx. */
2028 emit_jump_insn (gen_jump_return ());
2029 else if (only_popret_RA
)
2031 insn
= emit_jump_insn (gen_popret_RA_return ());
2032 RTX_FRAME_RELATED_P (insn
) = 1;
2036 insn
= emit_jump_insn (gen_pop_and_popret_return
2037 (GEN_INT (current_frame_info
.reg_size
)));
2038 RTX_FRAME_RELATED_P (insn
) = 1;
2042 /* Implements FRAME_POINTER_REQUIRED. */
2044 cr16_frame_pointer_required (void)
2046 return (cfun
->calls_alloca
|| crtl
->calls_eh_return
2047 || cfun
->has_nonlocal_label
|| crtl
->calls_eh_return
);
2051 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
2053 return (to
== STACK_POINTER_REGNUM
? !frame_pointer_needed
: true);
2057 /* A C compound statement that attempts to replace X with
2058 a valid memory address for an operand of mode MODE. WIN
2059 will be a C statement label elsewhere in the code.
2060 X will always be the result of a call to break_out_memory_refs (),
2061 and OLDX will be the operand that was given to that function to
2063 The code generated by this macro should not alter the
2064 substructure of X. If it transforms X into a more legitimate form,
2065 it should assign X (which will always be a C variable) a new value. */
2067 cr16_legitimize_address (rtx x
, rtx orig_x ATTRIBUTE_UNUSED
,
2068 machine_mode mode ATTRIBUTE_UNUSED
)
2071 return legitimize_pic_address (orig_x
, mode
, NULL_RTX
);
2076 /* Implement TARGET_LEGITIMATE_CONSTANT_P
2077 Nonzero if X is a legitimate constant for an immediate
2078 operand on the target machine. You can assume that X
2079 satisfies CONSTANT_P. In cr16c treat legitimize float
2080 constant as an immediate operand. */
2082 cr16_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
,
2083 rtx x ATTRIBUTE_UNUSED
)
2089 notice_update_cc (rtx exp
)
2091 if (GET_CODE (exp
) == SET
)
2093 /* Jumps do not alter the cc's. */
2094 if (SET_DEST (exp
) == pc_rtx
)
2097 /* Moving register or memory into a register:
2098 it doesn't alter the cc's, but it might invalidate
2099 the RTX's which we remember the cc's came from.
2100 (Note that moving a constant 0 or 1 MAY set the cc's). */
2101 if (REG_P (SET_DEST (exp
))
2102 && (REG_P (SET_SRC (exp
)) || GET_CODE (SET_SRC (exp
)) == MEM
))
2107 /* Moving register into memory doesn't alter the cc's.
2108 It may invalidate the RTX's which we remember the cc's came from. */
2109 if (GET_CODE (SET_DEST (exp
)) == MEM
&& REG_P (SET_SRC (exp
)))
2120 cr16_unwind_word_mode (void)
2125 /* Helper function for md file. This function is used to emit arithmetic
2126 DI instructions. The argument "num" decides which instruction to be
2129 cr16_emit_add_sub_di (rtx
*operands
, enum rtx_code code
)
2135 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2136 hi0_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 4);
2137 hi1_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 6);
2139 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2140 hi0_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 4);
2141 hi1_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 6);
2147 output_asm_insn ("addd\t%1, %0", lo_op
) ;
2148 output_asm_insn ("addcw\t%1, %0", hi0_op
) ;
2149 output_asm_insn ("addcw\t%1, %0", hi1_op
) ;
2154 output_asm_insn ("subd\t%1, %0", lo_op
) ;
2155 output_asm_insn ("subcw\t%1, %0", hi0_op
) ;
2156 output_asm_insn ("subcw\t%1, %0", hi1_op
) ;
2167 /* Helper function for md file. This function is used to emit logical
2168 DI instructions. The argument "num" decides which instruction to be
2171 cr16_emit_logical_di (rtx
*operands
, enum rtx_code code
)
2176 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2177 hi_op
[0] = simplify_gen_subreg (SImode
, operands
[0], DImode
, 4);
2179 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2180 hi_op
[1] = simplify_gen_subreg (SImode
, operands
[2], DImode
, 4);
2186 output_asm_insn ("andd\t%1, %0", lo_op
) ;
2187 output_asm_insn ("andd\t%1, %0", hi_op
) ;
2192 output_asm_insn ("ord\t%1, %0", lo_op
) ;
2193 output_asm_insn ("ord\t%1, %0", hi_op
) ;
2198 output_asm_insn ("xord\t%1, %0", lo_op
) ;
2199 output_asm_insn ("xord\t%1, %0", hi_op
) ;
2209 /* Initialize 'targetm' variable which contains pointers to functions
2210 and data relating to the target machine. */
2212 struct gcc_target targetm
= TARGET_INITIALIZER
;