1 /* Output routines for CR16 processor.
2 Copyright (C) 2012-2021 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/>. */
21 #define IN_TARGET_CODE 1
25 #include "coretypes.h"
30 #include "stringpool.h"
37 #include "diagnostic-core.h"
38 #include "stor-layout.h"
40 #include "conditions.h"
45 /* This file should be included last. */
46 #include "target-def.h"
50 /* Maximum number of register used for passing parameters. */
51 #define MAX_REG_FOR_PASSING_ARGS 6
53 /* Minimum number register used for passing parameters. */
54 #define MIN_REG_FOR_PASSING_ARGS 2
56 /* The maximum count of words supported in the assembly of the architecture in
57 a push/pop instruction. */
60 /* Predicate is true if the current function is a 'noreturn' function,
61 i.e. it is qualified as volatile. */
62 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
64 /* Predicate that holds when we need to save registers even for 'noreturn'
65 functions, to accommodate for unwinding. */
66 #define MUST_SAVE_REGS_P() \
67 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
69 /* Nonzero if the rtx X is a signed const int of n bits. */
70 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
71 ((GET_CODE (X) == CONST_INT \
72 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
74 /* Nonzero if the rtx X is an unsigned const int of n bits. */
75 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
76 ((GET_CODE (X) == CONST_INT \
77 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
79 /* Structure for stack computations. */
81 /* variable definitions in the struture
82 args_size Number of bytes saved on the stack for local
85 reg_size Number of bytes saved on the stack for
88 total_size The sum of 2 sizes: locals vars and padding byte
89 for saving the registers. Used in expand_prologue()
92 last_reg_to_save Will hold the number of the last register the
93 prologue saves, -1 if no register is saved
95 save_regs[16] Each object in the array is a register number.
96 Mark 1 for registers that need to be saved
98 num_regs Number of registers saved
100 initialized Non-zero if frame size already calculated, not
103 function_makes_calls Does the function make calls ? not used yet. */
105 struct cr16_frame_info
107 unsigned long var_size
;
108 unsigned long args_size
;
109 unsigned int reg_size
;
110 unsigned long total_size
;
111 long last_reg_to_save
;
112 long save_regs
[FIRST_PSEUDO_REGISTER
];
115 int function_makes_calls
;
118 /* Current frame information calculated by cr16_compute_frame_size. */
119 static struct cr16_frame_info current_frame_info
;
121 /* Static Variables. */
123 /* Data model that was supplied by user via command line option
124 This will be overridden in case of invalid combination
125 of core and data model options are supplied. */
126 static enum data_model_type data_model
= DM_DEFAULT
;
128 /* TARGETM Function Prototypes and forward declarations */
129 static void cr16_print_operand (FILE *, rtx
, int);
130 static void cr16_print_operand_address (FILE *, machine_mode
, rtx
);
132 /* Stack layout and calling conventions. */
133 #undef TARGET_STRUCT_VALUE_RTX
134 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
135 #undef TARGET_RETURN_IN_MEMORY
136 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
138 /* Target-specific uses of '__attribute__'. */
139 #undef TARGET_ATTRIBUTE_TABLE
140 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
141 #undef TARGET_NARROW_VOLATILE_BITFIELD
142 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
145 #undef TARGET_UNWIND_WORD_MODE
146 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
148 /* Override Options. */
149 #undef TARGET_OPTION_OVERRIDE
150 #define TARGET_OPTION_OVERRIDE cr16_override_options
152 /* Conditional register usuage. */
153 #undef TARGET_CONDITIONAL_REGISTER_USAGE
154 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
156 /* Controlling register spills. */
157 #undef TARGET_CLASS_LIKELY_SPILLED_P
158 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
160 /* Passing function arguments. */
161 #undef TARGET_PUSH_ARGUMENT
162 #define TARGET_PUSH_ARGUMENT hook_bool_uint_true
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
183 #define TARGET_LRA_P hook_bool_void_false
185 /* Returning function value. */
186 #undef TARGET_FUNCTION_VALUE
187 #define TARGET_FUNCTION_VALUE cr16_function_value
188 #undef TARGET_LIBCALL_VALUE
189 #define TARGET_LIBCALL_VALUE cr16_libcall_value
190 #undef TARGET_FUNCTION_VALUE_REGNO_P
191 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
193 /* printing the values. */
194 #undef TARGET_PRINT_OPERAND
195 #define TARGET_PRINT_OPERAND cr16_print_operand
196 #undef TARGET_PRINT_OPERAND_ADDRESS
197 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
199 /* Relative costs of operations. */
200 #undef TARGET_ADDRESS_COST
201 #define TARGET_ADDRESS_COST cr16_address_cost
202 #undef TARGET_REGISTER_MOVE_COST
203 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
204 #undef TARGET_MEMORY_MOVE_COST
205 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
207 #undef TARGET_CONSTANT_ALIGNMENT
208 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
210 /* Table of machine attributes. */
211 static const struct attribute_spec cr16_attribute_table
[] = {
212 /* ISRs have special prologue and epilogue requirements. */
213 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
214 affects_type_identity, handler, exclude }. */
215 {"interrupt", 0, 0, false, true, true, false, NULL
, NULL
},
216 {NULL
, 0, 0, false, false, false, false, NULL
, NULL
}
219 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
220 .?byte directive along with @c is not understood by assembler.
221 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
222 as TARGET_ASM_ALIGNED_xx_OP. */
223 #undef TARGET_ASM_UNALIGNED_HI_OP
224 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
225 #undef TARGET_ASM_UNALIGNED_SI_OP
226 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
227 #undef TARGET_ASM_UNALIGNED_DI_OP
228 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
230 #undef TARGET_HARD_REGNO_NREGS
231 #define TARGET_HARD_REGNO_NREGS cr16_hard_regno_nregs
232 #undef TARGET_HARD_REGNO_MODE_OK
233 #define TARGET_HARD_REGNO_MODE_OK cr16_hard_regno_mode_ok
234 #undef TARGET_MODES_TIEABLE_P
235 #define TARGET_MODES_TIEABLE_P cr16_modes_tieable_p
237 /* Target hook implementations. */
239 /* Implements hook TARGET_RETURN_IN_MEMORY. */
241 cr16_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
243 const HOST_WIDE_INT size
= int_size_in_bytes (type
);
244 return ((size
== -1) || (size
> 8));
247 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
249 cr16_class_likely_spilled_p (reg_class_t rclass
)
251 if ((rclass
) == SHORT_REGS
|| (rclass
) == DOUBLE_BASE_REGS
252 || (rclass
) == LONG_REGS
|| (rclass
) == GENERAL_REGS
)
259 cr16_return_pops_args (tree
, tree
, poly_int64
)
264 /* Returns true if data model selected via command line option
265 is same as function argument. */
267 cr16_is_data_model (enum data_model_type model
)
269 return (model
== data_model
);
272 /* Parse relevant options and override. */
274 cr16_override_options (void)
276 /* Disable -fdelete-null-pointer-checks option for CR16 target.
277 Programs which rely on NULL pointer dereferences _not_ halting the
278 program may not work properly with this option. So disable this
280 flag_delete_null_pointer_checks
= 0;
282 /* FIXME: To avoid spill_failure ICE during exception handling,
283 * disable cse_fllow_jumps. The spill error occurs when compiler
284 * can't find a suitable candidate in GENERAL_REGS class to reload
286 * Need to find a better way of avoiding this situation. */
288 flag_cse_follow_jumps
= 0;
290 /* If -fpic option, data_model == DM_FAR. */
291 if (flag_pic
== NEAR_PIC
)
296 /* The only option we want to examine is data model option. */
299 if (strcmp (cr16_data_model
, "medium") == 0)
300 data_model
= DM_DEFAULT
;
301 else if (strcmp (cr16_data_model
, "near") == 0)
302 data_model
= DM_NEAR
;
303 else if (strcmp (cr16_data_model
, "far") == 0)
308 error ("data-model=far not valid for cr16c architecture");
311 error ("invalid data model option %<-mdata-model=%s%>",
315 data_model
= DM_DEFAULT
;
318 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
320 cr16_conditional_register_usage (void)
324 fixed_regs
[12] = call_used_regs
[12] = 1;
328 /* Stack layout and calling conventions routines. */
330 /* Return nonzero if the current function being compiled is an interrupt
331 function as specified by the "interrupt" attribute. */
333 cr16_interrupt_function_p (void)
337 attributes
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
338 return (lookup_attribute ("interrupt", attributes
) != NULL_TREE
);
341 /* Compute values for the array current_frame_info.save_regs and the variable
342 current_frame_info.reg_size. The index of current_frame_info.save_regs
343 is numbers of register, each will get 1 if we need to save it in the
344 current function, 0 if not. current_frame_info.reg_size is the total sum
345 of the registers being saved. */
347 cr16_compute_save_regs (void)
351 /* Initialize here so in case the function is no-return it will be -1. */
352 current_frame_info
.last_reg_to_save
= -1;
354 /* Initialize the number of bytes to be saved. */
355 current_frame_info
.reg_size
= 0;
357 /* No need to save any registers if the function never returns. */
358 if (FUNC_IS_NORETURN_P (current_function_decl
) && !MUST_SAVE_REGS_P ())
361 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
363 if (fixed_regs
[regno
])
365 current_frame_info
.save_regs
[regno
] = 0;
369 /* If this reg is used and not call-used (except RA), save it. */
370 if (cr16_interrupt_function_p ())
372 if (!crtl
->is_leaf
&& call_used_or_fixed_reg_p (regno
))
373 /* This is a volatile reg in a non-leaf interrupt routine - save
374 it for the sake of its sons. */
375 current_frame_info
.save_regs
[regno
] = 1;
376 else if (df_regs_ever_live_p (regno
))
377 /* This reg is used - save it. */
378 current_frame_info
.save_regs
[regno
] = 1;
380 /* This reg is not used, and is not a volatile - don't save. */
381 current_frame_info
.save_regs
[regno
] = 0;
385 /* If this reg is used and not call-used (except RA), save it. */
386 if (df_regs_ever_live_p (regno
)
387 && (!call_used_or_fixed_reg_p (regno
)
388 || regno
== RETURN_ADDRESS_REGNUM
))
389 current_frame_info
.save_regs
[regno
] = 1;
391 current_frame_info
.save_regs
[regno
] = 0;
395 /* Save registers so the exception handler can modify them. */
396 if (crtl
->calls_eh_return
)
402 regno
= EH_RETURN_DATA_REGNO (i
);
403 if (INVALID_REGNUM
== regno
)
405 current_frame_info
.save_regs
[regno
] = 1;
409 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
410 if (current_frame_info
.save_regs
[regno
] == 1)
412 current_frame_info
.last_reg_to_save
= regno
;
413 if (regno
>= CR16_FIRST_DWORD_REGISTER
)
414 current_frame_info
.reg_size
+= CR16_UNITS_PER_DWORD
;
416 current_frame_info
.reg_size
+= UNITS_PER_WORD
;
420 /* Compute the size of the local area and the size to be adjusted by the
421 prologue and epilogue. */
423 cr16_compute_frame (void)
425 /* For aligning the local variables. */
426 int stack_alignment
= STACK_BOUNDARY
/ BITS_PER_UNIT
;
429 /* Padding needed for each element of the frame. */
430 current_frame_info
.var_size
= get_frame_size ();
432 /* Align to the stack alignment. */
433 padding_locals
= current_frame_info
.var_size
% stack_alignment
;
435 padding_locals
= stack_alignment
- padding_locals
;
437 current_frame_info
.var_size
+= padding_locals
;
438 current_frame_info
.total_size
439 = (current_frame_info
.var_size
440 + (ACCUMULATE_OUTGOING_ARGS
441 ? (HOST_WIDE_INT
) crtl
->outgoing_args_size
: 0));
444 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
446 cr16_initial_elimination_offset (int from
, int to
)
448 /* Compute this since we need to use current_frame_info.reg_size. */
449 cr16_compute_save_regs ();
451 /* Compute this since we need to use current_frame_info.var_size. */
452 cr16_compute_frame ();
454 if (((from
) == FRAME_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
455 return (ACCUMULATE_OUTGOING_ARGS
456 ? (HOST_WIDE_INT
) crtl
->outgoing_args_size
: 0);
457 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == FRAME_POINTER_REGNUM
))
458 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
);
459 else if (((from
) == ARG_POINTER_REGNUM
) && ((to
) == STACK_POINTER_REGNUM
))
460 return (current_frame_info
.reg_size
+ current_frame_info
.var_size
461 + (ACCUMULATE_OUTGOING_ARGS
462 ? (HOST_WIDE_INT
) crtl
->outgoing_args_size
: 0));
467 /* Register Usage. */
469 /* Return the class number of the smallest class containing reg number REGNO.
470 This could be a conditional expression or could index an array. */
472 cr16_regno_reg_class (int regno
)
474 if ((regno
>= 0) && (regno
< CR16_FIRST_DWORD_REGISTER
))
477 if ((regno
>= CR16_FIRST_DWORD_REGISTER
) && (regno
< FIRST_PSEUDO_REGISTER
))
483 /* Implement TARGET_HARD_REGNO_NREGS. */
486 cr16_hard_regno_nregs (unsigned int regno
, machine_mode mode
)
488 if (regno
>= CR16_FIRST_DWORD_REGISTER
)
489 return CEIL (GET_MODE_SIZE (mode
), CR16_UNITS_PER_DWORD
);
490 return CEIL (GET_MODE_SIZE (mode
), UNITS_PER_WORD
);
493 /* Implement TARGET_HARD_REGNO_MODE_OK. On the CR16 architecture, all
494 registers can hold all modes, except that double precision floats
495 (and double ints) must fall on even-register boundaries. */
498 cr16_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
500 if ((GET_MODE_SIZE (mode
) >= 4) && (regno
== 11))
503 if (mode
== DImode
|| mode
== DFmode
)
505 if ((regno
> 8) || (regno
& 1))
511 && ((regno
>= 12) && (GET_MODE_SIZE (mode
) < 4 )))
514 /* CC can only hold CCmode values. */
515 if (GET_MODE_CLASS (mode
) == MODE_CC
)
520 /* Implement TARGET_MODES_TIEABLE_P. */
522 cr16_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
524 return GET_MODE_CLASS (mode1
) == GET_MODE_CLASS (mode2
);
527 /* Returns register number for function return value.*/
528 static inline unsigned int
529 cr16_ret_register (void)
534 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
536 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED
,
537 int incoming ATTRIBUTE_UNUSED
)
539 return gen_rtx_REG (Pmode
, cr16_ret_register ());
542 /* Returning function value. */
544 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
546 cr16_function_value_regno_p (const unsigned int regno
)
548 return (regno
== cr16_ret_register ());
551 /* Create an RTX representing the place where a
552 library function returns a value of mode MODE. */
554 cr16_libcall_value (machine_mode mode
,
555 const_rtx func ATTRIBUTE_UNUSED
)
557 return gen_rtx_REG (mode
, cr16_ret_register ());
560 /* Create an RTX representing the place where a
561 function returns a value of data type VALTYPE. */
563 cr16_function_value (const_tree type
,
564 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
565 bool outgoing ATTRIBUTE_UNUSED
)
567 return gen_rtx_REG (TYPE_MODE (type
), cr16_ret_register ());
570 /* Passing function arguments. */
572 /* If enough param regs are available for passing the param of type TYPE return
573 the number of registers needed else 0. */
575 enough_regs_for_param (CUMULATIVE_ARGS
* cum
, const_tree type
,
582 type_size
= GET_MODE_BITSIZE (mode
);
584 type_size
= int_size_in_bytes (type
) * BITS_PER_UNIT
;
586 remaining_size
= BITS_PER_WORD
* (MAX_REG_FOR_PASSING_ARGS
587 - (MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) +
590 /* Any variable which is too big to pass in two registers, will pass on
592 if ((remaining_size
>= type_size
) && (type_size
<= 2 * BITS_PER_WORD
))
593 return (type_size
+ BITS_PER_WORD
- 1) / BITS_PER_WORD
;
598 /* Implement TARGET_FUNCTION_ARG. */
600 cr16_function_arg (cumulative_args_t cum_v
, const function_arg_info
&arg
)
602 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
603 cum
->last_parm_in_reg
= 0;
605 /* function_arg () is called with this type just after all the args have
606 had their registers assigned. The rtx that function_arg returns from
607 this type is supposed to pass to 'gen_call' but currently it is not
609 if (arg
.end_marker_p ())
612 if (targetm
.calls
.must_pass_in_stack (arg
) || (cum
->ints
< 0))
615 if (arg
.mode
== BLKmode
)
617 /* Enable structures that need padding bytes at the end to pass to a
618 function in registers. */
619 if (enough_regs_for_param (cum
, arg
.type
, arg
.mode
) != 0)
621 cum
->last_parm_in_reg
= 1;
622 return gen_rtx_REG (arg
.mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
626 if ((MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
) > MAX_REG_FOR_PASSING_ARGS
)
630 if (enough_regs_for_param (cum
, arg
.type
, arg
.mode
) != 0)
632 cum
->last_parm_in_reg
= 1;
633 return gen_rtx_REG (arg
.mode
, MIN_REG_FOR_PASSING_ARGS
+ cum
->ints
);
640 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
642 cr16_init_cumulative_args (CUMULATIVE_ARGS
* cum
, tree fntype
,
643 rtx libfunc ATTRIBUTE_UNUSED
)
645 tree param
, next_param
;
649 /* Determine if this function has variable arguments. This is indicated by
650 the last argument being 'void_type_mode' if there are no variable
651 arguments. Change here for a different vararg. */
652 for (param
= (fntype
) ? TYPE_ARG_TYPES (fntype
) : 0;
653 param
!= NULL_TREE
; param
= next_param
)
655 next_param
= TREE_CHAIN (param
);
656 if ((next_param
== NULL_TREE
) && (TREE_VALUE (param
) != void_type_node
))
664 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
666 cr16_function_arg_advance (cumulative_args_t cum_v
,
667 const function_arg_info
&arg
)
669 CUMULATIVE_ARGS
* cum
= get_cumulative_args (cum_v
);
671 /* l holds the number of registers required. */
672 int l
= GET_MODE_BITSIZE (arg
.mode
) / BITS_PER_WORD
;
674 /* If the parameter isn't passed on a register don't advance cum. */
675 if (!cum
->last_parm_in_reg
)
678 if (targetm
.calls
.must_pass_in_stack (arg
) || (cum
->ints
< 0))
681 if ((arg
.mode
== SImode
) || (arg
.mode
== HImode
)
682 || (arg
.mode
== QImode
) || (arg
.mode
== DImode
))
689 else if ((arg
.mode
== SFmode
) || (arg
.mode
== DFmode
))
691 else if (arg
.mode
== BLKmode
)
693 if ((l
= enough_regs_for_param (cum
, arg
.type
, arg
.mode
)) != 0)
699 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
700 Return nonzero if N is a register used for passing parameters. */
702 cr16_function_arg_regno_p (int n
)
704 return ((n
<= MAX_REG_FOR_PASSING_ARGS
) && (n
>= MIN_REG_FOR_PASSING_ARGS
));
708 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
709 defined in cr16.h. */
711 /* Helper function to check if is a valid base register that can
714 cr16_addr_reg_p (rtx addr_reg
)
718 if (REG_P (addr_reg
))
720 else if ((GET_CODE (addr_reg
) == SUBREG
)
721 && REG_P (SUBREG_REG (addr_reg
))
722 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg
)))
724 reg
= SUBREG_REG (addr_reg
);
728 if (GET_MODE (reg
) != Pmode
)
734 /* Helper functions: Created specifically for decomposing operand of CONST
735 Recursively look into expression x for code or data symbol.
736 The function expects the expression to contain combination of
737 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
738 LABEL_REF, CONST_INT, (PLUS or MINUS)
741 All other combinations will result in code = -1 and data = ILLEGAL_DM
743 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
744 0 DM_FAR SYMBOL_REF was found and it was far data reference.
745 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
746 1 ILLEGAL_DM LABEL_REF was found.
747 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
749 cr16_decompose_const (rtx x
, int *code
, enum data_model_type
*data
,
754 switch (GET_CODE (x
))
757 *code
= SYMBOL_REF_FUNCTION_P (x
) ? 2 : 0;
758 /* 2 indicates func sym. */
761 if (CR16_TARGET_DATA_NEAR
)
763 else if (CR16_TARGET_DATA_MEDIUM
)
765 else if (CR16_TARGET_DATA_FAR
)
768 /* This will be used only for printing
769 the qualifier. This call is (may be)
770 made by cr16_print_operand_address. */
773 /* This call is (may be) made by
774 cr16_legitimate_address_p. */
781 /* 1 - indicates non-function symbol. */
787 /* Look into the tree nodes. */
788 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
789 cr16_decompose_const (XEXP (x
, 1), code
, data
, treat_as_const
);
790 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
791 cr16_decompose_const (XEXP (x
, 0), code
, data
, treat_as_const
);
799 This function decomposes the address returns the type of address
800 as defined in enum cr16_addrtype. It also fills the parameter *out.
801 The decomposed address can be used for two purposes. One to
802 check if the address is valid and second to print the address
805 Following tables list valid address supported in CR16C/C+ architectures.
807 aN : Absoulte address N-bit address
808 R : One 16-bit register
809 RP : Consecutive two 16-bit registers or one 32-bit register
810 I : One 32-bit register
811 dispN : Signed displacement of N-bits
813 ----Code addresses----
815 disp9 : CR16_ABSOLUTE (disp)
816 disp17 : CR16_ABSOLUTE (disp)
817 disp25 : CR16_ABSOLUTE (disp)
818 RP + disp25 : CR16_REGP_REL (base, disp)
821 RP : CR16_REGP_REL (base, disp=0)
822 a24 : CR16_ABSOLUTE (disp)
824 ----Data addresses----
825 a20 : CR16_ABSOLUTE (disp) near (1M)
826 a24 : CR16_ABSOLUTE (disp) medium (16M)
827 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
828 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
829 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
830 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
831 I : *** Valid but port does not support this
832 I + a20 : *** Valid but port does not support this
833 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
834 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
836 Decomposing Data model in case of absolute address.
838 Target Option Address type Resultant Data ref type
839 ---------------------- ------------ -----------------------
840 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
841 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
842 CR16_TARGET_MODEL_NEAR ABS24 Invalid
843 CR16_TARGET_MODEL_NEAR IMM32 Invalid
845 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
846 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
847 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
848 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
850 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
851 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
852 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
853 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
855 cr16_decompose_address (rtx addr
, struct cr16_address
*out
,
856 bool debug_print
, bool treat_as_const
)
858 rtx base
= NULL_RTX
, disp
= NULL_RTX
, index
= NULL_RTX
;
859 enum data_model_type data
= ILLEGAL_DM
;
861 enum cr16_addrtype retval
= CR16_INVALID
;
863 switch (GET_CODE (addr
))
866 /* Absolute address (known at compile time). */
869 fprintf (stderr
, "\ncode:%d", code
);
874 fprintf (stderr
, "\ndisp:");
878 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
882 fprintf (stderr
, "\ndata:%d", data
);
883 retval
= CR16_ABSOLUTE
;
885 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 24))
887 if (!CR16_TARGET_DATA_NEAR
)
891 fprintf (stderr
, "\ndata:%d", data
);
892 retval
= CR16_ABSOLUTE
;
895 return CR16_INVALID
; /* ABS24 is not support in NEAR model. */
902 /* A CONST is an expression of PLUS or MINUS with
903 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
904 result of assembly-time arithmetic computation. */
905 retval
= CR16_ABSOLUTE
;
907 /* Call the helper function to check the validity. */
908 cr16_decompose_const (XEXP (addr
, 0), &code
, &data
, treat_as_const
);
909 if ((code
== 0) && (data
== ILLEGAL_DM
))
910 /* CONST is not valid code or data address. */
914 fprintf (stderr
, "\ndisp:");
916 fprintf (stderr
, "\ncode:%d", code
);
917 fprintf (stderr
, "\ndata:%d", data
);
922 retval
= CR16_ABSOLUTE
;
924 /* 1 - indicates non-function symbol. */
928 fprintf (stderr
, "\ndisp:");
930 fprintf (stderr
, "\ncode:%d", code
);
935 /* Absolute address (known at link time). */
936 retval
= CR16_ABSOLUTE
;
938 /* This is a code address if symbol_ref is a function. */
939 /* 2 indicates func sym. */
940 code
= SYMBOL_REF_FUNCTION_P (addr
) ? 2 : 0;
943 fprintf (stderr
, "\ndisp:");
945 fprintf (stderr
, "\ncode:%d", code
);
947 /* If not function ref then check if valid data ref. */
950 if (CR16_TARGET_DATA_NEAR
)
952 else if (CR16_TARGET_DATA_MEDIUM
)
954 else if (CR16_TARGET_DATA_FAR
)
957 /* This will be used only for printing the
958 qualifier. This call is (may be) made
959 by cr16_print_operand_address. */
962 /* This call is (may be) made by
963 cr16_legitimate_address_p. */
970 fprintf (stderr
, "\ndata:%d", data
);
975 /* Register relative address. */
976 /* Assume REG fits in a single register. */
977 retval
= CR16_REG_REL
;
978 if (GET_MODE_BITSIZE (GET_MODE (addr
)) > BITS_PER_WORD
)
979 if (!LONG_REG_P (REGNO (addr
)))
980 /* REG will result in reg pair. */
981 retval
= CR16_REGP_REL
;
985 fprintf (stderr
, "\nbase:");
991 switch (GET_CODE (XEXP (addr
, 0)))
996 /* All Reg relative addresses having a displacement needs
997 to fit in 20-bits. */
998 disp
= XEXP (addr
, 1);
1001 fprintf (stderr
, "\ndisp:");
1004 switch (GET_CODE (XEXP (addr
, 1)))
1007 /* Shall fit in 20-bits. */
1008 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
1009 return CR16_INVALID
;
1012 fprintf (stderr
, "\ncode:%d", code
);
1016 switch (XINT (XEXP (addr
, 1), 1))
1018 case UNSPEC_LIBRARY_OFFSET
:
1027 /* This is also a valid expression for address.
1028 However, we cannot ascertain if the resultant
1029 displacement will be valid 20-bit value. Therefore,
1030 lets not allow such an expression for now. This will
1031 be updated when we find a way to validate this
1032 expression as legitimate address.
1033 Till then fall through CR16_INVALID. */
1035 return CR16_INVALID
;
1038 /* Now check if REG can fit into single or pair regs. */
1039 retval
= CR16_REG_REL
;
1040 base
= XEXP (addr
, 0);
1043 fprintf (stderr
, "\nbase:");
1046 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr
, 0)))) > BITS_PER_WORD
)
1048 if (!LONG_REG_P (REGNO ((XEXP (addr
, 0)))))
1049 /* REG will result in reg pair. */
1050 retval
= CR16_REGP_REL
;
1064 Check if the operand 1 is valid index register. */
1067 fprintf (stderr
, "\ndata:%d", data
);
1068 switch (GET_CODE (XEXP (addr
, 1)))
1072 if (!REG_OK_FOR_INDEX_P (XEXP (addr
, 1)))
1073 return CR16_INVALID
;
1074 /* OK. REG is a valid index register. */
1075 index
= XEXP (addr
, 1);
1078 fprintf (stderr
, "\nindex:");
1083 return CR16_INVALID
;
1085 /* Check if operand 0 of operand 0 is REGP. */
1086 switch (GET_CODE (XEXP (XEXP (addr
, 0), 0)))
1090 /* Now check if REG is a REGP and not in LONG regs. */
1091 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr
, 0), 0)))
1094 if (REGNO (XEXP (XEXP (addr
, 0), 0))
1095 >= CR16_FIRST_DWORD_REGISTER
)
1096 return CR16_INVALID
;
1097 base
= XEXP (XEXP (addr
, 0), 0);
1100 fprintf (stderr
, "\nbase:");
1105 return CR16_INVALID
;
1108 return CR16_INVALID
;
1110 /* Now check if the operand 1 of operand 0 is const_int. */
1111 if (GET_CODE (XEXP (XEXP (addr
, 0), 1)) == CONST_INT
)
1113 disp
= XEXP (XEXP (addr
, 0), 1);
1116 fprintf (stderr
, "\ndisp:");
1119 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp
), 20))
1120 return CR16_INVALID
;
1123 return CR16_INVALID
;
1124 retval
= CR16_INDEX_REGP_REL
;
1127 return CR16_INVALID
;
1132 return CR16_INVALID
;
1135 /* Check if the base and index registers are valid. */
1136 if (base
&& !(cr16_addr_reg_p (base
)))
1137 return CR16_INVALID
;
1138 if (base
&& !(CR16_REG_OK_FOR_BASE_P (base
)))
1139 return CR16_INVALID
;
1140 if (index
&& !(REG_OK_FOR_INDEX_P (index
)))
1141 return CR16_INVALID
;
1143 /* Write the decomposition to out parameter. */
1153 /* Return non-zero value if 'x' is legitimate PIC operand
1154 when generating PIC code. */
1156 legitimate_pic_operand_p (rtx x
)
1158 switch (GET_CODE (x
))
1165 /* REVISIT: Use something like symbol_referenced_p. */
1166 if (GET_CODE (XEXP (x
, 0)) == PLUS
1167 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
1168 || GET_CODE (XEXP (XEXP (x
, 0), 0)) == LABEL_REF
)
1169 && (GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
))
1173 return legitimate_pic_operand_p (XEXP (x
, 0));
1180 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
1182 Input Output (-f pic) Output (-f PIC)
1185 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
1187 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
1189 NOTE: @BRO is added using unspec:BRO
1190 NOTE: @GOT is added using unspec:GOT. */
1192 legitimize_pic_address (rtx orig
, machine_mode mode ATTRIBUTE_UNUSED
,
1195 /* First handle a simple SYMBOL_REF or LABEL_REF. */
1196 if (GET_CODE (orig
) == SYMBOL_REF
|| GET_CODE (orig
) == LABEL_REF
)
1199 reg
= gen_reg_rtx (Pmode
);
1201 if (flag_pic
== NEAR_PIC
)
1203 /* Unspec to handle -fpic option. */
1204 emit_insn (gen_unspec_bro_addr (reg
, orig
));
1205 emit_insn (gen_addsi3 (reg
, reg
, pic_offset_table_rtx
));
1207 else if (flag_pic
== FAR_PIC
)
1209 /* Unspec to handle -fPIC option. */
1210 emit_insn (gen_unspec_got_addr (reg
, orig
));
1214 else if (GET_CODE (orig
) == CONST
)
1216 /* To handle (symbol + offset). */
1219 if (GET_CODE (XEXP (orig
, 0)) == PLUS
1220 && XEXP (XEXP (orig
, 0), 0) == pic_offset_table_rtx
)
1225 gcc_assert (can_create_pseudo_p ());
1226 reg
= gen_reg_rtx (Pmode
);
1229 gcc_assert (GET_CODE (XEXP (orig
, 0)) == PLUS
);
1231 base
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 0), Pmode
, reg
);
1232 offset
= legitimize_pic_address (XEXP (XEXP (orig
, 0), 1), Pmode
,
1233 base
== reg
? 0 : reg
);
1235 /* REVISIT: Optimize for const-offsets. */
1236 emit_insn (gen_addsi3 (reg
, base
, offset
));
1243 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
1245 cr16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1246 rtx addr
, bool strict
)
1248 enum cr16_addrtype addrtype
;
1249 struct cr16_address address
;
1251 if (TARGET_DEBUG_ADDR
)
1254 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
1255 GET_MODE_NAME (mode
), strict
);
1258 addrtype
= cr16_decompose_address (addr
, &address
,
1259 (TARGET_DEBUG_ADDR
? 1 : 0), FALSE
);
1261 if (TARGET_DEBUG_ADDR
)
1263 const char *typestr
;
1268 typestr
= "invalid";
1271 typestr
= "absolute";
1274 typestr
= "register relative";
1277 typestr
= "register pair relative";
1279 case CR16_INDEX_REGP_REL
:
1280 typestr
= "index + register pair relative";
1285 fprintf (stderr
, "\ncr16 address type: %s\n", typestr
);
1288 if (addrtype
== CR16_INVALID
)
1294 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address
.base
), mode
))
1296 if (TARGET_DEBUG_ADDR
)
1297 fprintf (stderr
, "base register not strict\n");
1300 if (address
.index
&& !REGNO_OK_FOR_INDEX_P (REGNO (address
.index
)))
1302 if (TARGET_DEBUG_ADDR
)
1303 fprintf (stderr
, "index register not strict\n");
1308 /* Return true if addressing mode is register relative. */
1311 if (addrtype
== CR16_REG_REL
|| addrtype
== CR16_REGP_REL
)
1320 /* Routines to compute costs. */
1322 /* Return cost of the memory address x. */
1324 cr16_address_cost (rtx addr
, machine_mode mode ATTRIBUTE_UNUSED
,
1325 addr_space_t as ATTRIBUTE_UNUSED
,
1326 bool speed ATTRIBUTE_UNUSED
)
1328 enum cr16_addrtype addrtype
;
1329 struct cr16_address address
;
1332 addrtype
= cr16_decompose_address (addr
, &address
, 0, FALSE
);
1334 gcc_assert (addrtype
!= CR16_INVALID
);
1336 /* CR16_ABSOLUTE : 3
1337 CR16_REG_REL (disp !=0) : 4
1338 CR16_REG_REL (disp ==0) : 5
1339 CR16_REGP_REL (disp !=0) : 6
1340 CR16_REGP_REL (disp ==0) : 7
1341 CR16_INDEX_REGP_REL (disp !=0) : 8
1342 CR16_INDEX_REGP_REL (disp ==0) : 9. */
1356 case CR16_INDEX_REGP_REL
:
1364 if (TARGET_DEBUG_ADDR
)
1366 fprintf (stderr
, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost
);
1374 /* Implement `TARGET_REGISTER_MOVE_COST'. */
1376 cr16_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED
,
1377 reg_class_t from ATTRIBUTE_UNUSED
, reg_class_t to
)
1379 return (to
!= GENERAL_REGS
? 8 : 2);
1382 /* Implement `TARGET_MEMORY_MOVE_COST'. */
1384 /* Return the cost of moving data of mode MODE between a register of class
1385 CLASS and memory; IN is zero if the value is to be written to memory,
1386 nonzero if it is to be read in. This cost is relative to those in
1387 REGISTER_MOVE_COST. */
1389 cr16_memory_move_cost (machine_mode mode
,
1390 reg_class_t rclass ATTRIBUTE_UNUSED
,
1391 bool in ATTRIBUTE_UNUSED
)
1393 /* One LD or ST takes twice the time of a simple reg-reg move. */
1394 if (reg_classes_intersect_p (rclass
, GENERAL_REGS
))
1395 return (4 * cr16_hard_regno_nregs (0, mode
));
1400 /* Instruction output. */
1402 /* Check if a const_double is ok for cr16 store-immediate instructions. */
1404 cr16_const_double_ok (rtx op
)
1406 if (GET_MODE (op
) == SFmode
)
1409 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op
), l
);
1410 return UNSIGNED_INT_FITS_N_BITS (l
, 4) ? 1 : 0;
1413 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op
), 4)) &&
1414 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op
), 4))) ? 1 : 0;
1417 /* Returns bit position of first 0 or 1 bit.
1418 It is safe to assume val as 16-bit wide. */
1420 cr16_operand_bit_pos (int val
, int bitval
)
1426 for (i
= 0; i
< 16; i
++)
1432 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
1434 cr16_print_operand (FILE * file
, rtx x
, int code
)
1436 int ptr_dereference
= 0;
1442 const char *cr16_cmp_str
;
1443 switch (GET_CODE (x
))
1445 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
1446 -> swap all non symmetric ops. */
1448 cr16_cmp_str
= "eq";
1451 cr16_cmp_str
= "ne";
1454 cr16_cmp_str
= "lt";
1457 cr16_cmp_str
= "lo";
1460 cr16_cmp_str
= "gt";
1463 cr16_cmp_str
= "hi";
1466 cr16_cmp_str
= "le";
1469 cr16_cmp_str
= "ls";
1472 cr16_cmp_str
= "ge";
1475 cr16_cmp_str
= "hs";
1480 fprintf (file
, "%s", cr16_cmp_str
);
1488 if (GET_CODE (x
) == REG
)
1490 /* For Push instructions, we should not print register pairs. */
1491 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1497 /* Print the immediate address for bal
1498 'b' is used instead of 'a' to avoid compiler calling
1499 the GO_IF_LEGITIMATE_ADDRESS which cannot
1500 perform checks on const_int code addresses as it
1501 assumes all const_int are data addresses. */
1502 fprintf (file
, "0x%lx", INTVAL (x
));
1506 /* Print bit position of first 0. */
1507 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 0));
1511 /* Print bit position of first 1. */
1512 fprintf (file
, "%d", cr16_operand_bit_pos (INTVAL (x
), 1));
1515 /* 'g' is used for implicit mem: dereference. */
1516 ptr_dereference
= 1;
1521 switch (GET_CODE (x
))
1524 if (GET_MODE_BITSIZE (GET_MODE (x
)) > BITS_PER_WORD
)
1526 if (LONG_REG_P (REGNO (x
)))
1527 fprintf (file
, "(%s)", reg_names
[REGNO (x
)]);
1529 fprintf (file
, "(%s,%s)", reg_names
[REGNO (x
) + 1],
1530 reg_names
[REGNO (x
)]);
1533 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1537 output_address (GET_MODE (x
), XEXP (x
, 0));
1544 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x
), l
);
1546 fprintf (file
, "$0x%lx", l
);
1551 fprintf (file
, "$%ld", INTVAL (x
));
1555 switch (XINT (x
, 1))
1563 if (!ptr_dereference
)
1567 cr16_print_operand_address (file
, VOIDmode
, x
);
1572 output_operand_lossage ("invalid %%xn code");
1578 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
1581 cr16_print_operand_address (FILE * file
, machine_mode
/*mode*/, rtx addr
)
1583 enum cr16_addrtype addrtype
;
1584 struct cr16_address address
;
1586 /* Decompose the address. Also ask it to treat address as constant. */
1587 addrtype
= cr16_decompose_address (addr
, &address
, 0, TRUE
);
1589 if (address
.disp
&& GET_CODE (address
.disp
) == UNSPEC
)
1599 if (GET_CODE (address
.disp
) == UNSPEC
)
1600 cr16_print_operand (file
, address
.disp
, 0);
1602 output_addr_const (file
, address
.disp
);
1605 fprintf (file
, "0");
1606 fprintf (file
, "(%s)", reg_names
[REGNO (address
.base
)]);
1611 output_addr_const (file
, address
.disp
);
1613 fprintf (file
, "0");
1616 case CR16_INDEX_REGP_REL
:
1617 fprintf (file
, "[%s]", reg_names
[REGNO (address
.index
)]);
1622 if (GET_CODE (address
.disp
) == UNSPEC
)
1623 cr16_print_operand (file
, address
.disp
, 0);
1625 output_addr_const (file
, address
.disp
);
1628 fprintf (file
, "0");
1629 fprintf (file
, "(%s,%s)", reg_names
[REGNO (address
.base
) + 1],
1630 reg_names
[REGNO (address
.base
)]);
1636 /* Add qualifiers to the address expression that was just printed. */
1637 if (flag_pic
< NEAR_PIC
&& address
.code
== 0)
1639 if (address
.data
== DM_FAR
)
1640 /* Addr contains SYMBOL_REF & far data ptr. */
1641 fprintf (file
, "@l");
1642 else if (address
.data
== DM_DEFAULT
)
1643 /* Addr contains SYMBOL_REF & medium data ptr. */
1644 fprintf (file
, "@m");
1645 /* Addr contains SYMBOL_REF & medium data ptr. */
1646 else if (address
.data
== DM_NEAR
)
1647 /* Addr contains SYMBOL_REF & near data ptr. */
1648 fprintf (file
, "@s");
1650 else if (flag_pic
== NEAR_PIC
1651 && (address
.code
== 0) && (address
.data
== DM_FAR
1652 || address
.data
== DM_DEFAULT
1653 || address
.data
== DM_NEAR
))
1655 fprintf (file
, "@l");
1657 else if (flag_pic
== NEAR_PIC
&& address
.code
== 2)
1659 fprintf (file
, "pic");
1661 else if (flag_pic
== NEAR_PIC
&& address
.code
== 1)
1663 fprintf (file
, "@cpic");
1666 else if (flag_pic
== FAR_PIC
&& address
.code
== 2)
1668 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
1669 address ! GOTc tells assembler this symbol is a text-address
1670 This needs to be fixed in such a way that this offset is done
1671 only in the case where an address is being used for indirect jump
1672 or call. Determining the potential usage of loadd is of course not
1673 possible always. Eventually, this has to be fixed in the
1675 fprintf (file
, "GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1677 else if (flag_pic
== FAR_PIC
&& address
.code
== 1)
1679 fprintf (file
, "@cGOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1682 else if (flag_pic
== FAR_PIC
&&
1683 (address
.data
== DM_FAR
|| address
.data
== DM_DEFAULT
1684 || address
.data
== DM_NEAR
))
1686 fprintf (file
, "@GOT (%s)", reg_names
[PIC_OFFSET_TABLE_REGNUM
]);
1690 /* Machine description helper functions. */
1692 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
1693 When push_or_pop is zero -> string for push instructions of prologue.
1694 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1695 Relies on the assumptions:
1696 1. RA is the last register to be saved.
1697 2. The maximal value of the counter is MAX_COUNT. */
1699 cr16_prepare_push_pop_string (int push_or_pop
)
1701 /* j is the number of registers being saved, takes care that there won't be
1702 more than 8 in one push/pop instruction. */
1704 /* For the register mask string. */
1705 static char one_inst_str
[50];
1707 /* i is the index of current_frame_info.save_regs[], going from 0 until
1708 current_frame_info.last_reg_to_save. */
1714 /* For reversing on the push instructions if there are more than one. */
1717 return_str
= (char *) xmalloc (160);
1718 temp_str
= (char *) xmalloc (160);
1721 memset (return_str
, 0, 3);
1724 while (i
<= current_frame_info
.last_reg_to_save
)
1726 /* Prepare mask for one instruction. */
1727 one_inst_str
[0] = 0;
1729 /* To count number of words in one instruction. */
1733 while ((word_cnt
< MAX_COUNT
)
1734 && (i
<= current_frame_info
.last_reg_to_save
))
1736 /* For each non consecutive save register,
1737 a new instruction shall be generated. */
1738 if (!current_frame_info
.save_regs
[i
])
1740 /* Move to next reg and break. */
1745 if (i
== RETURN_ADDRESS_REGNUM
)
1749 /* Check especially if adding 2 does not cross the MAX_COUNT. */
1750 if ((word_cnt
+ ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2))
1753 /* Increase word count by 2 for long registers except RA. */
1754 word_cnt
+= ((i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2);
1759 /* No need to generate any instruction as
1760 no register or RA needs to be saved. */
1761 if ((word_cnt
== 0) && (print_ra
== 0))
1764 /* Now prepare the instruction operands. */
1767 sprintf (one_inst_str
, "$%d, %s", word_cnt
, reg_names
[start_reg
]);
1769 strcat (one_inst_str
, ", ra");
1772 strcat (one_inst_str
, "ra");
1774 if (push_or_pop
== 1)
1776 /* Pop instruction. */
1777 if (print_ra
&& !cr16_interrupt_function_p ()
1778 && !crtl
->calls_eh_return
)
1779 /* Print popret if RA is saved and its not a interrupt
1781 strcpy (temp_str
, "\n\tpopret\t");
1783 strcpy (temp_str
, "\n\tpop\t");
1785 strcat (temp_str
, one_inst_str
);
1787 /* Add the pop instruction list. */
1788 strcat (return_str
, temp_str
);
1792 /* Push instruction. */
1793 strcpy (temp_str
, "\n\tpush\t");
1794 strcat (temp_str
, one_inst_str
);
1796 /* We need to reverse the order of the instructions if there
1797 are more than one. (since the pop will not be reversed in
1799 strcat (temp_str
, return_str
);
1800 strcpy (return_str
, temp_str
);
1804 if (push_or_pop
== 1)
1807 if (cr16_interrupt_function_p ())
1808 strcat (return_str
, "\n\tretx\n");
1809 else if (crtl
->calls_eh_return
)
1811 /* Add stack adjustment before returning to exception handler
1812 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
1813 strcat (return_str
, "\n\taddd\t (r5, r4), (sp)\t\n");
1814 strcat (return_str
, "\n\tjump\t (ra)\n");
1816 /* But before anything else, undo the adjustment addition done in
1817 cr16_expand_epilogue (). */
1818 strcpy (temp_str
, "\n\tsubd\t (r5, r4), (sp)\t\n");
1819 strcat (temp_str
, return_str
);
1820 strcpy (return_str
, temp_str
);
1822 else if (!FUNC_IS_NORETURN_P (current_function_decl
)
1823 && !(current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]))
1824 strcat (return_str
, "\n\tjump\t (ra)\n");
1827 /* Skip the newline and the tab in the start of return_str. */
1833 /* Generate DWARF2 annotation for multi-push instruction. */
1835 cr16_create_dwarf_for_multi_push (rtx insn
)
1837 rtx dwarf
, reg
, tmp
;
1838 int i
, j
, from
, to
, word_cnt
, dwarf_par_index
, inc
;
1840 int num_regs
= 0, offset
= 0, split_here
= 0, total_push_bytes
= 0;
1842 for (i
= 0; i
<= current_frame_info
.last_reg_to_save
; ++i
)
1844 if (current_frame_info
.save_regs
[i
])
1847 if (i
< CR16_FIRST_DWORD_REGISTER
)
1848 total_push_bytes
+= 2;
1850 total_push_bytes
+= 4;
1857 dwarf
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (num_regs
+ 1));
1858 dwarf_par_index
= num_regs
;
1860 from
= current_frame_info
.last_reg_to_save
+ 1;
1861 to
= current_frame_info
.last_reg_to_save
;
1864 for (i
= current_frame_info
.last_reg_to_save
; i
>= 0;)
1866 if (!current_frame_info
.save_regs
[i
] || i
== 0 || split_here
)
1868 /* This block of regs is pushed in one instruction. */
1869 if (i
== 0 && current_frame_info
.save_regs
[i
])
1872 for (j
= to
; j
>= from
; --j
)
1874 if (j
< CR16_FIRST_DWORD_REGISTER
)
1884 reg
= gen_rtx_REG (mode
, j
);
1886 tmp
= gen_rtx_SET (gen_frame_mem (mode
,
1888 (Pmode
, stack_pointer_rtx
,
1889 total_push_bytes
- offset
)),
1891 RTX_FRAME_RELATED_P (tmp
) = 1;
1892 XVECEXP (dwarf
, 0, dwarf_par_index
--) = tmp
;
1901 if (i
!= RETURN_ADDRESS_REGNUM
)
1903 inc
= (i
< CR16_FIRST_DWORD_REGISTER
) ? 1 : 2;
1904 if (word_cnt
+ inc
>= MAX_COUNT
|| FRAME_POINTER_REGNUM
== i
)
1916 tmp
= gen_rtx_SET (stack_pointer_rtx
,
1917 gen_rtx_PLUS (SImode
, stack_pointer_rtx
,
1918 GEN_INT (-offset
)));
1919 RTX_FRAME_RELATED_P (tmp
) = 1;
1920 XVECEXP (dwarf
, 0, 0) = tmp
;
1922 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, dwarf
);
1926 CompactRISC CR16 Architecture stack layout:
1928 0 +---------------------
1933 +==================== Sp (x) = Ap (x+1)
1934 A | Args for functions
1935 | | called by X and Dynamically
1936 | | Dynamic allocations allocated and
1937 | | (alloca, variable deallocated
1938 Stack | length arrays).
1939 grows +-------------------- Fp (x)
1940 down| | Local variables of X
1941 ward| +--------------------
1942 | | Regs saved for X-1
1943 | +==================== Sp (x-1) = Ap (x)
1946 +-------------------- Fp (x-1)
1952 cr16_expand_prologue (void)
1956 cr16_compute_frame ();
1957 cr16_compute_save_regs ();
1959 /* If there is no need in push and adjustment to sp, return. */
1960 if ((current_frame_info
.total_size
+ current_frame_info
.reg_size
) == 0)
1963 if (current_frame_info
.last_reg_to_save
!= -1)
1965 /* If there are registers to push. */
1966 insn
= emit_insn (gen_push_for_prologue
1967 (GEN_INT (current_frame_info
.reg_size
)));
1968 cr16_create_dwarf_for_multi_push (insn
);
1969 RTX_FRAME_RELATED_P (insn
) = 1;
1973 if (current_frame_info
.total_size
> 0)
1975 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
1976 GEN_INT (-current_frame_info
.total_size
)));
1977 RTX_FRAME_RELATED_P (insn
) = 1;
1980 if (frame_pointer_needed
)
1982 /* Initialize the frame pointer with the value of the stack pointer
1983 pointing now to the locals. */
1984 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1988 /* Generate insn that updates the stack for local variables and padding
1989 for registers we save. - Generate the appropriate return insn. */
1991 cr16_expand_epilogue (void)
1995 /* Nonzero if we need to return and pop only RA. This will generate a
1996 different insn. This differentiate is for the peepholes for call as
1997 last statement in function. */
1998 int only_popret_RA
= (current_frame_info
.save_regs
[RETURN_ADDRESS_REGNUM
]
1999 && (current_frame_info
.reg_size
2000 == CR16_UNITS_PER_DWORD
));
2002 if (frame_pointer_needed
)
2004 /* Restore the stack pointer with the frame pointers value. */
2005 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
2008 if (current_frame_info
.total_size
> 0)
2010 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
2011 GEN_INT (current_frame_info
.total_size
)));
2012 RTX_FRAME_RELATED_P (insn
) = 1;
2015 if (crtl
->calls_eh_return
)
2017 /* Add this here so that (r5, r4) is actually loaded with the adjustment
2018 value; otherwise, the load might be optimized away...
2019 NOTE: remember to subtract the adjustment before popping the regs
2020 and add it back before returning. */
2021 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
, stack_pointer_rtx
,
2022 EH_RETURN_STACKADJ_RTX
));
2025 if (cr16_interrupt_function_p ())
2027 insn
= emit_jump_insn (gen_interrupt_return ());
2028 RTX_FRAME_RELATED_P (insn
) = 1;
2030 else if (crtl
->calls_eh_return
)
2032 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
2033 insn
= emit_jump_insn (gen_pop_and_popret_return
2034 (GEN_INT (current_frame_info
.reg_size
)));
2035 RTX_FRAME_RELATED_P (insn
) = 1;
2037 else if (current_frame_info
.last_reg_to_save
== -1)
2038 /* Nothing to pop. */
2039 /* Don't output jump for interrupt routine, only retx. */
2040 emit_jump_insn (gen_jump_return ());
2041 else if (only_popret_RA
)
2043 insn
= emit_jump_insn (gen_popret_RA_return ());
2044 RTX_FRAME_RELATED_P (insn
) = 1;
2048 insn
= emit_jump_insn (gen_pop_and_popret_return
2049 (GEN_INT (current_frame_info
.reg_size
)));
2050 RTX_FRAME_RELATED_P (insn
) = 1;
2054 /* Implements FRAME_POINTER_REQUIRED. */
2056 cr16_frame_pointer_required (void)
2058 return (cfun
->calls_alloca
|| crtl
->calls_eh_return
2059 || cfun
->has_nonlocal_label
|| crtl
->calls_eh_return
);
2063 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
2065 return (to
== STACK_POINTER_REGNUM
? !frame_pointer_needed
: true);
2069 /* A C compound statement that attempts to replace X with
2070 a valid memory address for an operand of mode MODE. WIN
2071 will be a C statement label elsewhere in the code.
2072 X will always be the result of a call to break_out_memory_refs (),
2073 and OLDX will be the operand that was given to that function to
2075 The code generated by this macro should not alter the
2076 substructure of X. If it transforms X into a more legitimate form,
2077 it should assign X (which will always be a C variable) a new value. */
2079 cr16_legitimize_address (rtx x
, rtx orig_x ATTRIBUTE_UNUSED
,
2080 machine_mode mode ATTRIBUTE_UNUSED
)
2083 return legitimize_pic_address (orig_x
, mode
, NULL_RTX
);
2088 /* Implement TARGET_LEGITIMATE_CONSTANT_P
2089 Nonzero if X is a legitimate constant for an immediate
2090 operand on the target machine. You can assume that X
2091 satisfies CONSTANT_P. In cr16c treat legitimize float
2092 constant as an immediate operand. */
2094 cr16_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
,
2095 rtx x ATTRIBUTE_UNUSED
)
2100 static scalar_int_mode
2101 cr16_unwind_word_mode (void)
2106 /* Helper function for md file. This function is used to emit arithmetic
2107 DI instructions. The argument "num" decides which instruction to be
2110 cr16_emit_add_sub_di (rtx
*operands
, enum rtx_code code
)
2116 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2117 hi0_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 4);
2118 hi1_op
[0] = simplify_gen_subreg (HImode
, operands
[0], DImode
, 6);
2120 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2121 hi0_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 4);
2122 hi1_op
[1] = simplify_gen_subreg (HImode
, operands
[2], DImode
, 6);
2128 output_asm_insn ("addd\t%1, %0", lo_op
) ;
2129 output_asm_insn ("addcw\t%1, %0", hi0_op
) ;
2130 output_asm_insn ("addcw\t%1, %0", hi1_op
) ;
2135 output_asm_insn ("subd\t%1, %0", lo_op
) ;
2136 output_asm_insn ("subcw\t%1, %0", hi0_op
) ;
2137 output_asm_insn ("subcw\t%1, %0", hi1_op
) ;
2148 /* Helper function for md file. This function is used to emit logical
2149 DI instructions. The argument "num" decides which instruction to be
2152 cr16_emit_logical_di (rtx
*operands
, enum rtx_code code
)
2157 lo_op
[0] = gen_lowpart (SImode
, operands
[0]);
2158 hi_op
[0] = simplify_gen_subreg (SImode
, operands
[0], DImode
, 4);
2160 lo_op
[1] = gen_lowpart (SImode
, operands
[2]);
2161 hi_op
[1] = simplify_gen_subreg (SImode
, operands
[2], DImode
, 4);
2167 output_asm_insn ("andd\t%1, %0", lo_op
) ;
2168 output_asm_insn ("andd\t%1, %0", hi_op
) ;
2173 output_asm_insn ("ord\t%1, %0", lo_op
) ;
2174 output_asm_insn ("ord\t%1, %0", hi_op
) ;
2179 output_asm_insn ("xord\t%1, %0", lo_op
) ;
2180 output_asm_insn ("xord\t%1, %0", hi_op
) ;
2190 /* Implement PUSH_ROUNDING. */
2193 cr16_push_rounding (poly_int64 bytes
)
2195 return (bytes
+ 1) & ~1;
2198 /* Initialize 'targetm' variable which contains pointers to functions
2199 and data relating to the target machine. */
2201 struct gcc_target targetm
= TARGET_INITIALIZER
;