1 /* Output routines for CR16 processor.
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by KPIT Cummins Infosystems Limited.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "stor-layout.h"
31 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
35 #include "insn-codes.h"
36 #include "insn-attr.h"
43 #include "diagnostic-core.h"
44 #include "basic-block.h"
46 #include "target-def.h"
52 /* Maximum number of register used for passing parameters. */
53 #define MAX_REG_FOR_PASSING_ARGS 6
55 /* Minimum number register used for passing parameters. */
56 #define MIN_REG_FOR_PASSING_ARGS 2
58 /* The maximum count of words supported in the assembly of the architecture in
59 a push/pop instruction. */
62 /* Predicate is true if the current function is a 'noreturn' function,
63 i.e. it is qualified as volatile. */
64 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
66 /* Predicate that holds when we need to save registers even for 'noreturn'
67 functions, to accommodate for unwinding. */
68 #define MUST_SAVE_REGS_P() \
69 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
71 /* Nonzero if the rtx X is a signed const int of n bits. */
72 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
73 ((GET_CODE (X) == CONST_INT \
74 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
76 /* Nonzero if the rtx X is an unsigned const int of n bits. */
77 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
78 ((GET_CODE (X) == CONST_INT \
79 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
81 /* Structure for stack computations. */
83 /* variable definitions in the struture
84 args_size Number of bytes saved on the stack for local
87 reg_size Number of bytes saved on the stack for
90 total_size The sum of 2 sizes: locals vars and padding byte
91 for saving the registers. Used in expand_prologue()
94 last_reg_to_save Will hold the number of the last register the
95 prologue saves, -1 if no register is saved
97 save_regs[16] Each object in the array is a register number.
98 Mark 1 for registers that need to be saved
100 num_regs Number of registers saved
102 initialized Non-zero if frame size already calculated, not
105 function_makes_calls Does the function make calls ? not used yet. */
107 struct cr16_frame_info
109 unsigned long var_size
;
110 unsigned long args_size
;
111 unsigned int reg_size
;
112 unsigned long total_size
;
113 long last_reg_to_save
;
114 long save_regs
[FIRST_PSEUDO_REGISTER
];
117 int function_makes_calls
;
120 /* Current frame information calculated by cr16_compute_frame_size. */
121 static struct cr16_frame_info current_frame_info
;
123 /* Static Variables. */
125 /* Data model that was supplied by user via command line option
126 This will be overridden in case of invalid combination
127 of core and data model options are supplied. */
128 static enum data_model_type data_model
= DM_DEFAULT
;
130 /* TARGETM Function Prototypes and forward declarations */
131 static void cr16_print_operand (FILE *, rtx
, int);
132 static void cr16_print_operand_address (FILE *, rtx
);
134 /* Stack layout and calling conventions. */
135 #undef TARGET_STRUCT_VALUE_RTX
136 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
137 #undef TARGET_RETURN_IN_MEMORY
138 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
140 /* Target-specific uses of '__attribute__'. */
141 #undef TARGET_ATTRIBUTE_TABLE
142 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
143 #undef TARGET_NARROW_VOLATILE_BITFIELD
144 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
147 #undef TARGET_UNWIND_WORD_MODE
148 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
150 /* Override Options. */
151 #undef TARGET_OPTION_OVERRIDE
152 #define TARGET_OPTION_OVERRIDE cr16_override_options
154 /* Conditional register usuage. */
155 #undef TARGET_CONDITIONAL_REGISTER_USAGE
156 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
158 /* Controlling register spills. */
159 #undef TARGET_CLASS_LIKELY_SPILLED_P
160 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
162 /* Passing function arguments. */
163 #undef TARGET_FUNCTION_ARG
164 #define TARGET_FUNCTION_ARG cr16_function_arg
165 #undef TARGET_FUNCTION_ARG_ADVANCE
166 #define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
167 #undef TARGET_RETURN_POPS_ARGS
168 #define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
170 /* Initialize the GCC target structure. */
171 #undef TARGET_FRAME_POINTER_REQUIRED
172 #define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required
173 #undef TARGET_CAN_ELIMINATE
174 #define TARGET_CAN_ELIMINATE cr16_can_eliminate
175 #undef TARGET_LEGITIMIZE_ADDRESS
176 #define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address
177 #undef TARGET_LEGITIMATE_CONSTANT_P
178 #define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p
179 #undef TARGET_LEGITIMATE_ADDRESS_P
180 #define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p
182 /* Returning function value. */
183 #undef TARGET_FUNCTION_VALUE
184 #define TARGET_FUNCTION_VALUE cr16_function_value
185 #undef TARGET_LIBCALL_VALUE
186 #define TARGET_LIBCALL_VALUE cr16_libcall_value
187 #undef TARGET_FUNCTION_VALUE_REGNO_P
188 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
190 /* printing the values. */
191 #undef TARGET_PRINT_OPERAND
192 #define TARGET_PRINT_OPERAND cr16_print_operand
193 #undef TARGET_PRINT_OPERAND_ADDRESS
194 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
196 /* Relative costs of operations. */
197 #undef TARGET_ADDRESS_COST
198 #define TARGET_ADDRESS_COST cr16_address_cost
199 #undef TARGET_REGISTER_MOVE_COST
200 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
201 #undef TARGET_MEMORY_MOVE_COST
202 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
204 /* Table of machine attributes. */
205 static const struct attribute_spec cr16_attribute_table
[] = {
206 /* ISRs have special prologue and epilogue requirements. */
207 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
208 affects_type_identity }. */
209 {"interrupt", 0, 0, false, true, true, NULL
, false},
210 {NULL
, 0, 0, false, false, false, NULL
, false}
213 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
214 .?byte directive along with @c is not understood by assembler.
215 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
216 as TARGET_ASM_ALIGNED_xx_OP. */
217 #undef TARGET_ASM_UNALIGNED_HI_OP
218 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
219 #undef TARGET_ASM_UNALIGNED_SI_OP
220 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
221 #undef TARGET_ASM_UNALIGNED_DI_OP
222 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
224 /* Target hook implementations. */
226 /* Implements hook TARGET_RETURN_IN_MEMORY. */
228 cr16_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
230 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
231 return ((size
== -1) || (size
> 8));
234 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
236 cr16_class_likely_spilled_p (reg_class_t rclass
)
238 if ((rclass
) == SHORT_REGS
|| (rclass
) == DOUBLE_BASE_REGS
239 || (rclass
) == LONG_REGS
|| (rclass
) == GENERAL_REGS
)
246 cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
,
247 tree funtype ATTRIBUTE_UNUSED
,
248 int size ATTRIBUTE_UNUSED
)
253 /* Returns true if data model selected via command line option
254 is same as function argument. */
256 cr16_is_data_model (enum data_model_type model
)
258 return (model
== data_model
);
261 /* Parse relevant options and override. */
263 cr16_override_options (void)
265 /* Disable -fdelete-null-pointer-checks option for CR16 target.
266 Programs which rely on NULL pointer dereferences _not_ halting the
267 program may not work properly with this option. So disable this
269 flag_delete_null_pointer_checks
= 0;
271 /* FIXME: To avoid spill_failure ICE during exception handling,
272 * disable cse_fllow_jumps. The spill error occurs when compiler
273 * can't find a suitable candidate in GENERAL_REGS class to reload
275 * Need to find a better way of avoiding this situation. */
277 flag_cse_follow_jumps
= 0;
279 /* If -fpic option, data_model == DM_FAR. */
280 if (flag_pic
== NEAR_PIC
)
285 /* The only option we want to examine is data model option. */
288 if (strcmp (cr16_data_model
, "medium") == 0)
289 data_model
= DM_DEFAULT
;
290 else if (strcmp (cr16_data_model
, "near") == 0)
291 data_model
= DM_NEAR
;
292 else if (strcmp (cr16_data_model
, "far") == 0)
297 error ("data-model=far not valid for cr16c architecture");
300 error ("invalid data model option -mdata-model=%s", cr16_data_model
);
303 data_model
= DM_DEFAULT
;
306 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
308 cr16_conditional_register_usage (void)
312 fixed_regs
[12] = call_used_regs
[12] = 1;
316 /* Stack layout and calling conventions routines. */
318 /* Return nonzero if the current function being compiled is an interrupt
319 function as specified by the "interrupt" attribute. */
321 cr16_interrupt_function_p (void)
325 attributes
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
326 return (lookup_attribute ("interrupt", attributes
) != NULL_TREE
);
329 /* Compute values for the array current_frame_info.save_regs and the variable
330 current_frame_info.reg_size. The index of current_frame_info.save_regs
331 is numbers of register, each will get 1 if we need to save it in the
332 current function, 0 if not. current_frame_info.reg_size is the total sum
333 of the registers being saved. */
335 cr16_compute_save_regs (void)
339 /* Initialize here so in case the function is no-return it will be -1. */
340 current_frame_info
.last_reg_to_save
= -1;
342 /* Initialize the number of bytes to be saved. */
343 current_frame_info
.reg_size
= 0;
345 /* No need to save any registers if the function never returns. */
346 if (FUNC_IS_NORETURN_P (current_function_decl
) && !MUST_SAVE_REGS_P ())
349 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
351 if (fixed_regs
[regno
])
353 current_frame_info
.save_regs
[regno
] = 0;
357 /* If this reg is used and not call-used (except RA), save it. */
358 if (cr16_interrupt_function_p ())
360 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
361 /* This is a volatile reg in a non-leaf interrupt routine - save
362 it for the sake of its sons. */
363 current_frame_info
.save_regs
[regno
] = 1;
364 else if (df_regs_ever_live_p (regno
))
365 /* This reg is used - save it. */
366 current_frame_info
.save_regs
[regno
] = 1;
368 /* This reg is not used, and is not a volatile - don't save. */
369 current_frame_info
.save_regs
[regno
] = 0;
373 /* If this reg is used and not call-used (except RA), save it. */
374 if (df_regs_ever_live_p (regno
)
375 && (!call_used_regs
[regno
] || regno
== RETURN_ADDRESS_REGNUM
))
376 current_frame_info
.save_regs
[regno
] = 1;
378 current_frame_info
.save_regs
[regno
] = 0;
382 /* Save registers so the exception handler can modify them. */
383 if (crtl
->calls_eh_return
)
389 regno
= EH_RETURN_DATA_REGNO (i
);
390 if (INVALID_REGNUM
== regno
)
392 current_frame_info
.save_regs
[regno
] = 1;
396 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
397 if (current_frame_info
.save_regs
[regno
] == 1)
399 current_frame_info
.last_reg_to_save
= regno
;
400 if (regno
>= CR16_FIRST_DWORD_REGISTER
)
401 current_frame_info
.reg_size
+= CR16_UNITS_PER_DWORD
;
403 current_frame_info
.reg_size
+= UNITS_PER_WORD
;
407 /* Compute the size of the local area and the size to be adjusted by the
408 prologue and epilogue. */
410 cr16_compute_frame (void)
412 /* For aligning the local variables. */
413 int stack_alignment
= STACK_BOUNDARY
/ BITS_PER_UNIT
;
416 /* Padding needed for each element of the frame. */
417 current_frame_info
.var_size
= get_frame_size ();
419 /* Align to the stack alignment. */
420 padding_locals
= current_frame_info
.var_size
% stack_alignment
;
422 padding_locals
= stack_alignment
- padding_locals
;
424 current_frame_info
.var_size
+= padding_locals
;
425 current_frame_info
.total_size
= current_frame_info
.var_size
426 + (ACCUMULATE_OUTGOING_ARGS
427 ? crtl
->outgoing_args_size
: 0);
430 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
432 cr16_initial_elimination_offset (int from
, int to
)
434 /* Compute this since we need to use current_frame_info.reg_size. */
435 cr16_compute_save_regs ();
437 /* Compute this since we need to use current_frame_info.var_size. */
438 cr16_compute_frame ();
440 if (((from
) == FRAME_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
441 return (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0);
442 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == FRAME_POINTER_REGNUM
))
443 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
);
444 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
445 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
446 + (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0));
451 /* Register Usage. */
453 /* Return the class number of the smallest class containing reg number REGNO.
454 This could be a conditional expression or could index an array. */
456 cr16_regno_reg_class (int regno
)
458 if ((regno
>= 0) && (regno
< CR16_FIRST_DWORD_REGISTER
))
461 if ((regno
>= CR16_FIRST_DWORD_REGISTER
) && (regno
< FIRST_PSEUDO_REGISTER
))
467 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
469 cr16_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
471 if ((GET_MODE_SIZE (mode
) >= 4) && (regno
== 11))
474 if (mode
== DImode
|| mode
== DFmode
)
476 if ((regno
> 8) || (regno
& 1))
482 && ((regno
>= 12) && (GET_MODE_SIZE (mode
) < 4 )))
485 /* CC can only hold CCmode values. */
486 if (GET_MODE_CLASS (mode
) == MODE_CC
)
491 /* Returns register number for function return value.*/
492 static inline unsigned int
493 cr16_ret_register (void)
498 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
500 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED
,
501 int incoming ATTRIBUTE_UNUSED
)
503 return gen_rtx_REG (Pmode
, cr16_ret_register ());
506 /* Returning function value. */
508 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
510 cr16_function_value_regno_p (const unsigned int regno
)
512 return (regno
== cr16_ret_register ());
515 /* Create an RTX representing the place where a
516 library function returns a value of mode MODE. */
518 cr16_libcall_value (enum machine_mode mode
,
519 const_rtx func ATTRIBUTE_UNUSED
)
521 return gen_rtx_REG (mode
, cr16_ret_register ());
524 /* Create an RTX representing the place where a
525 function returns a value of data type VALTYPE. */
527 cr16_function_value (const_tree type
,
528 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
529 bool outgoing ATTRIBUTE_UNUSED
)
531 return gen_rtx_REG (TYPE_MODE (type
), cr16_ret_register ());
534 /* Passing function arguments. */
536 /* If enough param regs are available for passing the param of type TYPE return
537 the number of registers needed else 0. */
539 enough_regs_for_param (CUMULATIVE_ARGS
* cum
, const_tree type
,
540 enum machine_mode mode
)
546 type_size
= GET_MODE_BITSIZE (mode
);
548 type_size
= int_size_in_bytes (type
) * BITS_PER_UNIT
;
550 remaining_size
= BITS_PER_WORD
* (MAX_REG_FOR_PASSING_ARGS
551 - (MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) +
554 /* Any variable which is too big to pass in two registers, will pass on
556 if ((remaining_size
>= type_size
) && (type_size
<= 2 * BITS_PER_WORD
))
557 return (type_size
+ BITS_PER_WORD
- 1) / BITS_PER_WORD
;
562 /* Implements the macro FUNCTION_ARG defined in cr16.h. */
564 cr16_function_arg (cumulative_args_t cum_v
, enum machine_mode mode
,
565 const_tree type
, bool named ATTRIBUTE_UNUSED
)
567 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
568 cum
->last_parm_in_reg
= 0;
570 /* function_arg () is called with this type just after all the args have
571 had their registers assigned. The rtx that function_arg returns from
572 this type is supposed to pass to 'gen_call' but currently it is not
573 implemented (see macro GEN_CALL). */
574 if (type
== void_type_node
)
577 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
582 /* Enable structures that need padding bytes at the end to pass to a
583 function in registers. */
584 if (enough_regs_for_param (cum
, type
, mode
) != 0)
586 cum
->last_parm_in_reg
= 1;
587 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
591 if ((MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) > MAX_REG_FOR_PASSING_ARGS
)
595 if (enough_regs_for_param (cum
, type
, mode
) != 0)
597 cum
->last_parm_in_reg
= 1;
598 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
605 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
607 cr16_init_cumulative_args (CUMULATIVE_ARGS
* cum
, tree fntype
,
608 rtx libfunc ATTRIBUTE_UNUSED
)
610 tree param
, next_param
;
614 /* Determine if this function has variable arguments. This is indicated by
615 the last argument being 'void_type_mode' if there are no variable
616 arguments. Change here for a different vararg. */
617 for (param
= (fntype
) ? TYPE_ARG_TYPES (fntype
) : 0;
618 param
!= NULL_TREE
; param
= next_param
)
620 next_param
= TREE_CHAIN (param
);
621 if ((next_param
== NULL_TREE
) && (TREE_VALUE (param
) != void_type_node
))
629 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
631 cr16_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
,
632 const_tree type
, bool named ATTRIBUTE_UNUSED
)
634 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
636 /* l holds the number of registers required. */
637 int l
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
639 /* If the parameter isn't passed on a register don't advance cum. */
640 if (!cum
->last_parm_in_reg
)
643 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
646 if ((mode
== SImode
) || (mode
== HImode
)
647 || (mode
== QImode
) || (mode
== DImode
))
654 else if ((mode
== SFmode
) || (mode
== DFmode
))
656 else if ((mode
) == BLKmode
)
658 if ((l
= enough_regs_for_param (cum
, type
, mode
)) != 0)
664 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
665 Return nonzero if N is a register used for passing parameters. */
667 cr16_function_arg_regno_p (int n
)
669 return ((n
<= MAX_REG_FOR_PASSING_ARGS
) && (n
>= MIN_REG_FOR_PASSING_ARGS
));
673 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
674 defined in cr16.h. */
676 /* Helper function to check if is a valid base register that can
679 cr16_addr_reg_p (rtx addr_reg
)
683 if (REG_P (addr_reg
))
685 else if ((GET_CODE (addr_reg
) == SUBREG
)
686 && REG_P (SUBREG_REG (addr_reg
))
687 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg
)))
689 reg
= SUBREG_REG (addr_reg
);
693 if (GET_MODE (reg
) != Pmode
)
699 /* Helper functions: Created specifically for decomposing operand of CONST
700 Recursively look into expression x for code or data symbol.
701 The function expects the expression to contain combination of
702 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
703 LABEL_REF, CONST_INT, (PLUS or MINUS)
706 All other combinations will result in code = -1 and data = ILLEGAL_DM
708 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
709 0 DM_FAR SYMBOL_REF was found and it was far data reference.
710 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
711 1 ILLEGAL_DM LABEL_REF was found.
712 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
714 cr16_decompose_const (rtx x
, int *code
, enum data_model_type
*data
,
719 switch (GET_CODE (x
))
722 *code
= SYMBOL_REF_FUNCTION_P (x
) ? 2 : 0;
723 /* 2 indicates func sym. */
726 if (CR16_TARGET_DATA_NEAR
)
728 else if (CR16_TARGET_DATA_MEDIUM
)
730 else if (CR16_TARGET_DATA_FAR
)
733 /* This will be used only for printing
734 the qualifier. This call is (may be)
735 made by cr16_print_operand_address. */
738 /* This call is (may be) made by
739 cr16_legitimate_address_p. */
746 /* 1 - indicates non-function symbol. */
752 /* Look into the tree nodes. */
753 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
754 cr16_decompose_const (XEXP (x
, 1), code
, data
, treat_as_const
);
755 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
756 cr16_decompose_const (XEXP (x
, 0), code
, data
, treat_as_const
);
764 This function decomposes the address returns the type of address
765 as defined in enum cr16_addrtype. It also fills the parameter *out.
766 The decomposed address can be used for two purposes. One to
767 check if the address is valid and second to print the address
770 Following tables list valid address supported in CR16C/C+ architectures.
772 aN : Absoulte address N-bit address
773 R : One 16-bit register
774 RP : Consecutive two 16-bit registers or one 32-bit register
775 I : One 32-bit register
776 dispN : Signed displacement of N-bits
778 ----Code addresses----
780 disp9 : CR16_ABSOLUTE (disp)
781 disp17 : CR16_ABSOLUTE (disp)
782 disp25 : CR16_ABSOLUTE (disp)
783 RP + disp25 : CR16_REGP_REL (base, disp)
786 RP : CR16_REGP_REL (base, disp=0)
787 a24 : CR16_ABSOLUTE (disp)
789 ----Data addresses----
790 a20 : CR16_ABSOLUTE (disp) near (1M)
791 a24 : CR16_ABSOLUTE (disp) medium (16M)
792 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
793 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
794 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
795 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
796 I : *** Valid but port does not support this
797 I + a20 : *** Valid but port does not support this
798 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
799 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
801 Decomposing Data model in case of absolute address.
803 Target Option Address type Resultant Data ref type
804 ---------------------- ------------ -----------------------
805 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
806 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
807 CR16_TARGET_MODEL_NEAR ABS24 Invalid
808 CR16_TARGET_MODEL_NEAR IMM32 Invalid
810 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
811 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
812 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
813 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
815 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
816 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
817 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
818 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
820 cr16_decompose_address (rtx addr
, struct cr16_address
*out
,
821 bool debug_print
, bool treat_as_const
)
823 rtx base
= NULL_RTX
, disp
= NULL_RTX
, index
= NULL_RTX
;
824 enum data_model_type data
= ILLEGAL_DM
;
826 enum cr16_addrtype retval
= CR16_INVALID
;
828 switch (GET_CODE (addr
))
831 /* Absolute address (known at compile time). */
834 fprintf (stderr
, "\ncode:%d", code
);
839 fprintf (stderr
, "\ndisp:");
843 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
847 fprintf (stderr
, "\ndata:%d", data
);
848 retval
= CR16_ABSOLUTE
;
850 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 24))
852 if (!CR16_TARGET_DATA_NEAR
)
856 fprintf (stderr
, "\ndata:%d", data
);
857 retval
= CR16_ABSOLUTE
;
860 return CR16_INVALID
; /* ABS24 is not support in NEAR model. */
867 /* A CONST is an expression of PLUS or MINUS with
868 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
869 result of assembly-time arithmetic computation. */
870 retval
= CR16_ABSOLUTE
;
872 /* Call the helper function to check the validity. */
873 cr16_decompose_const (XEXP (addr
, 0), &code
, &data
, treat_as_const
);
874 if ((code
== 0) && (data
== ILLEGAL_DM
))
875 /* CONST is not valid code or data address. */
879 fprintf (stderr
, "\ndisp:");
881 fprintf (stderr
, "\ncode:%d", code
);
882 fprintf (stderr
, "\ndata:%d", data
);
887 retval
= CR16_ABSOLUTE
;
889 /* 1 - indicates non-function symbol. */
893 fprintf (stderr
, "\ndisp:");
895 fprintf (stderr
, "\ncode:%d", code
);
900 /* Absolute address (known at link time). */
901 retval
= CR16_ABSOLUTE
;
903 /* This is a code address if symbol_ref is a function. */
904 /* 2 indicates func sym. */
905 code
= SYMBOL_REF_FUNCTION_P (addr
) ? 2 : 0;
908 fprintf (stderr
, "\ndisp:");
910 fprintf (stderr
, "\ncode:%d", code
);
912 /* If not function ref then check if valid data ref. */
915 if (CR16_TARGET_DATA_NEAR
)
917 else if (CR16_TARGET_DATA_MEDIUM
)
919 else if (CR16_TARGET_DATA_FAR
)
922 /* This will be used only for printing the
923 qualifier. This call is (may be) made
924 by cr16_print_operand_address. */
927 /* This call is (may be) made by
928 cr16_legitimate_address_p. */
935 fprintf (stderr
, "\ndata:%d", data
);
940 /* Register relative address. */
941 /* Assume REG fits in a single register. */
942 retval
= CR16_REG_REL
;
943 if (GET_MODE_BITSIZE (GET_MODE (addr
)) > BITS_PER_WORD
)
944 if (!LONG_REG_P (REGNO (addr
)))
945 /* REG will result in reg pair. */
946 retval
= CR16_REGP_REL
;
950 fprintf (stderr
, "\nbase:");
956 switch (GET_CODE (XEXP (addr
, 0)))
961 /* All Reg relative addresses having a displacement needs
962 to fit in 20-bits. */
963 disp
= XEXP (addr
, 1);
966 fprintf (stderr
, "\ndisp:");
969 switch (GET_CODE (XEXP (addr
, 1)))
972 /* Shall fit in 20-bits. */
973 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
977 fprintf (stderr
, "\ncode:%d", code
);
981 switch (XINT (XEXP (addr
, 1), 1))
983 case UNSPEC_LIBRARY_OFFSET
:
992 /* This is also a valid expression for address.
993 However, we cannot ascertain if the resultant
994 displacement will be valid 20-bit value. Therefore,
995 lets not allow such an expression for now. This will
996 be updated when we find a way to validate this
997 expression as legitimate address.
998 Till then fall through CR16_INVALID. */
1000 return CR16_INVALID
;
1003 /* Now check if REG can fit into single or pair regs. */
1004 retval
= CR16_REG_REL
;
1005 base
= XEXP (addr
, 0);
1008 fprintf (stderr
, "\nbase:");
1011 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr
, 0)))) > BITS_PER_WORD
)
1013 if (!LONG_REG_P (REGNO ((XEXP (addr
, 0)))))
1014 /* REG will result in reg pair. */
1015 retval
= CR16_REGP_REL
;
1029 Check if the operand 1 is valid index register. */
1032 fprintf (stderr
, "\ndata:%d", data
);
1033 switch (GET_CODE (XEXP (addr
, 1)))
1037 if (!REG_OK_FOR_INDEX_P (XEXP (addr
, 1)))
1038 return CR16_INVALID
;
1039 /* OK. REG is a valid index register. */
1040 index
= XEXP (addr
, 1);
1043 fprintf (stderr
, "\nindex:");
1048 return CR16_INVALID
;
1050 /* Check if operand 0 of operand 0 is REGP. */
1051 switch (GET_CODE (XEXP (XEXP (addr
, 0), 0)))
1055 /* Now check if REG is a REGP and not in LONG regs. */
1056 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr
, 0), 0)))
1059 if (REGNO (XEXP (XEXP (addr
, 0), 0))
1060 >= CR16_FIRST_DWORD_REGISTER
)
1061 return CR16_INVALID
;
1062 base
= XEXP (XEXP (addr
, 0), 0);
1065 fprintf (stderr
, "\nbase:");
1070 return CR16_INVALID
;
1073 return CR16_INVALID
;
1075 /* Now check if the operand 1 of operand 0 is const_int. */
1076 if (GET_CODE (XEXP (XEXP (addr
, 0), 1)) == CONST_INT
)
1078 disp
= XEXP (XEXP (addr
, 0), 1);
1081 fprintf (stderr
, "\ndisp:");
1084 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
1085 return CR16_INVALID
;
1088 return CR16_INVALID
;
1089 retval
= CR16_INDEX_REGP_REL
;
1092 return CR16_INVALID
;
1097 return CR16_INVALID
;
1100 /* Check if the base and index registers are valid. */
1101 if (base
&& !(cr16_addr_reg_p (base
)))
1102 return CR16_INVALID
;
1103 if (base
&& !(CR16_REG_OK_FOR_BASE_P (base
)))
1104 return CR16_INVALID
;
1105 if (index
&& !(REG_OK_FOR_INDEX_P (index
)))
1106 return CR16_INVALID
;
1108 /* Write the decomposition to out parameter. */
1118 /* Return non-zero value if 'x' is legitimate PIC operand
1119 when generating PIC code. */
1121 legitimate_pic_operand_p (rtx x
)
1123 switch (GET_CODE (x
))
1132 /* REVISIT: Use something like symbol_referenced_p. */
1133 if (GET_CODE (XEXP (x
, 0)) == PLUS
1134 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
1135 || GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
)
1136 && (GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
))
1140 return legitimate_pic_operand_p (XEXP (x
, 0));
1148 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
1150 Input Output (-f pic) Output (-f PIC)
1153 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
1155 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
1157 NOTE: @BRO is added using unspec:BRO
1158 NOTE: @GOT is added using unspec:GOT. */
1160 legitimize_pic_address (rtx orig
, enum machine_mode mode ATTRIBUTE_UNUSED
,
1163 /* First handle a simple SYMBOL_REF or LABEL_REF. */
1164 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1167 reg
= gen_reg_rtx (Pmode
);
1169 if (flag_pic
== NEAR_PIC
)
1171 /* Unspec to handle -fpic option. */
1172 emit_insn (gen_unspec_bro_addr (reg
, orig
));
1173 emit_insn (gen_addsi3 (reg
, reg
, pic_offset_table_rtx
));
1175 else if (flag_pic
== FAR_PIC
)
1177 /* Unspec to handle -fPIC option. */
1178 emit_insn (gen_unspec_got_addr (reg
, orig
));
1182 else if (GET_CODE (orig
) == CONST
)
1184 /* To handle (symbol + offset). */
1187 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1188 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1193 gcc_assert (can_create_pseudo_p ());
1194 reg
= gen_reg_rtx (Pmode
);
1197 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
1199 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1200 offset
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1201 base
== reg
? 0 : reg
);
1203 /* REVISIT: Optimize for const-offsets. */
1204 emit_insn (gen_addsi3 (reg
, base
, offset
));
1211 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
1213 cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
1214 rtx addr
, bool strict
)
1216 enum cr16_addrtype addrtype
;
1217 struct cr16_address address
;
1219 if (TARGET_DEBUG_ADDR
)
1222 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
1223 GET_MODE_NAME (mode
), strict
);
1226 addrtype
= cr16_decompose_address (addr
, &address
,
1227 (TARGET_DEBUG_ADDR
? 1 : 0), FALSE
);
1229 if (TARGET_DEBUG_ADDR
)
1231 const char *typestr
;
1236 typestr
= "invalid";
1239 typestr
= "absolute";
1242 typestr
= "register relative";
1245 typestr
= "register pair relative";
1247 case CR16_INDEX_REGP_REL
:
1248 typestr
= "index + register pair relative";
1253 fprintf (stderr
, "\ncr16 address type: %s\n", typestr
);
1256 if (addrtype
== CR16_INVALID
)
1262 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address
.base
), mode
))
1264 if (TARGET_DEBUG_ADDR
)
1265 fprintf (stderr
, "base register not strict\n");
1268 if (address
.index
&& !REGNO_OK_FOR_INDEX_P (REGNO (address
.index
)))
1270 if (TARGET_DEBUG_ADDR
)
1271 fprintf (stderr
, "index register not strict\n");
1276 /* Return true if addressing mode is register relative. */
1279 if (addrtype
== CR16_REG_REL
|| addrtype
== CR16_REGP_REL
)
1288 /* Routines to compute costs. */
1290 /* Return cost of the memory address x. */
1292 cr16_address_cost (rtx addr
, enum machine_mode mode ATTRIBUTE_UNUSED
,
1293 addr_space_t as ATTRIBUTE_UNUSED
,
1294 bool speed ATTRIBUTE_UNUSED
)
1296 enum cr16_addrtype addrtype
;
1297 struct cr16_address address
;
1300 addrtype
= cr16_decompose_address (addr
, &address
, 0, FALSE
);
1302 gcc_assert (addrtype
!= CR16_INVALID
);
1304 /* CR16_ABSOLUTE : 3
1305 CR16_REG_REL (disp !=0) : 4
1306 CR16_REG_REL (disp ==0) : 5
1307 CR16_REGP_REL (disp !=0) : 6
1308 CR16_REGP_REL (disp ==0) : 7
1309 CR16_INDEX_REGP_REL (disp !=0) : 8
1310 CR16_INDEX_REGP_REL (disp ==0) : 9. */
1324 case CR16_INDEX_REGP_REL
:
1332 if (TARGET_DEBUG_ADDR
)
1334 fprintf (stderr
, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost
);
1342 /* Implement `TARGET_REGISTER_MOVE_COST'. */
1344 cr16_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
1345 reg_class_t from ATTRIBUTE_UNUSED
, reg_class_t to
)
1347 return (to
!= GENERAL_REGS
? 8 : 2);
1350 /* Implement `TARGET_MEMORY_MOVE_COST'. */
1352 /* Return the cost of moving data of mode MODE between a register of class
1353 CLASS and memory; IN is zero if the value is to be written to memory,
1354 nonzero if it is to be read in. This cost is relative to those in
1355 REGISTER_MOVE_COST. */
1357 cr16_memory_move_cost (enum machine_mode mode
,
1358 reg_class_t rclass ATTRIBUTE_UNUSED
,
1359 bool in ATTRIBUTE_UNUSED
)
1361 /* One LD or ST takes twice the time of a simple reg-reg move. */
1362 if (reg_classes_intersect_p (rclass
, GENERAL_REGS
))
1363 return (4 * HARD_REGNO_NREGS (0, mode
));
1368 /* Instruction output. */
1370 /* Check if a const_double is ok for cr16 store-immediate instructions. */
1372 cr16_const_double_ok (rtx op
)
1374 if (GET_MODE (op
) == SFmode
)
1378 REAL_VALUE_FROM_CONST_DOUBLE (r
, op
);
1379 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1380 return UNSIGNED_INT_FITS_N_BITS (l
, 4) ? 1 : 0;
1383 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op
), 4)) &&
1384 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op
), 4))) ? 1 : 0;
1387 /* Returns bit position of first 0 or 1 bit.
1388 It is safe to assume val as 16-bit wide. */
1390 cr16_operand_bit_pos (int val
, int bitval
)
1396 for (i
= 0; i
< 16; i
++)
1402 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
1404 cr16_print_operand (FILE * file
, rtx x
, int code
)
1406 int ptr_dereference
= 0;
1412 const char *cr16_cmp_str
;
1413 switch (GET_CODE (x
))
1415 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
1416 -> swap all non symmetric ops. */
1418 cr16_cmp_str
= "eq";
1421 cr16_cmp_str
= "ne";
1424 cr16_cmp_str
= "lt";
1427 cr16_cmp_str
= "lo";
1430 cr16_cmp_str
= "gt";
1433 cr16_cmp_str
= "hi";
1436 cr16_cmp_str
= "le";
1439 cr16_cmp_str
= "ls";
1442 cr16_cmp_str
= "ge";
1445 cr16_cmp_str
= "hs";
1450 fprintf (file
, "%s", cr16_cmp_str
);
1458 if (GET_CODE (x
) == REG
)
1460 /* For Push instructions, we should not print register pairs. */
1461 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1467 /* Print the immediate address for bal
1468 'b' is used instead of 'a' to avoid compiler calling
1469 the GO_IF_LEGITIMATE_ADDRESS which cannot
1470 perform checks on const_int code addresses as it
1471 assumes all const_int are data addresses. */
1472 fprintf (file
, "0x%lx", INTVAL (x
));
1476 /* Print bit position of first 0. */
1477 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 0));
1481 /* Print bit position of first 1. */
1482 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 1));
1485 /* 'g' is used for implicit mem: dereference. */
1486 ptr_dereference
= 1;
1490 switch (GET_CODE (x
))
1493 if (GET_MODE_BITSIZE (GET_MODE (x
)) > BITS_PER_WORD
)
1495 if (LONG_REG_P (REGNO (x
)))
1496 fprintf (file
, "(%s)", reg_names
[REGNO (x
)]);
1498 fprintf (file
, "(%s,%s)", reg_names
[REGNO (x
) + 1],
1499 reg_names
[REGNO (x
)]);
1502 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1506 output_address (XEXP (x
, 0));
1514 REAL_VALUE_FROM_CONST_DOUBLE (r
, x
);
1515 REAL_VALUE_TO_TARGET_SINGLE (r
, l
);
1517 fprintf (file
, "$0x%lx", l
);
1522 fprintf (file
, "$%ld", INTVAL (x
));
1526 switch (XINT (x
, 1))
1534 if (!ptr_dereference
)
1538 cr16_print_operand_address (file
, x
);
1542 output_operand_lossage ("invalid %%xn code");
1548 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
1551 cr16_print_operand_address (FILE * file
, rtx addr
)
1553 enum cr16_addrtype addrtype
;
1554 struct cr16_address address
;
1556 /* Decompose the address. Also ask it to treat address as constant. */
1557 addrtype
= cr16_decompose_address (addr
, &address
, 0, TRUE
);
1559 if (address
.disp
&& GET_CODE (address
.disp
) == UNSPEC
)
1569 if (GET_CODE (address
.disp
) == UNSPEC
)
1570 cr16_print_operand (file
, address
.disp
, 0);
1572 output_addr_const (file
, address
.disp
);
1575 fprintf (file
, "0");
1576 fprintf (file
, "(%s)", reg_names
[REGNO (address
.base
)]);
1581 output_addr_const (file
, address
.disp
);
1583 fprintf (file
, "0");
1586 case CR16_INDEX_REGP_REL
:
1587 fprintf (file
, "[%s]", reg_names
[REGNO (address
.index
)]);
1592 if (GET_CODE (address
.disp
) == UNSPEC
)
1593 cr16_print_operand (file
, address
.disp
, 0);
1595 output_addr_const (file
, address
.disp
);
1598 fprintf (file
, "0");
1599 fprintf (file
, "(%s,%s)", reg_names
[REGNO (address
.base
) + 1],
1600 reg_names
[REGNO (address
.base
)]);
1606 /* Add qualifiers to the address expression that was just printed. */
1607 if (flag_pic
< NEAR_PIC
&& address
.code
== 0)
1609 if (address
.data
== DM_FAR
)
1610 /* Addr contains SYMBOL_REF & far data ptr. */
1611 fprintf (file
, "@l");
1612 else if (address
.data
== DM_DEFAULT
)
1613 /* Addr contains SYMBOL_REF & medium data ptr. */
1614 fprintf (file
, "@m");
1615 /* Addr contains SYMBOL_REF & medium data ptr. */
1616 else if (address
.data
== DM_NEAR
)
1617 /* Addr contains SYMBOL_REF & near data ptr. */
1618 fprintf (file
, "@s");
1620 else if (flag_pic
== NEAR_PIC
1621 && (address
.code
== 0) && (address
.data
== DM_FAR
1622 || address
.data
== DM_DEFAULT
1623 || address
.data
== DM_NEAR
))
1625 fprintf (file
, "@l");
1627 else if (flag_pic
== NEAR_PIC
&& address
.code
== 2)
1629 fprintf (file
, "pic");
1631 else if (flag_pic
== NEAR_PIC
&& address
.code
== 1)
1633 fprintf (file
, "@cpic");
1636 else if (flag_pic
== FAR_PIC
&& address
.code
== 2)
1638 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
1639 address ! GOTc tells assembler this symbol is a text-address
1640 This needs to be fixed in such a way that this offset is done
1641 only in the case where an address is being used for indirect jump
1642 or call. Determining the potential usage of loadd is of course not
1643 possible always. Eventually, this has to be fixed in the
1645 fprintf (file
, "GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1647 else if (flag_pic
== FAR_PIC
&& address
.code
== 1)
1649 fprintf (file
, "@cGOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1652 else if (flag_pic
== FAR_PIC
&&
1653 (address
.data
== DM_FAR
|| address
.data
== DM_DEFAULT
1654 || address
.data
== DM_NEAR
))
1656 fprintf (file
, "@GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1660 /* Machine description helper functions. */
1662 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
1663 When push_or_pop is zero -> string for push instructions of prologue.
1664 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1665 Relies on the assumptions:
1666 1. RA is the last register to be saved.
1667 2. The maximal value of the counter is MAX_COUNT. */
1669 cr16_prepare_push_pop_string (int push_or_pop
)
1671 /* j is the number of registers being saved, takes care that there won't be
1672 more than 8 in one push/pop instruction. */
1674 /* For the register mask string. */
1675 static char one_inst_str
[50];
1677 /* i is the index of current_frame_info.save_regs[], going from 0 until
1678 current_frame_info.last_reg_to_save. */
1684 /* For reversing on the push instructions if there are more than one. */
1687 return_str
= (char *) xmalloc (160);
1688 temp_str
= (char *) xmalloc (160);
1691 memset (return_str
, 0, 3);
1694 while (i
<= current_frame_info
.last_reg_to_save
)
1696 /* Prepare mask for one instruction. */
1697 one_inst_str
[0] = 0;
1699 /* To count number of words in one instruction. */
1703 while ((word_cnt
< MAX_COUNT
)
1704 && (i
<= current_frame_info
.last_reg_to_save
))
1706 /* For each non consecutive save register,
1707 a new instruction shall be generated. */
1708 if (!current_frame_info
.save_regs
[i
])
1710 /* Move to next reg and break. */
1715 if (i
== RETURN_ADDRESS_REGNUM
)
1719 /* Check especially if adding 2 does not cross the MAX_COUNT. */
1720 if ((word_cnt
+ ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2))
1723 /* Increase word count by 2 for long registers except RA. */
1724 word_cnt
+= ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2);
1729 /* No need to generate any instruction as
1730 no register or RA needs to be saved. */
1731 if ((word_cnt
== 0) && (print_ra
== 0))
1734 /* Now prepare the instruction operands. */
1737 sprintf (one_inst_str
, "$%d, %s", word_cnt
, reg_names
[start_reg
]);
1739 strcat (one_inst_str
, ", ra");
1742 strcat (one_inst_str
, "ra");
1744 if (push_or_pop
== 1)
1746 /* Pop instruction. */
1747 if (print_ra
&& !cr16_interrupt_function_p ()
1748 && !crtl
->calls_eh_return
)
1749 /* Print popret if RA is saved and its not a interrupt
1751 strcpy (temp_str
, "\n\tpopret\t");
1753 strcpy (temp_str
, "\n\tpop\t");
1755 strcat (temp_str
, one_inst_str
);
1757 /* Add the pop instruction list. */
1758 strcat (return_str
, temp_str
);
1762 /* Push instruction. */
1763 strcpy (temp_str
, "\n\tpush\t");
1764 strcat (temp_str
, one_inst_str
);
1766 /* We need to reverse the order of the instructions if there
1767 are more than one. (since the pop will not be reversed in
1769 strcat (temp_str
, return_str
);
1770 strcpy (return_str
, temp_str
);
1774 if (push_or_pop
== 1)
1777 if (cr16_interrupt_function_p ())
1778 strcat (return_str
, "\n\tretx\n");
1779 else if (crtl
->calls_eh_return
)
1781 /* Add stack adjustment before returning to exception handler
1782 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
1783 strcat (return_str
, "\n\taddd\t (r5, r4), (sp)\t\n");
1784 strcat (return_str
, "\n\tjump\t (ra)\n");
1786 /* But before anything else, undo the adjustment addition done in
1787 cr16_expand_epilogue (). */
1788 strcpy (temp_str
, "\n\tsubd\t (r5, r4), (sp)\t\n");
1789 strcat (temp_str
, return_str
);
1790 strcpy (return_str
, temp_str
);
1792 else if (!FUNC_IS_NORETURN_P (current_function_decl
)
1793 && !(current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]))
1794 strcat (return_str
, "\n\tjump\t (ra)\n");
1797 /* Skip the newline and the tab in the start of return_str. */
1803 /* Generate DWARF2 annotation for multi-push instruction. */
1805 cr16_create_dwarf_for_multi_push (rtx insn
)
1807 rtx dwarf
, reg
, tmp
;
1808 int i
, j
, from
, to
, word_cnt
, dwarf_par_index
, inc
;
1809 enum machine_mode mode
;
1810 int num_regs
= 0, offset
= 0, split_here
= 0, total_push_bytes
= 0;
1812 for (i
= 0; i
<= current_frame_info
.last_reg_to_save
; ++i
)
1814 if (current_frame_info
.save_regs
[i
])
1817 if (i
< CR16_FIRST_DWORD_REGISTER
)
1818 total_push_bytes
+= 2;
1820 total_push_bytes
+= 4;
1827 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (num_regs
+ 1));
1828 dwarf_par_index
= num_regs
;
1830 from
= current_frame_info
.last_reg_to_save
+ 1;
1831 to
= current_frame_info
.last_reg_to_save
;
1834 for (i
= current_frame_info
.last_reg_to_save
; i
>= 0;)
1836 if (!current_frame_info
.save_regs
[i
] || 0 == i
|| split_here
)
1838 /* This block of regs is pushed in one instruction. */
1839 if (0 == i
&& current_frame_info
.save_regs
[i
])
1842 for (j
= to
; j
>= from
; --j
)
1844 if (j
< CR16_FIRST_DWORD_REGISTER
)
1854 reg
= gen_rtx_REG (mode
, j
);
1856 tmp
= gen_rtx_SET (VOIDmode
,
1857 gen_frame_mem (mode
,
1859 (Pmode
, stack_pointer_rtx
,
1860 total_push_bytes
- offset
)),
1862 RTX_FRAME_RELATED_P (tmp
) = 1;
1863 XVECEXP (dwarf
, 0, dwarf_par_index
--) = tmp
;
1872 if (i
!= RETURN_ADDRESS_REGNUM
)
1874 inc
= (i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2;
1875 if (word_cnt
+ inc
>= MAX_COUNT
|| FRAME_POINTER_REGNUM
== i
)
1887 tmp
= gen_rtx_SET (SImode
, stack_pointer_rtx
,
1888 gen_rtx_PLUS (SImode
, stack_pointer_rtx
,
1889 GEN_INT (-offset
)));
1890 RTX_FRAME_RELATED_P (tmp
) = 1;
1891 XVECEXP (dwarf
, 0, 0) = tmp
;
1893 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, dwarf
);
1897 CompactRISC CR16 Architecture stack layout:
1899 0 +---------------------
1904 +==================== Sp (x) = Ap (x+1)
1905 A | Args for functions
1906 | | called by X and Dynamically
1907 | | Dynamic allocations allocated and
1908 | | (alloca, variable deallocated
1909 Stack | length arrays).
1910 grows +-------------------- Fp (x)
1911 down| | Local variables of X
1912 ward| +--------------------
1913 | | Regs saved for X-1
1914 | +==================== Sp (x-1) = Ap (x)
1917 +-------------------- Fp (x-1)
1923 cr16_expand_prologue (void)
1927 cr16_compute_frame ();
1928 cr16_compute_save_regs ();
1930 /* If there is no need in push and adjustment to sp, return. */
1931 if ((current_frame_info
.total_size
+ current_frame_info
.reg_size
) == 0)
1934 if (current_frame_info
.last_reg_to_save
!= -1)
1936 /* If there are registers to push. */
1937 insn
= emit_insn (gen_push_for_prologue
1938 (GEN_INT (current_frame_info
.reg_size
)));
1939 cr16_create_dwarf_for_multi_push (insn
);
1940 RTX_FRAME_RELATED_P (insn
) = 1;
1944 if (current_frame_info
.total_size
> 0)
1946 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1947 GEN_INT (-current_frame_info
.total_size
)));
1948 RTX_FRAME_RELATED_P (insn
) = 1;
1951 if (frame_pointer_needed
)
1953 /* Initialize the frame pointer with the value of the stack pointer
1954 pointing now to the locals. */
1955 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1959 /* Generate insn that updates the stack for local variables and padding
1960 for registers we save. - Generate the appropriate return insn. */
1962 cr16_expand_epilogue (void)
1966 /* Nonzero if we need to return and pop only RA. This will generate a
1967 different insn. This differentiate is for the peepholes for call as
1968 last statement in function. */
1969 int only_popret_RA
= (current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]
1970 && (current_frame_info
.reg_size
1971 == CR16_UNITS_PER_DWORD
));
1973 if (frame_pointer_needed
)
1975 /* Restore the stack pointer with the frame pointers value. */
1976 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
1979 if (current_frame_info
.total_size
> 0)
1981 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1982 GEN_INT (current_frame_info
.total_size
)));
1983 RTX_FRAME_RELATED_P (insn
) = 1;
1986 if (crtl
->calls_eh_return
)
1988 /* Add this here so that (r5, r4) is actually loaded with the adjustment
1989 value; otherwise, the load might be optimized away...
1990 NOTE: remember to subtract the adjustment before popping the regs
1991 and add it back before returning. */
1992 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1993 EH_RETURN_STACKADJ_RTX
));
1996 if (cr16_interrupt_function_p ())
1998 insn
= emit_jump_insn (gen_interrupt_return ());
1999 RTX_FRAME_RELATED_P (insn
) = 1;
2001 else if (crtl
->calls_eh_return
)
2003 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
2004 insn
= emit_jump_insn (gen_pop_and_popret_return
2005 (GEN_INT (current_frame_info
.reg_size
)));
2006 RTX_FRAME_RELATED_P (insn
) = 1;
2008 else if (current_frame_info
.last_reg_to_save
== -1)
2009 /* Nothing to pop. */
2010 /* Don't output jump for interrupt routine, only retx. */
2011 emit_jump_insn (gen_jump_return ());
2012 else if (only_popret_RA
)
2014 insn
= emit_jump_insn (gen_popret_RA_return ());
2015 RTX_FRAME_RELATED_P (insn
) = 1;
2019 insn
= emit_jump_insn (gen_pop_and_popret_return
2020 (GEN_INT (current_frame_info
.reg_size
)));
2021 RTX_FRAME_RELATED_P (insn
) = 1;
2025 /* Implements FRAME_POINTER_REQUIRED. */
2027 cr16_frame_pointer_required (void)
2029 return (cfun
->calls_alloca
|| crtl
->calls_eh_return
2030 || cfun
->has_nonlocal_label
|| crtl
->calls_eh_return
);
2034 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
2036 return (to
== STACK_POINTER_REGNUM
? !frame_pointer_needed
: true);
2040 /* A C compound statement that attempts to replace X with
2041 a valid memory address for an operand of mode MODE. WIN
2042 will be a C statement label elsewhere in the code.
2043 X will always be the result of a call to break_out_memory_refs (),
2044 and OLDX will be the operand that was given to that function to
2046 The code generated by this macro should not alter the
2047 substructure of X. If it transforms X into a more legitimate form,
2048 it should assign X (which will always be a C variable) a new value. */
2050 cr16_legitimize_address (rtx x
, rtx orig_x ATTRIBUTE_UNUSED
,
2051 enum machine_mode mode ATTRIBUTE_UNUSED
)
2054 return legitimize_pic_address (orig_x
, mode
, NULL_RTX
);
2059 /* Implement TARGET_LEGITIMATE_CONSTANT_P
2060 Nonzero if X is a legitimate constant for an immediate
2061 operand on the target machine. You can assume that X
2062 satisfies CONSTANT_P. In cr16c treat legitimize float
2063 constant as an immediate operand. */
2065 cr16_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
2066 rtx x ATTRIBUTE_UNUSED
)
2072 notice_update_cc (rtx exp
)
2074 if (GET_CODE (exp
) == SET
)
2076 /* Jumps do not alter the cc's. */
2077 if (SET_DEST (exp
) == pc_rtx
)
2080 /* Moving register or memory into a register:
2081 it doesn't alter the cc's, but it might invalidate
2082 the RTX's which we remember the cc's came from.
2083 (Note that moving a constant 0 or 1 MAY set the cc's). */
2084 if (REG_P (SET_DEST (exp
))
2085 && (REG_P (SET_SRC (exp
)) || GET_CODE (SET_SRC (exp
)) == MEM
))
2090 /* Moving register into memory doesn't alter the cc's.
2091 It may invalidate the RTX's which we remember the cc's came from. */
2092 if (GET_CODE (SET_DEST (exp
)) == MEM
&& REG_P (SET_SRC (exp
)))
2102 static enum machine_mode
2103 cr16_unwind_word_mode (void)
2108 /* Helper function for md file. This function is used to emit arithmetic
2109 DI instructions. The argument "num" decides which instruction to be
2112 cr16_emit_add_sub_di (rtx
*operands
, enum rtx_code code
)
2118 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2119 hi0_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 4);
2120 hi1_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 6);
2122 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2123 hi0_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 4);
2124 hi1_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 6);
2130 output_asm_insn ("addd\t%1, %0", lo_op
) ;
2131 output_asm_insn ("addcw\t%1, %0", hi0_op
) ;
2132 output_asm_insn ("addcw\t%1, %0", hi1_op
) ;
2137 output_asm_insn ("subd\t%1, %0", lo_op
) ;
2138 output_asm_insn ("subcw\t%1, %0", hi0_op
) ;
2139 output_asm_insn ("subcw\t%1, %0", hi1_op
) ;
2150 /* Helper function for md file. This function is used to emit logical
2151 DI instructions. The argument "num" decides which instruction to be
2154 cr16_emit_logical_di (rtx
*operands
, enum rtx_code code
)
2159 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2160 hi_op
[0] = simplify_gen_subreg (SImode
, operands
[0], DImode
, 4);
2162 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2163 hi_op
[1] = simplify_gen_subreg (SImode
, operands
[2], DImode
, 4);
2169 output_asm_insn ("andd\t%1, %0", lo_op
) ;
2170 output_asm_insn ("andd\t%1, %0", hi_op
) ;
2175 output_asm_insn ("ord\t%1, %0", lo_op
) ;
2176 output_asm_insn ("ord\t%1, %0", hi_op
) ;
2181 output_asm_insn ("xord\t%1, %0", lo_op
) ;
2182 output_asm_insn ("xord\t%1, %0", hi_op
) ;
2192 /* Initialize 'targetm' variable which contains pointers to functions
2193 and data relating to the target machine. */
2195 struct gcc_target targetm
= TARGET_INITIALIZER
;