1 /* Output routines for CR16 processor.
2 Copyright (C) 2012-2017 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"
33 #include "diagnostic-core.h"
34 #include "stor-layout.h"
36 #include "conditions.h"
41 /* This file should be included last. */
42 #include "target-def.h"
46 /* Maximum number of register used for passing parameters. */
47 #define MAX_REG_FOR_PASSING_ARGS 6
49 /* Minimum number register used for passing parameters. */
50 #define MIN_REG_FOR_PASSING_ARGS 2
52 /* The maximum count of words supported in the assembly of the architecture in
53 a push/pop instruction. */
56 /* Predicate is true if the current function is a 'noreturn' function,
57 i.e. it is qualified as volatile. */
58 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
60 /* Predicate that holds when we need to save registers even for 'noreturn'
61 functions, to accommodate for unwinding. */
62 #define MUST_SAVE_REGS_P() \
63 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
65 /* Nonzero if the rtx X is a signed const int of n bits. */
66 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
67 ((GET_CODE (X) == CONST_INT \
68 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
70 /* Nonzero if the rtx X is an unsigned const int of n bits. */
71 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
72 ((GET_CODE (X) == CONST_INT \
73 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
75 /* Structure for stack computations. */
77 /* variable definitions in the struture
78 args_size Number of bytes saved on the stack for local
81 reg_size Number of bytes saved on the stack for
84 total_size The sum of 2 sizes: locals vars and padding byte
85 for saving the registers. Used in expand_prologue()
88 last_reg_to_save Will hold the number of the last register the
89 prologue saves, -1 if no register is saved
91 save_regs[16] Each object in the array is a register number.
92 Mark 1 for registers that need to be saved
94 num_regs Number of registers saved
96 initialized Non-zero if frame size already calculated, not
99 function_makes_calls Does the function make calls ? not used yet. */
101 struct cr16_frame_info
103 unsigned long var_size
;
104 unsigned long args_size
;
105 unsigned int reg_size
;
106 unsigned long total_size
;
107 long last_reg_to_save
;
108 long save_regs
[FIRST_PSEUDO_REGISTER
];
111 int function_makes_calls
;
114 /* Current frame information calculated by cr16_compute_frame_size. */
115 static struct cr16_frame_info current_frame_info
;
117 /* Static Variables. */
119 /* Data model that was supplied by user via command line option
120 This will be overridden in case of invalid combination
121 of core and data model options are supplied. */
122 static enum data_model_type data_model
= DM_DEFAULT
;
124 /* TARGETM Function Prototypes and forward declarations */
125 static void cr16_print_operand (FILE *, rtx
, int);
126 static void cr16_print_operand_address (FILE *, machine_mode
, rtx
);
128 /* Stack layout and calling conventions. */
129 #undef TARGET_STRUCT_VALUE_RTX
130 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
131 #undef TARGET_RETURN_IN_MEMORY
132 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
134 /* Target-specific uses of '__attribute__'. */
135 #undef TARGET_ATTRIBUTE_TABLE
136 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
137 #undef TARGET_NARROW_VOLATILE_BITFIELD
138 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
141 #undef TARGET_UNWIND_WORD_MODE
142 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
144 /* Override Options. */
145 #undef TARGET_OPTION_OVERRIDE
146 #define TARGET_OPTION_OVERRIDE cr16_override_options
148 /* Conditional register usuage. */
149 #undef TARGET_CONDITIONAL_REGISTER_USAGE
150 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
152 /* Controlling register spills. */
153 #undef TARGET_CLASS_LIKELY_SPILLED_P
154 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
156 /* Passing function arguments. */
157 #undef TARGET_FUNCTION_ARG
158 #define TARGET_FUNCTION_ARG cr16_function_arg
159 #undef TARGET_FUNCTION_ARG_ADVANCE
160 #define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
161 #undef TARGET_RETURN_POPS_ARGS
162 #define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
164 /* Initialize the GCC target structure. */
165 #undef TARGET_FRAME_POINTER_REQUIRED
166 #define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required
167 #undef TARGET_CAN_ELIMINATE
168 #define TARGET_CAN_ELIMINATE cr16_can_eliminate
169 #undef TARGET_LEGITIMIZE_ADDRESS
170 #define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address
171 #undef TARGET_LEGITIMATE_CONSTANT_P
172 #define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p
173 #undef TARGET_LEGITIMATE_ADDRESS_P
174 #define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p
177 #define TARGET_LRA_P hook_bool_void_false
179 /* Returning function value. */
180 #undef TARGET_FUNCTION_VALUE
181 #define TARGET_FUNCTION_VALUE cr16_function_value
182 #undef TARGET_LIBCALL_VALUE
183 #define TARGET_LIBCALL_VALUE cr16_libcall_value
184 #undef TARGET_FUNCTION_VALUE_REGNO_P
185 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
187 /* printing the values. */
188 #undef TARGET_PRINT_OPERAND
189 #define TARGET_PRINT_OPERAND cr16_print_operand
190 #undef TARGET_PRINT_OPERAND_ADDRESS
191 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
193 /* Relative costs of operations. */
194 #undef TARGET_ADDRESS_COST
195 #define TARGET_ADDRESS_COST cr16_address_cost
196 #undef TARGET_REGISTER_MOVE_COST
197 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
198 #undef TARGET_MEMORY_MOVE_COST
199 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
201 /* Table of machine attributes. */
202 static const struct attribute_spec cr16_attribute_table
[] = {
203 /* ISRs have special prologue and epilogue requirements. */
204 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
205 affects_type_identity }. */
206 {"interrupt", 0, 0, false, true, true, NULL
, false},
207 {NULL
, 0, 0, false, false, false, NULL
, false}
210 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
211 .?byte directive along with @c is not understood by assembler.
212 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
213 as TARGET_ASM_ALIGNED_xx_OP. */
214 #undef TARGET_ASM_UNALIGNED_HI_OP
215 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
216 #undef TARGET_ASM_UNALIGNED_SI_OP
217 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
218 #undef TARGET_ASM_UNALIGNED_DI_OP
219 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
221 /* Target hook implementations. */
223 /* Implements hook TARGET_RETURN_IN_MEMORY. */
225 cr16_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
227 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
228 return ((size
== -1) || (size
> 8));
231 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
233 cr16_class_likely_spilled_p (reg_class_t rclass
)
235 if ((rclass
) == SHORT_REGS
|| (rclass
) == DOUBLE_BASE_REGS
236 || (rclass
) == LONG_REGS
|| (rclass
) == GENERAL_REGS
)
243 cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
,
244 tree funtype ATTRIBUTE_UNUSED
,
245 int size ATTRIBUTE_UNUSED
)
250 /* Returns true if data model selected via command line option
251 is same as function argument. */
253 cr16_is_data_model (enum data_model_type model
)
255 return (model
== data_model
);
258 /* Parse relevant options and override. */
260 cr16_override_options (void)
262 /* Disable -fdelete-null-pointer-checks option for CR16 target.
263 Programs which rely on NULL pointer dereferences _not_ halting the
264 program may not work properly with this option. So disable this
266 flag_delete_null_pointer_checks
= 0;
268 /* FIXME: To avoid spill_failure ICE during exception handling,
269 * disable cse_fllow_jumps. The spill error occurs when compiler
270 * can't find a suitable candidate in GENERAL_REGS class to reload
272 * Need to find a better way of avoiding this situation. */
274 flag_cse_follow_jumps
= 0;
276 /* If -fpic option, data_model == DM_FAR. */
277 if (flag_pic
== NEAR_PIC
)
282 /* The only option we want to examine is data model option. */
285 if (strcmp (cr16_data_model
, "medium") == 0)
286 data_model
= DM_DEFAULT
;
287 else if (strcmp (cr16_data_model
, "near") == 0)
288 data_model
= DM_NEAR
;
289 else if (strcmp (cr16_data_model
, "far") == 0)
294 error ("data-model=far not valid for cr16c architecture");
297 error ("invalid data model option -mdata-model=%s", cr16_data_model
);
300 data_model
= DM_DEFAULT
;
303 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
305 cr16_conditional_register_usage (void)
309 fixed_regs
[12] = call_used_regs
[12] = 1;
313 /* Stack layout and calling conventions routines. */
315 /* Return nonzero if the current function being compiled is an interrupt
316 function as specified by the "interrupt" attribute. */
318 cr16_interrupt_function_p (void)
322 attributes
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
323 return (lookup_attribute ("interrupt", attributes
) != NULL_TREE
);
326 /* Compute values for the array current_frame_info.save_regs and the variable
327 current_frame_info.reg_size. The index of current_frame_info.save_regs
328 is numbers of register, each will get 1 if we need to save it in the
329 current function, 0 if not. current_frame_info.reg_size is the total sum
330 of the registers being saved. */
332 cr16_compute_save_regs (void)
336 /* Initialize here so in case the function is no-return it will be -1. */
337 current_frame_info
.last_reg_to_save
= -1;
339 /* Initialize the number of bytes to be saved. */
340 current_frame_info
.reg_size
= 0;
342 /* No need to save any registers if the function never returns. */
343 if (FUNC_IS_NORETURN_P (current_function_decl
) && !MUST_SAVE_REGS_P ())
346 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
348 if (fixed_regs
[regno
])
350 current_frame_info
.save_regs
[regno
] = 0;
354 /* If this reg is used and not call-used (except RA), save it. */
355 if (cr16_interrupt_function_p ())
357 if (!crtl
->is_leaf
&& call_used_regs
[regno
])
358 /* This is a volatile reg in a non-leaf interrupt routine - save
359 it for the sake of its sons. */
360 current_frame_info
.save_regs
[regno
] = 1;
361 else if (df_regs_ever_live_p (regno
))
362 /* This reg is used - save it. */
363 current_frame_info
.save_regs
[regno
] = 1;
365 /* This reg is not used, and is not a volatile - don't save. */
366 current_frame_info
.save_regs
[regno
] = 0;
370 /* If this reg is used and not call-used (except RA), save it. */
371 if (df_regs_ever_live_p (regno
)
372 && (!call_used_regs
[regno
] || regno
== RETURN_ADDRESS_REGNUM
))
373 current_frame_info
.save_regs
[regno
] = 1;
375 current_frame_info
.save_regs
[regno
] = 0;
379 /* Save registers so the exception handler can modify them. */
380 if (crtl
->calls_eh_return
)
386 regno
= EH_RETURN_DATA_REGNO (i
);
387 if (INVALID_REGNUM
== regno
)
389 current_frame_info
.save_regs
[regno
] = 1;
393 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
394 if (current_frame_info
.save_regs
[regno
] == 1)
396 current_frame_info
.last_reg_to_save
= regno
;
397 if (regno
>= CR16_FIRST_DWORD_REGISTER
)
398 current_frame_info
.reg_size
+= CR16_UNITS_PER_DWORD
;
400 current_frame_info
.reg_size
+= UNITS_PER_WORD
;
404 /* Compute the size of the local area and the size to be adjusted by the
405 prologue and epilogue. */
407 cr16_compute_frame (void)
409 /* For aligning the local variables. */
410 int stack_alignment
= STACK_BOUNDARY
/ BITS_PER_UNIT
;
413 /* Padding needed for each element of the frame. */
414 current_frame_info
.var_size
= get_frame_size ();
416 /* Align to the stack alignment. */
417 padding_locals
= current_frame_info
.var_size
% stack_alignment
;
419 padding_locals
= stack_alignment
- padding_locals
;
421 current_frame_info
.var_size
+= padding_locals
;
422 current_frame_info
.total_size
= current_frame_info
.var_size
423 + (ACCUMULATE_OUTGOING_ARGS
424 ? crtl
->outgoing_args_size
: 0);
427 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
429 cr16_initial_elimination_offset (int from
, int to
)
431 /* Compute this since we need to use current_frame_info.reg_size. */
432 cr16_compute_save_regs ();
434 /* Compute this since we need to use current_frame_info.var_size. */
435 cr16_compute_frame ();
437 if (((from
) == FRAME_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
438 return (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0);
439 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == FRAME_POINTER_REGNUM
))
440 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
);
441 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
442 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
443 + (ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0));
448 /* Register Usage. */
450 /* Return the class number of the smallest class containing reg number REGNO.
451 This could be a conditional expression or could index an array. */
453 cr16_regno_reg_class (int regno
)
455 if ((regno
>= 0) && (regno
< CR16_FIRST_DWORD_REGISTER
))
458 if ((regno
>= CR16_FIRST_DWORD_REGISTER
) && (regno
< FIRST_PSEUDO_REGISTER
))
464 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
466 cr16_hard_regno_mode_ok (int regno
, machine_mode mode
)
468 if ((GET_MODE_SIZE (mode
) >= 4) && (regno
== 11))
471 if (mode
== DImode
|| mode
== DFmode
)
473 if ((regno
> 8) || (regno
& 1))
479 && ((regno
>= 12) && (GET_MODE_SIZE (mode
) < 4 )))
482 /* CC can only hold CCmode values. */
483 if (GET_MODE_CLASS (mode
) == MODE_CC
)
488 /* Returns register number for function return value.*/
489 static inline unsigned int
490 cr16_ret_register (void)
495 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
497 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED
,
498 int incoming ATTRIBUTE_UNUSED
)
500 return gen_rtx_REG (Pmode
, cr16_ret_register ());
503 /* Returning function value. */
505 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
507 cr16_function_value_regno_p (const unsigned int regno
)
509 return (regno
== cr16_ret_register ());
512 /* Create an RTX representing the place where a
513 library function returns a value of mode MODE. */
515 cr16_libcall_value (machine_mode mode
,
516 const_rtx func ATTRIBUTE_UNUSED
)
518 return gen_rtx_REG (mode
, cr16_ret_register ());
521 /* Create an RTX representing the place where a
522 function returns a value of data type VALTYPE. */
524 cr16_function_value (const_tree type
,
525 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
526 bool outgoing ATTRIBUTE_UNUSED
)
528 return gen_rtx_REG (TYPE_MODE (type
), cr16_ret_register ());
531 /* Passing function arguments. */
533 /* If enough param regs are available for passing the param of type TYPE return
534 the number of registers needed else 0. */
536 enough_regs_for_param (CUMULATIVE_ARGS
* cum
, const_tree type
,
543 type_size
= GET_MODE_BITSIZE (mode
);
545 type_size
= int_size_in_bytes (type
) * BITS_PER_UNIT
;
547 remaining_size
= BITS_PER_WORD
* (MAX_REG_FOR_PASSING_ARGS
548 - (MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) +
551 /* Any variable which is too big to pass in two registers, will pass on
553 if ((remaining_size
>= type_size
) && (type_size
<= 2 * BITS_PER_WORD
))
554 return (type_size
+ BITS_PER_WORD
- 1) / BITS_PER_WORD
;
559 /* Implements the macro FUNCTION_ARG defined in cr16.h. */
561 cr16_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
562 const_tree type
, bool named ATTRIBUTE_UNUSED
)
564 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
565 cum
->last_parm_in_reg
= 0;
567 /* function_arg () is called with this type just after all the args have
568 had their registers assigned. The rtx that function_arg returns from
569 this type is supposed to pass to 'gen_call' but currently it is not
571 if (type
== void_type_node
)
574 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
579 /* Enable structures that need padding bytes at the end to pass to a
580 function in registers. */
581 if (enough_regs_for_param (cum
, type
, mode
) != 0)
583 cum
->last_parm_in_reg
= 1;
584 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
588 if ((MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) > MAX_REG_FOR_PASSING_ARGS
)
592 if (enough_regs_for_param (cum
, type
, mode
) != 0)
594 cum
->last_parm_in_reg
= 1;
595 return gen_rtx_REG (mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
602 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
604 cr16_init_cumulative_args (CUMULATIVE_ARGS
* cum
, tree fntype
,
605 rtx libfunc ATTRIBUTE_UNUSED
)
607 tree param
, next_param
;
611 /* Determine if this function has variable arguments. This is indicated by
612 the last argument being 'void_type_mode' if there are no variable
613 arguments. Change here for a different vararg. */
614 for (param
= (fntype
) ? TYPE_ARG_TYPES (fntype
) : 0;
615 param
!= NULL_TREE
; param
= next_param
)
617 next_param
= TREE_CHAIN (param
);
618 if ((next_param
== NULL_TREE
) && (TREE_VALUE (param
) != void_type_node
))
626 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
628 cr16_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
629 const_tree type
, bool named ATTRIBUTE_UNUSED
)
631 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
633 /* l holds the number of registers required. */
634 int l
= GET_MODE_BITSIZE (mode
) / BITS_PER_WORD
;
636 /* If the parameter isn't passed on a register don't advance cum. */
637 if (!cum
->last_parm_in_reg
)
640 if (targetm
.calls
.must_pass_in_stack (mode
, type
) || (cum
->ints
< 0))
643 if ((mode
== SImode
) || (mode
== HImode
)
644 || (mode
== QImode
) || (mode
== DImode
))
651 else if ((mode
== SFmode
) || (mode
== DFmode
))
653 else if ((mode
) == BLKmode
)
655 if ((l
= enough_regs_for_param (cum
, type
, mode
)) != 0)
661 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
662 Return nonzero if N is a register used for passing parameters. */
664 cr16_function_arg_regno_p (int n
)
666 return ((n
<= MAX_REG_FOR_PASSING_ARGS
) && (n
>= MIN_REG_FOR_PASSING_ARGS
));
670 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
671 defined in cr16.h. */
673 /* Helper function to check if is a valid base register that can
676 cr16_addr_reg_p (rtx addr_reg
)
680 if (REG_P (addr_reg
))
682 else if ((GET_CODE (addr_reg
) == SUBREG
)
683 && REG_P (SUBREG_REG (addr_reg
))
684 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg
)))
686 reg
= SUBREG_REG (addr_reg
);
690 if (GET_MODE (reg
) != Pmode
)
696 /* Helper functions: Created specifically for decomposing operand of CONST
697 Recursively look into expression x for code or data symbol.
698 The function expects the expression to contain combination of
699 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
700 LABEL_REF, CONST_INT, (PLUS or MINUS)
703 All other combinations will result in code = -1 and data = ILLEGAL_DM
705 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
706 0 DM_FAR SYMBOL_REF was found and it was far data reference.
707 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
708 1 ILLEGAL_DM LABEL_REF was found.
709 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
711 cr16_decompose_const (rtx x
, int *code
, enum data_model_type
*data
,
716 switch (GET_CODE (x
))
719 *code
= SYMBOL_REF_FUNCTION_P (x
) ? 2 : 0;
720 /* 2 indicates func sym. */
723 if (CR16_TARGET_DATA_NEAR
)
725 else if (CR16_TARGET_DATA_MEDIUM
)
727 else if (CR16_TARGET_DATA_FAR
)
730 /* This will be used only for printing
731 the qualifier. This call is (may be)
732 made by cr16_print_operand_address. */
735 /* This call is (may be) made by
736 cr16_legitimate_address_p. */
743 /* 1 - indicates non-function symbol. */
749 /* Look into the tree nodes. */
750 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
751 cr16_decompose_const (XEXP (x
, 1), code
, data
, treat_as_const
);
752 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
753 cr16_decompose_const (XEXP (x
, 0), code
, data
, treat_as_const
);
761 This function decomposes the address returns the type of address
762 as defined in enum cr16_addrtype. It also fills the parameter *out.
763 The decomposed address can be used for two purposes. One to
764 check if the address is valid and second to print the address
767 Following tables list valid address supported in CR16C/C+ architectures.
769 aN : Absoulte address N-bit address
770 R : One 16-bit register
771 RP : Consecutive two 16-bit registers or one 32-bit register
772 I : One 32-bit register
773 dispN : Signed displacement of N-bits
775 ----Code addresses----
777 disp9 : CR16_ABSOLUTE (disp)
778 disp17 : CR16_ABSOLUTE (disp)
779 disp25 : CR16_ABSOLUTE (disp)
780 RP + disp25 : CR16_REGP_REL (base, disp)
783 RP : CR16_REGP_REL (base, disp=0)
784 a24 : CR16_ABSOLUTE (disp)
786 ----Data addresses----
787 a20 : CR16_ABSOLUTE (disp) near (1M)
788 a24 : CR16_ABSOLUTE (disp) medium (16M)
789 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
790 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
791 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
792 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
793 I : *** Valid but port does not support this
794 I + a20 : *** Valid but port does not support this
795 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
796 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
798 Decomposing Data model in case of absolute address.
800 Target Option Address type Resultant Data ref type
801 ---------------------- ------------ -----------------------
802 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
803 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
804 CR16_TARGET_MODEL_NEAR ABS24 Invalid
805 CR16_TARGET_MODEL_NEAR IMM32 Invalid
807 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
808 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
809 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
810 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
812 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
813 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
814 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
815 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
817 cr16_decompose_address (rtx addr
, struct cr16_address
*out
,
818 bool debug_print
, bool treat_as_const
)
820 rtx base
= NULL_RTX
, disp
= NULL_RTX
, index
= NULL_RTX
;
821 enum data_model_type data
= ILLEGAL_DM
;
823 enum cr16_addrtype retval
= CR16_INVALID
;
825 switch (GET_CODE (addr
))
828 /* Absolute address (known at compile time). */
831 fprintf (stderr
, "\ncode:%d", code
);
836 fprintf (stderr
, "\ndisp:");
840 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
844 fprintf (stderr
, "\ndata:%d", data
);
845 retval
= CR16_ABSOLUTE
;
847 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 24))
849 if (!CR16_TARGET_DATA_NEAR
)
853 fprintf (stderr
, "\ndata:%d", data
);
854 retval
= CR16_ABSOLUTE
;
857 return CR16_INVALID
; /* ABS24 is not support in NEAR model. */
864 /* A CONST is an expression of PLUS or MINUS with
865 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
866 result of assembly-time arithmetic computation. */
867 retval
= CR16_ABSOLUTE
;
869 /* Call the helper function to check the validity. */
870 cr16_decompose_const (XEXP (addr
, 0), &code
, &data
, treat_as_const
);
871 if ((code
== 0) && (data
== ILLEGAL_DM
))
872 /* CONST is not valid code or data address. */
876 fprintf (stderr
, "\ndisp:");
878 fprintf (stderr
, "\ncode:%d", code
);
879 fprintf (stderr
, "\ndata:%d", data
);
884 retval
= CR16_ABSOLUTE
;
886 /* 1 - indicates non-function symbol. */
890 fprintf (stderr
, "\ndisp:");
892 fprintf (stderr
, "\ncode:%d", code
);
897 /* Absolute address (known at link time). */
898 retval
= CR16_ABSOLUTE
;
900 /* This is a code address if symbol_ref is a function. */
901 /* 2 indicates func sym. */
902 code
= SYMBOL_REF_FUNCTION_P (addr
) ? 2 : 0;
905 fprintf (stderr
, "\ndisp:");
907 fprintf (stderr
, "\ncode:%d", code
);
909 /* If not function ref then check if valid data ref. */
912 if (CR16_TARGET_DATA_NEAR
)
914 else if (CR16_TARGET_DATA_MEDIUM
)
916 else if (CR16_TARGET_DATA_FAR
)
919 /* This will be used only for printing the
920 qualifier. This call is (may be) made
921 by cr16_print_operand_address. */
924 /* This call is (may be) made by
925 cr16_legitimate_address_p. */
932 fprintf (stderr
, "\ndata:%d", data
);
937 /* Register relative address. */
938 /* Assume REG fits in a single register. */
939 retval
= CR16_REG_REL
;
940 if (GET_MODE_BITSIZE (GET_MODE (addr
)) > BITS_PER_WORD
)
941 if (!LONG_REG_P (REGNO (addr
)))
942 /* REG will result in reg pair. */
943 retval
= CR16_REGP_REL
;
947 fprintf (stderr
, "\nbase:");
953 switch (GET_CODE (XEXP (addr
, 0)))
958 /* All Reg relative addresses having a displacement needs
959 to fit in 20-bits. */
960 disp
= XEXP (addr
, 1);
963 fprintf (stderr
, "\ndisp:");
966 switch (GET_CODE (XEXP (addr
, 1)))
969 /* Shall fit in 20-bits. */
970 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
974 fprintf (stderr
, "\ncode:%d", code
);
978 switch (XINT (XEXP (addr
, 1), 1))
980 case UNSPEC_LIBRARY_OFFSET
:
989 /* This is also a valid expression for address.
990 However, we cannot ascertain if the resultant
991 displacement will be valid 20-bit value. Therefore,
992 lets not allow such an expression for now. This will
993 be updated when we find a way to validate this
994 expression as legitimate address.
995 Till then fall through CR16_INVALID. */
1000 /* Now check if REG can fit into single or pair regs. */
1001 retval
= CR16_REG_REL
;
1002 base
= XEXP (addr
, 0);
1005 fprintf (stderr
, "\nbase:");
1008 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr
, 0)))) > BITS_PER_WORD
)
1010 if (!LONG_REG_P (REGNO ((XEXP (addr
, 0)))))
1011 /* REG will result in reg pair. */
1012 retval
= CR16_REGP_REL
;
1026 Check if the operand 1 is valid index register. */
1029 fprintf (stderr
, "\ndata:%d", data
);
1030 switch (GET_CODE (XEXP (addr
, 1)))
1034 if (!REG_OK_FOR_INDEX_P (XEXP (addr
, 1)))
1035 return CR16_INVALID
;
1036 /* OK. REG is a valid index register. */
1037 index
= XEXP (addr
, 1);
1040 fprintf (stderr
, "\nindex:");
1045 return CR16_INVALID
;
1047 /* Check if operand 0 of operand 0 is REGP. */
1048 switch (GET_CODE (XEXP (XEXP (addr
, 0), 0)))
1052 /* Now check if REG is a REGP and not in LONG regs. */
1053 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr
, 0), 0)))
1056 if (REGNO (XEXP (XEXP (addr
, 0), 0))
1057 >= CR16_FIRST_DWORD_REGISTER
)
1058 return CR16_INVALID
;
1059 base
= XEXP (XEXP (addr
, 0), 0);
1062 fprintf (stderr
, "\nbase:");
1067 return CR16_INVALID
;
1070 return CR16_INVALID
;
1072 /* Now check if the operand 1 of operand 0 is const_int. */
1073 if (GET_CODE (XEXP (XEXP (addr
, 0), 1)) == CONST_INT
)
1075 disp
= XEXP (XEXP (addr
, 0), 1);
1078 fprintf (stderr
, "\ndisp:");
1081 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
1082 return CR16_INVALID
;
1085 return CR16_INVALID
;
1086 retval
= CR16_INDEX_REGP_REL
;
1089 return CR16_INVALID
;
1094 return CR16_INVALID
;
1097 /* Check if the base and index registers are valid. */
1098 if (base
&& !(cr16_addr_reg_p (base
)))
1099 return CR16_INVALID
;
1100 if (base
&& !(CR16_REG_OK_FOR_BASE_P (base
)))
1101 return CR16_INVALID
;
1102 if (index
&& !(REG_OK_FOR_INDEX_P (index
)))
1103 return CR16_INVALID
;
1105 /* Write the decomposition to out parameter. */
1115 /* Return non-zero value if 'x' is legitimate PIC operand
1116 when generating PIC code. */
1118 legitimate_pic_operand_p (rtx x
)
1120 switch (GET_CODE (x
))
1127 /* REVISIT: Use something like symbol_referenced_p. */
1128 if (GET_CODE (XEXP (x
, 0)) == PLUS
1129 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
1130 || GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
)
1131 && (GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
))
1135 return legitimate_pic_operand_p (XEXP (x
, 0));
1142 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
1144 Input Output (-f pic) Output (-f PIC)
1147 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
1149 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
1151 NOTE: @BRO is added using unspec:BRO
1152 NOTE: @GOT is added using unspec:GOT. */
1154 legitimize_pic_address (rtx orig
, machine_mode mode ATTRIBUTE_UNUSED
,
1157 /* First handle a simple SYMBOL_REF or LABEL_REF. */
1158 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1161 reg
= gen_reg_rtx (Pmode
);
1163 if (flag_pic
== NEAR_PIC
)
1165 /* Unspec to handle -fpic option. */
1166 emit_insn (gen_unspec_bro_addr (reg
, orig
));
1167 emit_insn (gen_addsi3 (reg
, reg
, pic_offset_table_rtx
));
1169 else if (flag_pic
== FAR_PIC
)
1171 /* Unspec to handle -fPIC option. */
1172 emit_insn (gen_unspec_got_addr (reg
, orig
));
1176 else if (GET_CODE (orig
) == CONST
)
1178 /* To handle (symbol + offset). */
1181 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1182 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1187 gcc_assert (can_create_pseudo_p ());
1188 reg
= gen_reg_rtx (Pmode
);
1191 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
1193 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1194 offset
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1195 base
== reg
? 0 : reg
);
1197 /* REVISIT: Optimize for const-offsets. */
1198 emit_insn (gen_addsi3 (reg
, base
, offset
));
1205 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
1207 cr16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1208 rtx addr
, bool strict
)
1210 enum cr16_addrtype addrtype
;
1211 struct cr16_address address
;
1213 if (TARGET_DEBUG_ADDR
)
1216 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
1217 GET_MODE_NAME (mode
), strict
);
1220 addrtype
= cr16_decompose_address (addr
, &address
,
1221 (TARGET_DEBUG_ADDR
? 1 : 0), FALSE
);
1223 if (TARGET_DEBUG_ADDR
)
1225 const char *typestr
;
1230 typestr
= "invalid";
1233 typestr
= "absolute";
1236 typestr
= "register relative";
1239 typestr
= "register pair relative";
1241 case CR16_INDEX_REGP_REL
:
1242 typestr
= "index + register pair relative";
1247 fprintf (stderr
, "\ncr16 address type: %s\n", typestr
);
1250 if (addrtype
== CR16_INVALID
)
1256 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address
.base
), mode
))
1258 if (TARGET_DEBUG_ADDR
)
1259 fprintf (stderr
, "base register not strict\n");
1262 if (address
.index
&& !REGNO_OK_FOR_INDEX_P (REGNO (address
.index
)))
1264 if (TARGET_DEBUG_ADDR
)
1265 fprintf (stderr
, "index register not strict\n");
1270 /* Return true if addressing mode is register relative. */
1273 if (addrtype
== CR16_REG_REL
|| addrtype
== CR16_REGP_REL
)
1282 /* Routines to compute costs. */
1284 /* Return cost of the memory address x. */
1286 cr16_address_cost (rtx addr
, machine_mode mode ATTRIBUTE_UNUSED
,
1287 addr_space_t as ATTRIBUTE_UNUSED
,
1288 bool speed ATTRIBUTE_UNUSED
)
1290 enum cr16_addrtype addrtype
;
1291 struct cr16_address address
;
1294 addrtype
= cr16_decompose_address (addr
, &address
, 0, FALSE
);
1296 gcc_assert (addrtype
!= CR16_INVALID
);
1298 /* CR16_ABSOLUTE : 3
1299 CR16_REG_REL (disp !=0) : 4
1300 CR16_REG_REL (disp ==0) : 5
1301 CR16_REGP_REL (disp !=0) : 6
1302 CR16_REGP_REL (disp ==0) : 7
1303 CR16_INDEX_REGP_REL (disp !=0) : 8
1304 CR16_INDEX_REGP_REL (disp ==0) : 9. */
1318 case CR16_INDEX_REGP_REL
:
1326 if (TARGET_DEBUG_ADDR
)
1328 fprintf (stderr
, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost
);
1336 /* Implement `TARGET_REGISTER_MOVE_COST'. */
1338 cr16_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED
,
1339 reg_class_t from ATTRIBUTE_UNUSED
, reg_class_t to
)
1341 return (to
!= GENERAL_REGS
? 8 : 2);
1344 /* Implement `TARGET_MEMORY_MOVE_COST'. */
1346 /* Return the cost of moving data of mode MODE between a register of class
1347 CLASS and memory; IN is zero if the value is to be written to memory,
1348 nonzero if it is to be read in. This cost is relative to those in
1349 REGISTER_MOVE_COST. */
1351 cr16_memory_move_cost (machine_mode mode
,
1352 reg_class_t rclass ATTRIBUTE_UNUSED
,
1353 bool in ATTRIBUTE_UNUSED
)
1355 /* One LD or ST takes twice the time of a simple reg-reg move. */
1356 if (reg_classes_intersect_p (rclass
, GENERAL_REGS
))
1357 return (4 * HARD_REGNO_NREGS (0, mode
));
1362 /* Instruction output. */
1364 /* Check if a const_double is ok for cr16 store-immediate instructions. */
1366 cr16_const_double_ok (rtx op
)
1368 if (GET_MODE (op
) == SFmode
)
1371 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op
), l
);
1372 return UNSIGNED_INT_FITS_N_BITS (l
, 4) ? 1 : 0;
1375 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op
), 4)) &&
1376 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op
), 4))) ? 1 : 0;
1379 /* Returns bit position of first 0 or 1 bit.
1380 It is safe to assume val as 16-bit wide. */
1382 cr16_operand_bit_pos (int val
, int bitval
)
1388 for (i
= 0; i
< 16; i
++)
1394 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
1396 cr16_print_operand (FILE * file
, rtx x
, int code
)
1398 int ptr_dereference
= 0;
1404 const char *cr16_cmp_str
;
1405 switch (GET_CODE (x
))
1407 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
1408 -> swap all non symmetric ops. */
1410 cr16_cmp_str
= "eq";
1413 cr16_cmp_str
= "ne";
1416 cr16_cmp_str
= "lt";
1419 cr16_cmp_str
= "lo";
1422 cr16_cmp_str
= "gt";
1425 cr16_cmp_str
= "hi";
1428 cr16_cmp_str
= "le";
1431 cr16_cmp_str
= "ls";
1434 cr16_cmp_str
= "ge";
1437 cr16_cmp_str
= "hs";
1442 fprintf (file
, "%s", cr16_cmp_str
);
1450 if (GET_CODE (x
) == REG
)
1452 /* For Push instructions, we should not print register pairs. */
1453 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1459 /* Print the immediate address for bal
1460 'b' is used instead of 'a' to avoid compiler calling
1461 the GO_IF_LEGITIMATE_ADDRESS which cannot
1462 perform checks on const_int code addresses as it
1463 assumes all const_int are data addresses. */
1464 fprintf (file
, "0x%lx", INTVAL (x
));
1468 /* Print bit position of first 0. */
1469 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 0));
1473 /* Print bit position of first 1. */
1474 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 1));
1477 /* 'g' is used for implicit mem: dereference. */
1478 ptr_dereference
= 1;
1483 switch (GET_CODE (x
))
1486 if (GET_MODE_BITSIZE (GET_MODE (x
)) > BITS_PER_WORD
)
1488 if (LONG_REG_P (REGNO (x
)))
1489 fprintf (file
, "(%s)", reg_names
[REGNO (x
)]);
1491 fprintf (file
, "(%s,%s)", reg_names
[REGNO (x
) + 1],
1492 reg_names
[REGNO (x
)]);
1495 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1499 output_address (GET_MODE (x
), XEXP (x
, 0));
1506 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x
), l
);
1508 fprintf (file
, "$0x%lx", l
);
1513 fprintf (file
, "$%ld", INTVAL (x
));
1517 switch (XINT (x
, 1))
1525 if (!ptr_dereference
)
1529 cr16_print_operand_address (file
, VOIDmode
, x
);
1534 output_operand_lossage ("invalid %%xn code");
1540 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
1543 cr16_print_operand_address (FILE * file
, machine_mode
/*mode*/, rtx addr
)
1545 enum cr16_addrtype addrtype
;
1546 struct cr16_address address
;
1548 /* Decompose the address. Also ask it to treat address as constant. */
1549 addrtype
= cr16_decompose_address (addr
, &address
, 0, TRUE
);
1551 if (address
.disp
&& GET_CODE (address
.disp
) == UNSPEC
)
1561 if (GET_CODE (address
.disp
) == UNSPEC
)
1562 cr16_print_operand (file
, address
.disp
, 0);
1564 output_addr_const (file
, address
.disp
);
1567 fprintf (file
, "0");
1568 fprintf (file
, "(%s)", reg_names
[REGNO (address
.base
)]);
1573 output_addr_const (file
, address
.disp
);
1575 fprintf (file
, "0");
1578 case CR16_INDEX_REGP_REL
:
1579 fprintf (file
, "[%s]", reg_names
[REGNO (address
.index
)]);
1584 if (GET_CODE (address
.disp
) == UNSPEC
)
1585 cr16_print_operand (file
, address
.disp
, 0);
1587 output_addr_const (file
, address
.disp
);
1590 fprintf (file
, "0");
1591 fprintf (file
, "(%s,%s)", reg_names
[REGNO (address
.base
) + 1],
1592 reg_names
[REGNO (address
.base
)]);
1598 /* Add qualifiers to the address expression that was just printed. */
1599 if (flag_pic
< NEAR_PIC
&& address
.code
== 0)
1601 if (address
.data
== DM_FAR
)
1602 /* Addr contains SYMBOL_REF & far data ptr. */
1603 fprintf (file
, "@l");
1604 else if (address
.data
== DM_DEFAULT
)
1605 /* Addr contains SYMBOL_REF & medium data ptr. */
1606 fprintf (file
, "@m");
1607 /* Addr contains SYMBOL_REF & medium data ptr. */
1608 else if (address
.data
== DM_NEAR
)
1609 /* Addr contains SYMBOL_REF & near data ptr. */
1610 fprintf (file
, "@s");
1612 else if (flag_pic
== NEAR_PIC
1613 && (address
.code
== 0) && (address
.data
== DM_FAR
1614 || address
.data
== DM_DEFAULT
1615 || address
.data
== DM_NEAR
))
1617 fprintf (file
, "@l");
1619 else if (flag_pic
== NEAR_PIC
&& address
.code
== 2)
1621 fprintf (file
, "pic");
1623 else if (flag_pic
== NEAR_PIC
&& address
.code
== 1)
1625 fprintf (file
, "@cpic");
1628 else if (flag_pic
== FAR_PIC
&& address
.code
== 2)
1630 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
1631 address ! GOTc tells assembler this symbol is a text-address
1632 This needs to be fixed in such a way that this offset is done
1633 only in the case where an address is being used for indirect jump
1634 or call. Determining the potential usage of loadd is of course not
1635 possible always. Eventually, this has to be fixed in the
1637 fprintf (file
, "GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1639 else if (flag_pic
== FAR_PIC
&& address
.code
== 1)
1641 fprintf (file
, "@cGOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1644 else if (flag_pic
== FAR_PIC
&&
1645 (address
.data
== DM_FAR
|| address
.data
== DM_DEFAULT
1646 || address
.data
== DM_NEAR
))
1648 fprintf (file
, "@GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1652 /* Machine description helper functions. */
1654 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
1655 When push_or_pop is zero -> string for push instructions of prologue.
1656 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1657 Relies on the assumptions:
1658 1. RA is the last register to be saved.
1659 2. The maximal value of the counter is MAX_COUNT. */
1661 cr16_prepare_push_pop_string (int push_or_pop
)
1663 /* j is the number of registers being saved, takes care that there won't be
1664 more than 8 in one push/pop instruction. */
1666 /* For the register mask string. */
1667 static char one_inst_str
[50];
1669 /* i is the index of current_frame_info.save_regs[], going from 0 until
1670 current_frame_info.last_reg_to_save. */
1676 /* For reversing on the push instructions if there are more than one. */
1679 return_str
= (char *) xmalloc (160);
1680 temp_str
= (char *) xmalloc (160);
1683 memset (return_str
, 0, 3);
1686 while (i
<= current_frame_info
.last_reg_to_save
)
1688 /* Prepare mask for one instruction. */
1689 one_inst_str
[0] = 0;
1691 /* To count number of words in one instruction. */
1695 while ((word_cnt
< MAX_COUNT
)
1696 && (i
<= current_frame_info
.last_reg_to_save
))
1698 /* For each non consecutive save register,
1699 a new instruction shall be generated. */
1700 if (!current_frame_info
.save_regs
[i
])
1702 /* Move to next reg and break. */
1707 if (i
== RETURN_ADDRESS_REGNUM
)
1711 /* Check especially if adding 2 does not cross the MAX_COUNT. */
1712 if ((word_cnt
+ ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2))
1715 /* Increase word count by 2 for long registers except RA. */
1716 word_cnt
+= ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2);
1721 /* No need to generate any instruction as
1722 no register or RA needs to be saved. */
1723 if ((word_cnt
== 0) && (print_ra
== 0))
1726 /* Now prepare the instruction operands. */
1729 sprintf (one_inst_str
, "$%d, %s", word_cnt
, reg_names
[start_reg
]);
1731 strcat (one_inst_str
, ", ra");
1734 strcat (one_inst_str
, "ra");
1736 if (push_or_pop
== 1)
1738 /* Pop instruction. */
1739 if (print_ra
&& !cr16_interrupt_function_p ()
1740 && !crtl
->calls_eh_return
)
1741 /* Print popret if RA is saved and its not a interrupt
1743 strcpy (temp_str
, "\n\tpopret\t");
1745 strcpy (temp_str
, "\n\tpop\t");
1747 strcat (temp_str
, one_inst_str
);
1749 /* Add the pop instruction list. */
1750 strcat (return_str
, temp_str
);
1754 /* Push instruction. */
1755 strcpy (temp_str
, "\n\tpush\t");
1756 strcat (temp_str
, one_inst_str
);
1758 /* We need to reverse the order of the instructions if there
1759 are more than one. (since the pop will not be reversed in
1761 strcat (temp_str
, return_str
);
1762 strcpy (return_str
, temp_str
);
1766 if (push_or_pop
== 1)
1769 if (cr16_interrupt_function_p ())
1770 strcat (return_str
, "\n\tretx\n");
1771 else if (crtl
->calls_eh_return
)
1773 /* Add stack adjustment before returning to exception handler
1774 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
1775 strcat (return_str
, "\n\taddd\t (r5, r4), (sp)\t\n");
1776 strcat (return_str
, "\n\tjump\t (ra)\n");
1778 /* But before anything else, undo the adjustment addition done in
1779 cr16_expand_epilogue (). */
1780 strcpy (temp_str
, "\n\tsubd\t (r5, r4), (sp)\t\n");
1781 strcat (temp_str
, return_str
);
1782 strcpy (return_str
, temp_str
);
1784 else if (!FUNC_IS_NORETURN_P (current_function_decl
)
1785 && !(current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]))
1786 strcat (return_str
, "\n\tjump\t (ra)\n");
1789 /* Skip the newline and the tab in the start of return_str. */
1795 /* Generate DWARF2 annotation for multi-push instruction. */
1797 cr16_create_dwarf_for_multi_push (rtx insn
)
1799 rtx dwarf
, reg
, tmp
;
1800 int i
, j
, from
, to
, word_cnt
, dwarf_par_index
, inc
;
1802 int num_regs
= 0, offset
= 0, split_here
= 0, total_push_bytes
= 0;
1804 for (i
= 0; i
<= current_frame_info
.last_reg_to_save
; ++i
)
1806 if (current_frame_info
.save_regs
[i
])
1809 if (i
< CR16_FIRST_DWORD_REGISTER
)
1810 total_push_bytes
+= 2;
1812 total_push_bytes
+= 4;
1819 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (num_regs
+ 1));
1820 dwarf_par_index
= num_regs
;
1822 from
= current_frame_info
.last_reg_to_save
+ 1;
1823 to
= current_frame_info
.last_reg_to_save
;
1826 for (i
= current_frame_info
.last_reg_to_save
; i
>= 0;)
1828 if (!current_frame_info
.save_regs
[i
] || 0 == i
|| split_here
)
1830 /* This block of regs is pushed in one instruction. */
1831 if (0 == i
&& current_frame_info
.save_regs
[i
])
1834 for (j
= to
; j
>= from
; --j
)
1836 if (j
< CR16_FIRST_DWORD_REGISTER
)
1846 reg
= gen_rtx_REG (mode
, j
);
1848 tmp
= gen_rtx_SET (gen_frame_mem (mode
,
1850 (Pmode
, stack_pointer_rtx
,
1851 total_push_bytes
- offset
)),
1853 RTX_FRAME_RELATED_P (tmp
) = 1;
1854 XVECEXP (dwarf
, 0, dwarf_par_index
--) = tmp
;
1863 if (i
!= RETURN_ADDRESS_REGNUM
)
1865 inc
= (i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2;
1866 if (word_cnt
+ inc
>= MAX_COUNT
|| FRAME_POINTER_REGNUM
== i
)
1878 tmp
= gen_rtx_SET (stack_pointer_rtx
,
1879 gen_rtx_PLUS (SImode
, stack_pointer_rtx
,
1880 GEN_INT (-offset
)));
1881 RTX_FRAME_RELATED_P (tmp
) = 1;
1882 XVECEXP (dwarf
, 0, 0) = tmp
;
1884 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, dwarf
);
1888 CompactRISC CR16 Architecture stack layout:
1890 0 +---------------------
1895 +==================== Sp (x) = Ap (x+1)
1896 A | Args for functions
1897 | | called by X and Dynamically
1898 | | Dynamic allocations allocated and
1899 | | (alloca, variable deallocated
1900 Stack | length arrays).
1901 grows +-------------------- Fp (x)
1902 down| | Local variables of X
1903 ward| +--------------------
1904 | | Regs saved for X-1
1905 | +==================== Sp (x-1) = Ap (x)
1908 +-------------------- Fp (x-1)
1914 cr16_expand_prologue (void)
1918 cr16_compute_frame ();
1919 cr16_compute_save_regs ();
1921 /* If there is no need in push and adjustment to sp, return. */
1922 if ((current_frame_info
.total_size
+ current_frame_info
.reg_size
) == 0)
1925 if (current_frame_info
.last_reg_to_save
!= -1)
1927 /* If there are registers to push. */
1928 insn
= emit_insn (gen_push_for_prologue
1929 (GEN_INT (current_frame_info
.reg_size
)));
1930 cr16_create_dwarf_for_multi_push (insn
);
1931 RTX_FRAME_RELATED_P (insn
) = 1;
1935 if (current_frame_info
.total_size
> 0)
1937 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1938 GEN_INT (-current_frame_info
.total_size
)));
1939 RTX_FRAME_RELATED_P (insn
) = 1;
1942 if (frame_pointer_needed
)
1944 /* Initialize the frame pointer with the value of the stack pointer
1945 pointing now to the locals. */
1946 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1950 /* Generate insn that updates the stack for local variables and padding
1951 for registers we save. - Generate the appropriate return insn. */
1953 cr16_expand_epilogue (void)
1957 /* Nonzero if we need to return and pop only RA. This will generate a
1958 different insn. This differentiate is for the peepholes for call as
1959 last statement in function. */
1960 int only_popret_RA
= (current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]
1961 && (current_frame_info
.reg_size
1962 == CR16_UNITS_PER_DWORD
));
1964 if (frame_pointer_needed
)
1966 /* Restore the stack pointer with the frame pointers value. */
1967 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
1970 if (current_frame_info
.total_size
> 0)
1972 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1973 GEN_INT (current_frame_info
.total_size
)));
1974 RTX_FRAME_RELATED_P (insn
) = 1;
1977 if (crtl
->calls_eh_return
)
1979 /* Add this here so that (r5, r4) is actually loaded with the adjustment
1980 value; otherwise, the load might be optimized away...
1981 NOTE: remember to subtract the adjustment before popping the regs
1982 and add it back before returning. */
1983 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1984 EH_RETURN_STACKADJ_RTX
));
1987 if (cr16_interrupt_function_p ())
1989 insn
= emit_jump_insn (gen_interrupt_return ());
1990 RTX_FRAME_RELATED_P (insn
) = 1;
1992 else if (crtl
->calls_eh_return
)
1994 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
1995 insn
= emit_jump_insn (gen_pop_and_popret_return
1996 (GEN_INT (current_frame_info
.reg_size
)));
1997 RTX_FRAME_RELATED_P (insn
) = 1;
1999 else if (current_frame_info
.last_reg_to_save
== -1)
2000 /* Nothing to pop. */
2001 /* Don't output jump for interrupt routine, only retx. */
2002 emit_jump_insn (gen_jump_return ());
2003 else if (only_popret_RA
)
2005 insn
= emit_jump_insn (gen_popret_RA_return ());
2006 RTX_FRAME_RELATED_P (insn
) = 1;
2010 insn
= emit_jump_insn (gen_pop_and_popret_return
2011 (GEN_INT (current_frame_info
.reg_size
)));
2012 RTX_FRAME_RELATED_P (insn
) = 1;
2016 /* Implements FRAME_POINTER_REQUIRED. */
2018 cr16_frame_pointer_required (void)
2020 return (cfun
->calls_alloca
|| crtl
->calls_eh_return
2021 || cfun
->has_nonlocal_label
|| crtl
->calls_eh_return
);
2025 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
2027 return (to
== STACK_POINTER_REGNUM
? !frame_pointer_needed
: true);
2031 /* A C compound statement that attempts to replace X with
2032 a valid memory address for an operand of mode MODE. WIN
2033 will be a C statement label elsewhere in the code.
2034 X will always be the result of a call to break_out_memory_refs (),
2035 and OLDX will be the operand that was given to that function to
2037 The code generated by this macro should not alter the
2038 substructure of X. If it transforms X into a more legitimate form,
2039 it should assign X (which will always be a C variable) a new value. */
2041 cr16_legitimize_address (rtx x
, rtx orig_x ATTRIBUTE_UNUSED
,
2042 machine_mode mode ATTRIBUTE_UNUSED
)
2045 return legitimize_pic_address (orig_x
, mode
, NULL_RTX
);
2050 /* Implement TARGET_LEGITIMATE_CONSTANT_P
2051 Nonzero if X is a legitimate constant for an immediate
2052 operand on the target machine. You can assume that X
2053 satisfies CONSTANT_P. In cr16c treat legitimize float
2054 constant as an immediate operand. */
2056 cr16_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
,
2057 rtx x ATTRIBUTE_UNUSED
)
2063 notice_update_cc (rtx exp
)
2065 if (GET_CODE (exp
) == SET
)
2067 /* Jumps do not alter the cc's. */
2068 if (SET_DEST (exp
) == pc_rtx
)
2071 /* Moving register or memory into a register:
2072 it doesn't alter the cc's, but it might invalidate
2073 the RTX's which we remember the cc's came from.
2074 (Note that moving a constant 0 or 1 MAY set the cc's). */
2075 if (REG_P (SET_DEST (exp
))
2076 && (REG_P (SET_SRC (exp
)) || GET_CODE (SET_SRC (exp
)) == MEM
))
2081 /* Moving register into memory doesn't alter the cc's.
2082 It may invalidate the RTX's which we remember the cc's came from. */
2083 if (GET_CODE (SET_DEST (exp
)) == MEM
&& REG_P (SET_SRC (exp
)))
2094 cr16_unwind_word_mode (void)
2099 /* Helper function for md file. This function is used to emit arithmetic
2100 DI instructions. The argument "num" decides which instruction to be
2103 cr16_emit_add_sub_di (rtx
*operands
, enum rtx_code code
)
2109 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2110 hi0_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 4);
2111 hi1_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 6);
2113 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2114 hi0_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 4);
2115 hi1_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 6);
2121 output_asm_insn ("addd\t%1, %0", lo_op
) ;
2122 output_asm_insn ("addcw\t%1, %0", hi0_op
) ;
2123 output_asm_insn ("addcw\t%1, %0", hi1_op
) ;
2128 output_asm_insn ("subd\t%1, %0", lo_op
) ;
2129 output_asm_insn ("subcw\t%1, %0", hi0_op
) ;
2130 output_asm_insn ("subcw\t%1, %0", hi1_op
) ;
2141 /* Helper function for md file. This function is used to emit logical
2142 DI instructions. The argument "num" decides which instruction to be
2145 cr16_emit_logical_di (rtx
*operands
, enum rtx_code code
)
2150 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2151 hi_op
[0] = simplify_gen_subreg (SImode
, operands
[0], DImode
, 4);
2153 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2154 hi_op
[1] = simplify_gen_subreg (SImode
, operands
[2], DImode
, 4);
2160 output_asm_insn ("andd\t%1, %0", lo_op
) ;
2161 output_asm_insn ("andd\t%1, %0", hi_op
) ;
2166 output_asm_insn ("ord\t%1, %0", lo_op
) ;
2167 output_asm_insn ("ord\t%1, %0", hi_op
) ;
2172 output_asm_insn ("xord\t%1, %0", lo_op
) ;
2173 output_asm_insn ("xord\t%1, %0", hi_op
) ;
2183 /* Initialize 'targetm' variable which contains pointers to functions
2184 and data relating to the target machine. */
2186 struct gcc_target targetm
= TARGET_INITIALIZER
;