annotate gcc/config/cr16/cr16.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Output routines for CR16 processor.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by KPIT Cummins Infosystems Limited.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
8 under the terms of the GNU General Public License as published
kono
parents:
diff changeset
9 by the Free Software Foundation; either version 3, or (at your
kono
parents:
diff changeset
10 option) any later version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT
kono
parents:
diff changeset
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
kono
parents:
diff changeset
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
kono
parents:
diff changeset
15 License for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
21 #define IN_TARGET_CODE 1
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
22
111
kono
parents:
diff changeset
23 #include "config.h"
kono
parents:
diff changeset
24 #include "system.h"
kono
parents:
diff changeset
25 #include "coretypes.h"
kono
parents:
diff changeset
26 #include "backend.h"
kono
parents:
diff changeset
27 #include "target.h"
kono
parents:
diff changeset
28 #include "rtl.h"
kono
parents:
diff changeset
29 #include "tree.h"
kono
parents:
diff changeset
30 #include "stringpool.h"
kono
parents:
diff changeset
31 #include "attribs.h"
kono
parents:
diff changeset
32 #include "df.h"
kono
parents:
diff changeset
33 #include "memmodel.h"
kono
parents:
diff changeset
34 #include "tm_p.h"
kono
parents:
diff changeset
35 #include "regs.h"
kono
parents:
diff changeset
36 #include "emit-rtl.h"
kono
parents:
diff changeset
37 #include "diagnostic-core.h"
kono
parents:
diff changeset
38 #include "stor-layout.h"
kono
parents:
diff changeset
39 #include "calls.h"
kono
parents:
diff changeset
40 #include "conditions.h"
kono
parents:
diff changeset
41 #include "output.h"
kono
parents:
diff changeset
42 #include "expr.h"
kono
parents:
diff changeset
43 #include "builtins.h"
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 /* This file should be included last. */
kono
parents:
diff changeset
46 #include "target-def.h"
kono
parents:
diff changeset
47
kono
parents:
diff changeset
48 /* Definitions. */
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 /* Maximum number of register used for passing parameters. */
kono
parents:
diff changeset
51 #define MAX_REG_FOR_PASSING_ARGS 6
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53 /* Minimum number register used for passing parameters. */
kono
parents:
diff changeset
54 #define MIN_REG_FOR_PASSING_ARGS 2
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 /* The maximum count of words supported in the assembly of the architecture in
kono
parents:
diff changeset
57 a push/pop instruction. */
kono
parents:
diff changeset
58 #define MAX_COUNT 8
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 /* Predicate is true if the current function is a 'noreturn' function,
kono
parents:
diff changeset
61 i.e. it is qualified as volatile. */
kono
parents:
diff changeset
62 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
kono
parents:
diff changeset
63
kono
parents:
diff changeset
64 /* Predicate that holds when we need to save registers even for 'noreturn'
kono
parents:
diff changeset
65 functions, to accommodate for unwinding. */
kono
parents:
diff changeset
66 #define MUST_SAVE_REGS_P() \
kono
parents:
diff changeset
67 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 /* Nonzero if the rtx X is a signed const int of n bits. */
kono
parents:
diff changeset
70 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
kono
parents:
diff changeset
71 ((GET_CODE (X) == CONST_INT \
kono
parents:
diff changeset
72 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 /* Nonzero if the rtx X is an unsigned const int of n bits. */
kono
parents:
diff changeset
75 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
kono
parents:
diff changeset
76 ((GET_CODE (X) == CONST_INT \
kono
parents:
diff changeset
77 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 /* Structure for stack computations. */
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 /* variable definitions in the struture
kono
parents:
diff changeset
82 args_size Number of bytes saved on the stack for local
kono
parents:
diff changeset
83 variables
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 reg_size Number of bytes saved on the stack for
kono
parents:
diff changeset
86 non-scratch registers
kono
parents:
diff changeset
87
kono
parents:
diff changeset
88 total_size The sum of 2 sizes: locals vars and padding byte
kono
parents:
diff changeset
89 for saving the registers. Used in expand_prologue()
kono
parents:
diff changeset
90 and expand_epilogue()
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 last_reg_to_save Will hold the number of the last register the
kono
parents:
diff changeset
93 prologue saves, -1 if no register is saved
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 save_regs[16] Each object in the array is a register number.
kono
parents:
diff changeset
96 Mark 1 for registers that need to be saved
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 num_regs Number of registers saved
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 initialized Non-zero if frame size already calculated, not
kono
parents:
diff changeset
101 used yet
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103 function_makes_calls Does the function make calls ? not used yet. */
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 struct cr16_frame_info
kono
parents:
diff changeset
106 {
kono
parents:
diff changeset
107 unsigned long var_size;
kono
parents:
diff changeset
108 unsigned long args_size;
kono
parents:
diff changeset
109 unsigned int reg_size;
kono
parents:
diff changeset
110 unsigned long total_size;
kono
parents:
diff changeset
111 long last_reg_to_save;
kono
parents:
diff changeset
112 long save_regs[FIRST_PSEUDO_REGISTER];
kono
parents:
diff changeset
113 int num_regs;
kono
parents:
diff changeset
114 int initialized;
kono
parents:
diff changeset
115 int function_makes_calls;
kono
parents:
diff changeset
116 };
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 /* Current frame information calculated by cr16_compute_frame_size. */
kono
parents:
diff changeset
119 static struct cr16_frame_info current_frame_info;
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 /* Static Variables. */
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 /* Data model that was supplied by user via command line option
kono
parents:
diff changeset
124 This will be overridden in case of invalid combination
kono
parents:
diff changeset
125 of core and data model options are supplied. */
kono
parents:
diff changeset
126 static enum data_model_type data_model = DM_DEFAULT;
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 /* TARGETM Function Prototypes and forward declarations */
kono
parents:
diff changeset
129 static void cr16_print_operand (FILE *, rtx, int);
kono
parents:
diff changeset
130 static void cr16_print_operand_address (FILE *, machine_mode, rtx);
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 /* Stack layout and calling conventions. */
kono
parents:
diff changeset
133 #undef TARGET_STRUCT_VALUE_RTX
kono
parents:
diff changeset
134 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
kono
parents:
diff changeset
135 #undef TARGET_RETURN_IN_MEMORY
kono
parents:
diff changeset
136 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
kono
parents:
diff changeset
137
kono
parents:
diff changeset
138 /* Target-specific uses of '__attribute__'. */
kono
parents:
diff changeset
139 #undef TARGET_ATTRIBUTE_TABLE
kono
parents:
diff changeset
140 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
kono
parents:
diff changeset
141 #undef TARGET_NARROW_VOLATILE_BITFIELD
kono
parents:
diff changeset
142 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
kono
parents:
diff changeset
143
kono
parents:
diff changeset
144 /* EH related. */
kono
parents:
diff changeset
145 #undef TARGET_UNWIND_WORD_MODE
kono
parents:
diff changeset
146 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 /* Override Options. */
kono
parents:
diff changeset
149 #undef TARGET_OPTION_OVERRIDE
kono
parents:
diff changeset
150 #define TARGET_OPTION_OVERRIDE cr16_override_options
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 /* Conditional register usuage. */
kono
parents:
diff changeset
153 #undef TARGET_CONDITIONAL_REGISTER_USAGE
kono
parents:
diff changeset
154 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
kono
parents:
diff changeset
155
kono
parents:
diff changeset
156 /* Controlling register spills. */
kono
parents:
diff changeset
157 #undef TARGET_CLASS_LIKELY_SPILLED_P
kono
parents:
diff changeset
158 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
kono
parents:
diff changeset
159
kono
parents:
diff changeset
160 /* Passing function arguments. */
kono
parents:
diff changeset
161 #undef TARGET_FUNCTION_ARG
kono
parents:
diff changeset
162 #define TARGET_FUNCTION_ARG cr16_function_arg
kono
parents:
diff changeset
163 #undef TARGET_FUNCTION_ARG_ADVANCE
kono
parents:
diff changeset
164 #define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
kono
parents:
diff changeset
165 #undef TARGET_RETURN_POPS_ARGS
kono
parents:
diff changeset
166 #define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 /* Initialize the GCC target structure. */
kono
parents:
diff changeset
169 #undef TARGET_FRAME_POINTER_REQUIRED
kono
parents:
diff changeset
170 #define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required
kono
parents:
diff changeset
171 #undef TARGET_CAN_ELIMINATE
kono
parents:
diff changeset
172 #define TARGET_CAN_ELIMINATE cr16_can_eliminate
kono
parents:
diff changeset
173 #undef TARGET_LEGITIMIZE_ADDRESS
kono
parents:
diff changeset
174 #define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address
kono
parents:
diff changeset
175 #undef TARGET_LEGITIMATE_CONSTANT_P
kono
parents:
diff changeset
176 #define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p
kono
parents:
diff changeset
177 #undef TARGET_LEGITIMATE_ADDRESS_P
kono
parents:
diff changeset
178 #define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 #undef TARGET_LRA_P
kono
parents:
diff changeset
181 #define TARGET_LRA_P hook_bool_void_false
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 /* Returning function value. */
kono
parents:
diff changeset
184 #undef TARGET_FUNCTION_VALUE
kono
parents:
diff changeset
185 #define TARGET_FUNCTION_VALUE cr16_function_value
kono
parents:
diff changeset
186 #undef TARGET_LIBCALL_VALUE
kono
parents:
diff changeset
187 #define TARGET_LIBCALL_VALUE cr16_libcall_value
kono
parents:
diff changeset
188 #undef TARGET_FUNCTION_VALUE_REGNO_P
kono
parents:
diff changeset
189 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191 /* printing the values. */
kono
parents:
diff changeset
192 #undef TARGET_PRINT_OPERAND
kono
parents:
diff changeset
193 #define TARGET_PRINT_OPERAND cr16_print_operand
kono
parents:
diff changeset
194 #undef TARGET_PRINT_OPERAND_ADDRESS
kono
parents:
diff changeset
195 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 /* Relative costs of operations. */
kono
parents:
diff changeset
198 #undef TARGET_ADDRESS_COST
kono
parents:
diff changeset
199 #define TARGET_ADDRESS_COST cr16_address_cost
kono
parents:
diff changeset
200 #undef TARGET_REGISTER_MOVE_COST
kono
parents:
diff changeset
201 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
kono
parents:
diff changeset
202 #undef TARGET_MEMORY_MOVE_COST
kono
parents:
diff changeset
203 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
kono
parents:
diff changeset
204
kono
parents:
diff changeset
205 #undef TARGET_CONSTANT_ALIGNMENT
kono
parents:
diff changeset
206 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 /* Table of machine attributes. */
kono
parents:
diff changeset
209 static const struct attribute_spec cr16_attribute_table[] = {
kono
parents:
diff changeset
210 /* ISRs have special prologue and epilogue requirements. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
211 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
212 affects_type_identity, handler, exclude }. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
213 {"interrupt", 0, 0, false, true, true, false, NULL, NULL},
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
214 {NULL, 0, 0, false, false, false, false, NULL, NULL}
111
kono
parents:
diff changeset
215 };
kono
parents:
diff changeset
216
kono
parents:
diff changeset
217 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
kono
parents:
diff changeset
218 .?byte directive along with @c is not understood by assembler.
kono
parents:
diff changeset
219 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
kono
parents:
diff changeset
220 as TARGET_ASM_ALIGNED_xx_OP. */
kono
parents:
diff changeset
221 #undef TARGET_ASM_UNALIGNED_HI_OP
kono
parents:
diff changeset
222 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
kono
parents:
diff changeset
223 #undef TARGET_ASM_UNALIGNED_SI_OP
kono
parents:
diff changeset
224 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
kono
parents:
diff changeset
225 #undef TARGET_ASM_UNALIGNED_DI_OP
kono
parents:
diff changeset
226 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 #undef TARGET_HARD_REGNO_NREGS
kono
parents:
diff changeset
229 #define TARGET_HARD_REGNO_NREGS cr16_hard_regno_nregs
kono
parents:
diff changeset
230 #undef TARGET_HARD_REGNO_MODE_OK
kono
parents:
diff changeset
231 #define TARGET_HARD_REGNO_MODE_OK cr16_hard_regno_mode_ok
kono
parents:
diff changeset
232 #undef TARGET_MODES_TIEABLE_P
kono
parents:
diff changeset
233 #define TARGET_MODES_TIEABLE_P cr16_modes_tieable_p
kono
parents:
diff changeset
234
kono
parents:
diff changeset
235 /* Target hook implementations. */
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 /* Implements hook TARGET_RETURN_IN_MEMORY. */
kono
parents:
diff changeset
238 static bool
kono
parents:
diff changeset
239 cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
240 {
kono
parents:
diff changeset
241 const HOST_WIDE_INT size = int_size_in_bytes (type);
kono
parents:
diff changeset
242 return ((size == -1) || (size > 8));
kono
parents:
diff changeset
243 }
kono
parents:
diff changeset
244
kono
parents:
diff changeset
245 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
kono
parents:
diff changeset
246 static bool
kono
parents:
diff changeset
247 cr16_class_likely_spilled_p (reg_class_t rclass)
kono
parents:
diff changeset
248 {
kono
parents:
diff changeset
249 if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS
kono
parents:
diff changeset
250 || (rclass) == LONG_REGS || (rclass) == GENERAL_REGS)
kono
parents:
diff changeset
251 return true;
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 return false;
kono
parents:
diff changeset
254 }
kono
parents:
diff changeset
255
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
256 static poly_int64
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
257 cr16_return_pops_args (tree, tree, poly_int64)
111
kono
parents:
diff changeset
258 {
kono
parents:
diff changeset
259 return 0;
kono
parents:
diff changeset
260 }
kono
parents:
diff changeset
261
kono
parents:
diff changeset
262 /* Returns true if data model selected via command line option
kono
parents:
diff changeset
263 is same as function argument. */
kono
parents:
diff changeset
264 bool
kono
parents:
diff changeset
265 cr16_is_data_model (enum data_model_type model)
kono
parents:
diff changeset
266 {
kono
parents:
diff changeset
267 return (model == data_model);
kono
parents:
diff changeset
268 }
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 /* Parse relevant options and override. */
kono
parents:
diff changeset
271 static void
kono
parents:
diff changeset
272 cr16_override_options (void)
kono
parents:
diff changeset
273 {
kono
parents:
diff changeset
274 /* Disable -fdelete-null-pointer-checks option for CR16 target.
kono
parents:
diff changeset
275 Programs which rely on NULL pointer dereferences _not_ halting the
kono
parents:
diff changeset
276 program may not work properly with this option. So disable this
kono
parents:
diff changeset
277 option. */
kono
parents:
diff changeset
278 flag_delete_null_pointer_checks = 0;
kono
parents:
diff changeset
279
kono
parents:
diff changeset
280 /* FIXME: To avoid spill_failure ICE during exception handling,
kono
parents:
diff changeset
281 * disable cse_fllow_jumps. The spill error occurs when compiler
kono
parents:
diff changeset
282 * can't find a suitable candidate in GENERAL_REGS class to reload
kono
parents:
diff changeset
283 * a 32bit register.
kono
parents:
diff changeset
284 * Need to find a better way of avoiding this situation. */
kono
parents:
diff changeset
285 if (flag_exceptions)
kono
parents:
diff changeset
286 flag_cse_follow_jumps = 0;
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 /* If -fpic option, data_model == DM_FAR. */
kono
parents:
diff changeset
289 if (flag_pic == NEAR_PIC)
kono
parents:
diff changeset
290 {
kono
parents:
diff changeset
291 data_model = DM_FAR;
kono
parents:
diff changeset
292 }
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 /* The only option we want to examine is data model option. */
kono
parents:
diff changeset
295 if (cr16_data_model)
kono
parents:
diff changeset
296 {
kono
parents:
diff changeset
297 if (strcmp (cr16_data_model, "medium") == 0)
kono
parents:
diff changeset
298 data_model = DM_DEFAULT;
kono
parents:
diff changeset
299 else if (strcmp (cr16_data_model, "near") == 0)
kono
parents:
diff changeset
300 data_model = DM_NEAR;
kono
parents:
diff changeset
301 else if (strcmp (cr16_data_model, "far") == 0)
kono
parents:
diff changeset
302 {
kono
parents:
diff changeset
303 if (TARGET_CR16CP)
kono
parents:
diff changeset
304 data_model = DM_FAR;
kono
parents:
diff changeset
305 else
kono
parents:
diff changeset
306 error ("data-model=far not valid for cr16c architecture");
kono
parents:
diff changeset
307 }
kono
parents:
diff changeset
308 else
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
309 error ("invalid data model option %<-mdata-model=%s%>",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
310 cr16_data_model);
111
kono
parents:
diff changeset
311 }
kono
parents:
diff changeset
312 else
kono
parents:
diff changeset
313 data_model = DM_DEFAULT;
kono
parents:
diff changeset
314 }
kono
parents:
diff changeset
315
kono
parents:
diff changeset
316 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
kono
parents:
diff changeset
317 static void
kono
parents:
diff changeset
318 cr16_conditional_register_usage (void)
kono
parents:
diff changeset
319 {
kono
parents:
diff changeset
320 if (flag_pic)
kono
parents:
diff changeset
321 {
kono
parents:
diff changeset
322 fixed_regs[12] = call_used_regs[12] = 1;
kono
parents:
diff changeset
323 }
kono
parents:
diff changeset
324 }
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 /* Stack layout and calling conventions routines. */
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 /* Return nonzero if the current function being compiled is an interrupt
kono
parents:
diff changeset
329 function as specified by the "interrupt" attribute. */
kono
parents:
diff changeset
330 int
kono
parents:
diff changeset
331 cr16_interrupt_function_p (void)
kono
parents:
diff changeset
332 {
kono
parents:
diff changeset
333 tree attributes;
kono
parents:
diff changeset
334
kono
parents:
diff changeset
335 attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
kono
parents:
diff changeset
336 return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
kono
parents:
diff changeset
337 }
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 /* Compute values for the array current_frame_info.save_regs and the variable
kono
parents:
diff changeset
340 current_frame_info.reg_size. The index of current_frame_info.save_regs
kono
parents:
diff changeset
341 is numbers of register, each will get 1 if we need to save it in the
kono
parents:
diff changeset
342 current function, 0 if not. current_frame_info.reg_size is the total sum
kono
parents:
diff changeset
343 of the registers being saved. */
kono
parents:
diff changeset
344 static void
kono
parents:
diff changeset
345 cr16_compute_save_regs (void)
kono
parents:
diff changeset
346 {
kono
parents:
diff changeset
347 unsigned int regno;
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349 /* Initialize here so in case the function is no-return it will be -1. */
kono
parents:
diff changeset
350 current_frame_info.last_reg_to_save = -1;
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 /* Initialize the number of bytes to be saved. */
kono
parents:
diff changeset
353 current_frame_info.reg_size = 0;
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 /* No need to save any registers if the function never returns. */
kono
parents:
diff changeset
356 if (FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
kono
parents:
diff changeset
357 return;
kono
parents:
diff changeset
358
kono
parents:
diff changeset
359 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
kono
parents:
diff changeset
360 {
kono
parents:
diff changeset
361 if (fixed_regs[regno])
kono
parents:
diff changeset
362 {
kono
parents:
diff changeset
363 current_frame_info.save_regs[regno] = 0;
kono
parents:
diff changeset
364 continue;
kono
parents:
diff changeset
365 }
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 /* If this reg is used and not call-used (except RA), save it. */
kono
parents:
diff changeset
368 if (cr16_interrupt_function_p ())
kono
parents:
diff changeset
369 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
370 if (!crtl->is_leaf && call_used_or_fixed_reg_p (regno))
111
kono
parents:
diff changeset
371 /* This is a volatile reg in a non-leaf interrupt routine - save
kono
parents:
diff changeset
372 it for the sake of its sons. */
kono
parents:
diff changeset
373 current_frame_info.save_regs[regno] = 1;
kono
parents:
diff changeset
374 else if (df_regs_ever_live_p (regno))
kono
parents:
diff changeset
375 /* This reg is used - save it. */
kono
parents:
diff changeset
376 current_frame_info.save_regs[regno] = 1;
kono
parents:
diff changeset
377 else
kono
parents:
diff changeset
378 /* This reg is not used, and is not a volatile - don't save. */
kono
parents:
diff changeset
379 current_frame_info.save_regs[regno] = 0;
kono
parents:
diff changeset
380 }
kono
parents:
diff changeset
381 else
kono
parents:
diff changeset
382 {
kono
parents:
diff changeset
383 /* If this reg is used and not call-used (except RA), save it. */
kono
parents:
diff changeset
384 if (df_regs_ever_live_p (regno)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
385 && (!call_used_or_fixed_reg_p (regno)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
386 || regno == RETURN_ADDRESS_REGNUM))
111
kono
parents:
diff changeset
387 current_frame_info.save_regs[regno] = 1;
kono
parents:
diff changeset
388 else
kono
parents:
diff changeset
389 current_frame_info.save_regs[regno] = 0;
kono
parents:
diff changeset
390 }
kono
parents:
diff changeset
391 }
kono
parents:
diff changeset
392
kono
parents:
diff changeset
393 /* Save registers so the exception handler can modify them. */
kono
parents:
diff changeset
394 if (crtl->calls_eh_return)
kono
parents:
diff changeset
395 {
kono
parents:
diff changeset
396 unsigned int i;
kono
parents:
diff changeset
397
kono
parents:
diff changeset
398 for (i = 0;; ++i)
kono
parents:
diff changeset
399 {
kono
parents:
diff changeset
400 regno = EH_RETURN_DATA_REGNO (i);
kono
parents:
diff changeset
401 if (INVALID_REGNUM == regno)
kono
parents:
diff changeset
402 break;
kono
parents:
diff changeset
403 current_frame_info.save_regs[regno] = 1;
kono
parents:
diff changeset
404 }
kono
parents:
diff changeset
405 }
kono
parents:
diff changeset
406
kono
parents:
diff changeset
407 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
kono
parents:
diff changeset
408 if (current_frame_info.save_regs[regno] == 1)
kono
parents:
diff changeset
409 {
kono
parents:
diff changeset
410 current_frame_info.last_reg_to_save = regno;
kono
parents:
diff changeset
411 if (regno >= CR16_FIRST_DWORD_REGISTER)
kono
parents:
diff changeset
412 current_frame_info.reg_size += CR16_UNITS_PER_DWORD;
kono
parents:
diff changeset
413 else
kono
parents:
diff changeset
414 current_frame_info.reg_size += UNITS_PER_WORD;
kono
parents:
diff changeset
415 }
kono
parents:
diff changeset
416 }
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 /* Compute the size of the local area and the size to be adjusted by the
kono
parents:
diff changeset
419 prologue and epilogue. */
kono
parents:
diff changeset
420 static void
kono
parents:
diff changeset
421 cr16_compute_frame (void)
kono
parents:
diff changeset
422 {
kono
parents:
diff changeset
423 /* For aligning the local variables. */
kono
parents:
diff changeset
424 int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
kono
parents:
diff changeset
425 int padding_locals;
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 /* Padding needed for each element of the frame. */
kono
parents:
diff changeset
428 current_frame_info.var_size = get_frame_size ();
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 /* Align to the stack alignment. */
kono
parents:
diff changeset
431 padding_locals = current_frame_info.var_size % stack_alignment;
kono
parents:
diff changeset
432 if (padding_locals)
kono
parents:
diff changeset
433 padding_locals = stack_alignment - padding_locals;
kono
parents:
diff changeset
434
kono
parents:
diff changeset
435 current_frame_info.var_size += padding_locals;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
436 current_frame_info.total_size
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
437 = (current_frame_info.var_size
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
438 + (ACCUMULATE_OUTGOING_ARGS
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
439 ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0));
111
kono
parents:
diff changeset
440 }
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
kono
parents:
diff changeset
443 int
kono
parents:
diff changeset
444 cr16_initial_elimination_offset (int from, int to)
kono
parents:
diff changeset
445 {
kono
parents:
diff changeset
446 /* Compute this since we need to use current_frame_info.reg_size. */
kono
parents:
diff changeset
447 cr16_compute_save_regs ();
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 /* Compute this since we need to use current_frame_info.var_size. */
kono
parents:
diff changeset
450 cr16_compute_frame ();
kono
parents:
diff changeset
451
kono
parents:
diff changeset
452 if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
453 return (ACCUMULATE_OUTGOING_ARGS
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
454 ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0);
111
kono
parents:
diff changeset
455 else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
kono
parents:
diff changeset
456 return (current_frame_info.reg_size + current_frame_info.var_size);
kono
parents:
diff changeset
457 else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
kono
parents:
diff changeset
458 return (current_frame_info.reg_size + current_frame_info.var_size
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
459 + (ACCUMULATE_OUTGOING_ARGS
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
460 ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0));
111
kono
parents:
diff changeset
461 else
kono
parents:
diff changeset
462 gcc_unreachable ();
kono
parents:
diff changeset
463 }
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 /* Register Usage. */
kono
parents:
diff changeset
466
kono
parents:
diff changeset
467 /* Return the class number of the smallest class containing reg number REGNO.
kono
parents:
diff changeset
468 This could be a conditional expression or could index an array. */
kono
parents:
diff changeset
469 enum reg_class
kono
parents:
diff changeset
470 cr16_regno_reg_class (int regno)
kono
parents:
diff changeset
471 {
kono
parents:
diff changeset
472 if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
kono
parents:
diff changeset
473 return SHORT_REGS;
kono
parents:
diff changeset
474
kono
parents:
diff changeset
475 if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
kono
parents:
diff changeset
476 return LONG_REGS;
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 return NO_REGS;
kono
parents:
diff changeset
479 }
kono
parents:
diff changeset
480
kono
parents:
diff changeset
481 /* Implement TARGET_HARD_REGNO_NREGS. */
kono
parents:
diff changeset
482
kono
parents:
diff changeset
483 static unsigned int
kono
parents:
diff changeset
484 cr16_hard_regno_nregs (unsigned int regno, machine_mode mode)
kono
parents:
diff changeset
485 {
kono
parents:
diff changeset
486 if (regno >= CR16_FIRST_DWORD_REGISTER)
kono
parents:
diff changeset
487 return CEIL (GET_MODE_SIZE (mode), CR16_UNITS_PER_DWORD);
kono
parents:
diff changeset
488 return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
kono
parents:
diff changeset
489 }
kono
parents:
diff changeset
490
kono
parents:
diff changeset
491 /* Implement TARGET_HARD_REGNO_MODE_OK. On the CR16 architecture, all
kono
parents:
diff changeset
492 registers can hold all modes, except that double precision floats
kono
parents:
diff changeset
493 (and double ints) must fall on even-register boundaries. */
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 static bool
kono
parents:
diff changeset
496 cr16_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
kono
parents:
diff changeset
497 {
kono
parents:
diff changeset
498 if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11))
kono
parents:
diff changeset
499 return false;
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 if (mode == DImode || mode == DFmode)
kono
parents:
diff changeset
502 {
kono
parents:
diff changeset
503 if ((regno > 8) || (regno & 1))
kono
parents:
diff changeset
504 return false;
kono
parents:
diff changeset
505 return true;
kono
parents:
diff changeset
506 }
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 if ((TARGET_INT32)
kono
parents:
diff changeset
509 && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 )))
kono
parents:
diff changeset
510 return false;
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 /* CC can only hold CCmode values. */
kono
parents:
diff changeset
513 if (GET_MODE_CLASS (mode) == MODE_CC)
kono
parents:
diff changeset
514 return false;
kono
parents:
diff changeset
515 return true;
kono
parents:
diff changeset
516 }
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 /* Implement TARGET_MODES_TIEABLE_P. */
kono
parents:
diff changeset
519 static bool
kono
parents:
diff changeset
520 cr16_modes_tieable_p (machine_mode mode1, machine_mode mode2)
kono
parents:
diff changeset
521 {
kono
parents:
diff changeset
522 return GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2);
kono
parents:
diff changeset
523 }
kono
parents:
diff changeset
524
kono
parents:
diff changeset
525 /* Returns register number for function return value.*/
kono
parents:
diff changeset
526 static inline unsigned int
kono
parents:
diff changeset
527 cr16_ret_register (void)
kono
parents:
diff changeset
528 {
kono
parents:
diff changeset
529 return 0;
kono
parents:
diff changeset
530 }
kono
parents:
diff changeset
531
kono
parents:
diff changeset
532 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
kono
parents:
diff changeset
533 static rtx
kono
parents:
diff changeset
534 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
535 int incoming ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
536 {
kono
parents:
diff changeset
537 return gen_rtx_REG (Pmode, cr16_ret_register ());
kono
parents:
diff changeset
538 }
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 /* Returning function value. */
kono
parents:
diff changeset
541
kono
parents:
diff changeset
542 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
kono
parents:
diff changeset
543 static bool
kono
parents:
diff changeset
544 cr16_function_value_regno_p (const unsigned int regno)
kono
parents:
diff changeset
545 {
kono
parents:
diff changeset
546 return (regno == cr16_ret_register ());
kono
parents:
diff changeset
547 }
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 /* Create an RTX representing the place where a
kono
parents:
diff changeset
550 library function returns a value of mode MODE. */
kono
parents:
diff changeset
551 static rtx
kono
parents:
diff changeset
552 cr16_libcall_value (machine_mode mode,
kono
parents:
diff changeset
553 const_rtx func ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
554 {
kono
parents:
diff changeset
555 return gen_rtx_REG (mode, cr16_ret_register ());
kono
parents:
diff changeset
556 }
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 /* Create an RTX representing the place where a
kono
parents:
diff changeset
559 function returns a value of data type VALTYPE. */
kono
parents:
diff changeset
560 static rtx
kono
parents:
diff changeset
561 cr16_function_value (const_tree type,
kono
parents:
diff changeset
562 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
563 bool outgoing ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
564 {
kono
parents:
diff changeset
565 return gen_rtx_REG (TYPE_MODE (type), cr16_ret_register ());
kono
parents:
diff changeset
566 }
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 /* Passing function arguments. */
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 /* If enough param regs are available for passing the param of type TYPE return
kono
parents:
diff changeset
571 the number of registers needed else 0. */
kono
parents:
diff changeset
572 static int
kono
parents:
diff changeset
573 enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
kono
parents:
diff changeset
574 machine_mode mode)
kono
parents:
diff changeset
575 {
kono
parents:
diff changeset
576 int type_size;
kono
parents:
diff changeset
577 int remaining_size;
kono
parents:
diff changeset
578
kono
parents:
diff changeset
579 if (mode != BLKmode)
kono
parents:
diff changeset
580 type_size = GET_MODE_BITSIZE (mode);
kono
parents:
diff changeset
581 else
kono
parents:
diff changeset
582 type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
kono
parents:
diff changeset
583
kono
parents:
diff changeset
584 remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
kono
parents:
diff changeset
585 - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
kono
parents:
diff changeset
586 1);
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 /* Any variable which is too big to pass in two registers, will pass on
kono
parents:
diff changeset
589 stack. */
kono
parents:
diff changeset
590 if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
kono
parents:
diff changeset
591 return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 return 0;
kono
parents:
diff changeset
594 }
kono
parents:
diff changeset
595
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
596 /* Implement TARGET_FUNCTION_ARG. */
111
kono
parents:
diff changeset
597 static rtx
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
598 cr16_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
111
kono
parents:
diff changeset
599 {
kono
parents:
diff changeset
600 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
kono
parents:
diff changeset
601 cum->last_parm_in_reg = 0;
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 /* function_arg () is called with this type just after all the args have
kono
parents:
diff changeset
604 had their registers assigned. The rtx that function_arg returns from
kono
parents:
diff changeset
605 this type is supposed to pass to 'gen_call' but currently it is not
kono
parents:
diff changeset
606 implemented. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
607 if (arg.end_marker_p ())
111
kono
parents:
diff changeset
608 return NULL_RTX;
kono
parents:
diff changeset
609
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
610 if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0))
111
kono
parents:
diff changeset
611 return NULL_RTX;
kono
parents:
diff changeset
612
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
613 if (arg.mode == BLKmode)
111
kono
parents:
diff changeset
614 {
kono
parents:
diff changeset
615 /* Enable structures that need padding bytes at the end to pass to a
kono
parents:
diff changeset
616 function in registers. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
617 if (enough_regs_for_param (cum, arg.type, arg.mode) != 0)
111
kono
parents:
diff changeset
618 {
kono
parents:
diff changeset
619 cum->last_parm_in_reg = 1;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
620 return gen_rtx_REG (arg.mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
111
kono
parents:
diff changeset
621 }
kono
parents:
diff changeset
622 }
kono
parents:
diff changeset
623
kono
parents:
diff changeset
624 if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
kono
parents:
diff changeset
625 return NULL_RTX;
kono
parents:
diff changeset
626 else
kono
parents:
diff changeset
627 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
628 if (enough_regs_for_param (cum, arg.type, arg.mode) != 0)
111
kono
parents:
diff changeset
629 {
kono
parents:
diff changeset
630 cum->last_parm_in_reg = 1;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
631 return gen_rtx_REG (arg.mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
111
kono
parents:
diff changeset
632 }
kono
parents:
diff changeset
633 }
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 return NULL_RTX;
kono
parents:
diff changeset
636 }
kono
parents:
diff changeset
637
kono
parents:
diff changeset
638 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
kono
parents:
diff changeset
639 void
kono
parents:
diff changeset
640 cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
kono
parents:
diff changeset
641 rtx libfunc ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
642 {
kono
parents:
diff changeset
643 tree param, next_param;
kono
parents:
diff changeset
644
kono
parents:
diff changeset
645 cum->ints = 0;
kono
parents:
diff changeset
646
kono
parents:
diff changeset
647 /* Determine if this function has variable arguments. This is indicated by
kono
parents:
diff changeset
648 the last argument being 'void_type_mode' if there are no variable
kono
parents:
diff changeset
649 arguments. Change here for a different vararg. */
kono
parents:
diff changeset
650 for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
kono
parents:
diff changeset
651 param != NULL_TREE; param = next_param)
kono
parents:
diff changeset
652 {
kono
parents:
diff changeset
653 next_param = TREE_CHAIN (param);
kono
parents:
diff changeset
654 if ((next_param == NULL_TREE) && (TREE_VALUE (param) != void_type_node))
kono
parents:
diff changeset
655 {
kono
parents:
diff changeset
656 cum->ints = -1;
kono
parents:
diff changeset
657 return;
kono
parents:
diff changeset
658 }
kono
parents:
diff changeset
659 }
kono
parents:
diff changeset
660 }
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
kono
parents:
diff changeset
663 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
664 cr16_function_arg_advance (cumulative_args_t cum_v,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
665 const function_arg_info &arg)
111
kono
parents:
diff changeset
666 {
kono
parents:
diff changeset
667 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
kono
parents:
diff changeset
668
kono
parents:
diff changeset
669 /* l holds the number of registers required. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
670 int l = GET_MODE_BITSIZE (arg.mode) / BITS_PER_WORD;
111
kono
parents:
diff changeset
671
kono
parents:
diff changeset
672 /* If the parameter isn't passed on a register don't advance cum. */
kono
parents:
diff changeset
673 if (!cum->last_parm_in_reg)
kono
parents:
diff changeset
674 return;
kono
parents:
diff changeset
675
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
676 if (targetm.calls.must_pass_in_stack (arg) || (cum->ints < 0))
111
kono
parents:
diff changeset
677 return;
kono
parents:
diff changeset
678
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
679 if ((arg.mode == SImode) || (arg.mode == HImode)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
680 || (arg.mode == QImode) || (arg.mode == DImode))
111
kono
parents:
diff changeset
681 {
kono
parents:
diff changeset
682 if (l <= 1)
kono
parents:
diff changeset
683 cum->ints += 1;
kono
parents:
diff changeset
684 else
kono
parents:
diff changeset
685 cum->ints += l;
kono
parents:
diff changeset
686 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
687 else if ((arg.mode == SFmode) || (arg.mode == DFmode))
111
kono
parents:
diff changeset
688 cum->ints += l;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
689 else if (arg.mode == BLKmode)
111
kono
parents:
diff changeset
690 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
691 if ((l = enough_regs_for_param (cum, arg.type, arg.mode)) != 0)
111
kono
parents:
diff changeset
692 cum->ints += l;
kono
parents:
diff changeset
693 }
kono
parents:
diff changeset
694 return;
kono
parents:
diff changeset
695 }
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
kono
parents:
diff changeset
698 Return nonzero if N is a register used for passing parameters. */
kono
parents:
diff changeset
699 int
kono
parents:
diff changeset
700 cr16_function_arg_regno_p (int n)
kono
parents:
diff changeset
701 {
kono
parents:
diff changeset
702 return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
kono
parents:
diff changeset
703 }
kono
parents:
diff changeset
704
kono
parents:
diff changeset
705 /* Addressing modes.
kono
parents:
diff changeset
706 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
kono
parents:
diff changeset
707 defined in cr16.h. */
kono
parents:
diff changeset
708
kono
parents:
diff changeset
709 /* Helper function to check if is a valid base register that can
kono
parents:
diff changeset
710 hold address. */
kono
parents:
diff changeset
711 static int
kono
parents:
diff changeset
712 cr16_addr_reg_p (rtx addr_reg)
kono
parents:
diff changeset
713 {
kono
parents:
diff changeset
714 rtx reg;
kono
parents:
diff changeset
715
kono
parents:
diff changeset
716 if (REG_P (addr_reg))
kono
parents:
diff changeset
717 reg = addr_reg;
kono
parents:
diff changeset
718 else if ((GET_CODE (addr_reg) == SUBREG)
kono
parents:
diff changeset
719 && REG_P (SUBREG_REG (addr_reg))
kono
parents:
diff changeset
720 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
kono
parents:
diff changeset
721 <= UNITS_PER_WORD))
kono
parents:
diff changeset
722 reg = SUBREG_REG (addr_reg);
kono
parents:
diff changeset
723 else
kono
parents:
diff changeset
724 return FALSE;
kono
parents:
diff changeset
725
kono
parents:
diff changeset
726 if (GET_MODE (reg) != Pmode)
kono
parents:
diff changeset
727 return FALSE;
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 return TRUE;
kono
parents:
diff changeset
730 }
kono
parents:
diff changeset
731
kono
parents:
diff changeset
732 /* Helper functions: Created specifically for decomposing operand of CONST
kono
parents:
diff changeset
733 Recursively look into expression x for code or data symbol.
kono
parents:
diff changeset
734 The function expects the expression to contain combination of
kono
parents:
diff changeset
735 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
kono
parents:
diff changeset
736 LABEL_REF, CONST_INT, (PLUS or MINUS)
kono
parents:
diff changeset
737 SYMBOL_REF
kono
parents:
diff changeset
738 LABEL_REF
kono
parents:
diff changeset
739 All other combinations will result in code = -1 and data = ILLEGAL_DM
kono
parents:
diff changeset
740 code data
kono
parents:
diff changeset
741 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
kono
parents:
diff changeset
742 0 DM_FAR SYMBOL_REF was found and it was far data reference.
kono
parents:
diff changeset
743 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
kono
parents:
diff changeset
744 1 ILLEGAL_DM LABEL_REF was found.
kono
parents:
diff changeset
745 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
kono
parents:
diff changeset
746 void
kono
parents:
diff changeset
747 cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
kono
parents:
diff changeset
748 bool treat_as_const)
kono
parents:
diff changeset
749 {
kono
parents:
diff changeset
750 *code = -1;
kono
parents:
diff changeset
751 *data = ILLEGAL_DM;
kono
parents:
diff changeset
752 switch (GET_CODE (x))
kono
parents:
diff changeset
753 {
kono
parents:
diff changeset
754 case SYMBOL_REF:
kono
parents:
diff changeset
755 *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
kono
parents:
diff changeset
756 /* 2 indicates func sym. */
kono
parents:
diff changeset
757 if (*code == 0)
kono
parents:
diff changeset
758 {
kono
parents:
diff changeset
759 if (CR16_TARGET_DATA_NEAR)
kono
parents:
diff changeset
760 *data = DM_DEFAULT;
kono
parents:
diff changeset
761 else if (CR16_TARGET_DATA_MEDIUM)
kono
parents:
diff changeset
762 *data = DM_FAR;
kono
parents:
diff changeset
763 else if (CR16_TARGET_DATA_FAR)
kono
parents:
diff changeset
764 {
kono
parents:
diff changeset
765 if (treat_as_const)
kono
parents:
diff changeset
766 /* This will be used only for printing
kono
parents:
diff changeset
767 the qualifier. This call is (may be)
kono
parents:
diff changeset
768 made by cr16_print_operand_address. */
kono
parents:
diff changeset
769 *data = DM_FAR;
kono
parents:
diff changeset
770 else
kono
parents:
diff changeset
771 /* This call is (may be) made by
kono
parents:
diff changeset
772 cr16_legitimate_address_p. */
kono
parents:
diff changeset
773 *data = ILLEGAL_DM;
kono
parents:
diff changeset
774 }
kono
parents:
diff changeset
775 }
kono
parents:
diff changeset
776 return;
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 case LABEL_REF:
kono
parents:
diff changeset
779 /* 1 - indicates non-function symbol. */
kono
parents:
diff changeset
780 *code = 1;
kono
parents:
diff changeset
781 return;
kono
parents:
diff changeset
782
kono
parents:
diff changeset
783 case PLUS:
kono
parents:
diff changeset
784 case MINUS:
kono
parents:
diff changeset
785 /* Look into the tree nodes. */
kono
parents:
diff changeset
786 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
kono
parents:
diff changeset
787 cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
kono
parents:
diff changeset
788 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
kono
parents:
diff changeset
789 cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
kono
parents:
diff changeset
790 return;
kono
parents:
diff changeset
791 default:
kono
parents:
diff changeset
792 return;
kono
parents:
diff changeset
793 }
kono
parents:
diff changeset
794 }
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 /* Decompose Address
kono
parents:
diff changeset
797 This function decomposes the address returns the type of address
kono
parents:
diff changeset
798 as defined in enum cr16_addrtype. It also fills the parameter *out.
kono
parents:
diff changeset
799 The decomposed address can be used for two purposes. One to
kono
parents:
diff changeset
800 check if the address is valid and second to print the address
kono
parents:
diff changeset
801 operand.
kono
parents:
diff changeset
802
kono
parents:
diff changeset
803 Following tables list valid address supported in CR16C/C+ architectures.
kono
parents:
diff changeset
804 Legend:
kono
parents:
diff changeset
805 aN : Absoulte address N-bit address
kono
parents:
diff changeset
806 R : One 16-bit register
kono
parents:
diff changeset
807 RP : Consecutive two 16-bit registers or one 32-bit register
kono
parents:
diff changeset
808 I : One 32-bit register
kono
parents:
diff changeset
809 dispN : Signed displacement of N-bits
kono
parents:
diff changeset
810
kono
parents:
diff changeset
811 ----Code addresses----
kono
parents:
diff changeset
812 Branch operands:
kono
parents:
diff changeset
813 disp9 : CR16_ABSOLUTE (disp)
kono
parents:
diff changeset
814 disp17 : CR16_ABSOLUTE (disp)
kono
parents:
diff changeset
815 disp25 : CR16_ABSOLUTE (disp)
kono
parents:
diff changeset
816 RP + disp25 : CR16_REGP_REL (base, disp)
kono
parents:
diff changeset
817
kono
parents:
diff changeset
818 Jump operands:
kono
parents:
diff changeset
819 RP : CR16_REGP_REL (base, disp=0)
kono
parents:
diff changeset
820 a24 : CR16_ABSOLUTE (disp)
kono
parents:
diff changeset
821
kono
parents:
diff changeset
822 ----Data addresses----
kono
parents:
diff changeset
823 a20 : CR16_ABSOLUTE (disp) near (1M)
kono
parents:
diff changeset
824 a24 : CR16_ABSOLUTE (disp) medium (16M)
kono
parents:
diff changeset
825 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
kono
parents:
diff changeset
826 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
kono
parents:
diff changeset
827 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
kono
parents:
diff changeset
828 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
kono
parents:
diff changeset
829 I : *** Valid but port does not support this
kono
parents:
diff changeset
830 I + a20 : *** Valid but port does not support this
kono
parents:
diff changeset
831 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
kono
parents:
diff changeset
832 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
kono
parents:
diff changeset
833
kono
parents:
diff changeset
834 Decomposing Data model in case of absolute address.
kono
parents:
diff changeset
835
kono
parents:
diff changeset
836 Target Option Address type Resultant Data ref type
kono
parents:
diff changeset
837 ---------------------- ------------ -----------------------
kono
parents:
diff changeset
838 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
kono
parents:
diff changeset
839 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
kono
parents:
diff changeset
840 CR16_TARGET_MODEL_NEAR ABS24 Invalid
kono
parents:
diff changeset
841 CR16_TARGET_MODEL_NEAR IMM32 Invalid
kono
parents:
diff changeset
842
kono
parents:
diff changeset
843 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
kono
parents:
diff changeset
844 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
kono
parents:
diff changeset
845 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
kono
parents:
diff changeset
846 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
kono
parents:
diff changeset
847
kono
parents:
diff changeset
848 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
kono
parents:
diff changeset
849 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
kono
parents:
diff changeset
850 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
kono
parents:
diff changeset
851 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
kono
parents:
diff changeset
852 enum cr16_addrtype
kono
parents:
diff changeset
853 cr16_decompose_address (rtx addr, struct cr16_address *out,
kono
parents:
diff changeset
854 bool debug_print, bool treat_as_const)
kono
parents:
diff changeset
855 {
kono
parents:
diff changeset
856 rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
kono
parents:
diff changeset
857 enum data_model_type data = ILLEGAL_DM;
kono
parents:
diff changeset
858 int code = -1;
kono
parents:
diff changeset
859 enum cr16_addrtype retval = CR16_INVALID;
kono
parents:
diff changeset
860
kono
parents:
diff changeset
861 switch (GET_CODE (addr))
kono
parents:
diff changeset
862 {
kono
parents:
diff changeset
863 case CONST_INT:
kono
parents:
diff changeset
864 /* Absolute address (known at compile time). */
kono
parents:
diff changeset
865 code = 0;
kono
parents:
diff changeset
866 if (debug_print)
kono
parents:
diff changeset
867 fprintf (stderr, "\ncode:%d", code);
kono
parents:
diff changeset
868 disp = addr;
kono
parents:
diff changeset
869
kono
parents:
diff changeset
870 if (debug_print)
kono
parents:
diff changeset
871 {
kono
parents:
diff changeset
872 fprintf (stderr, "\ndisp:");
kono
parents:
diff changeset
873 debug_rtx (disp);
kono
parents:
diff changeset
874 }
kono
parents:
diff changeset
875
kono
parents:
diff changeset
876 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
kono
parents:
diff changeset
877 {
kono
parents:
diff changeset
878 data = DM_DEFAULT;
kono
parents:
diff changeset
879 if (debug_print)
kono
parents:
diff changeset
880 fprintf (stderr, "\ndata:%d", data);
kono
parents:
diff changeset
881 retval = CR16_ABSOLUTE;
kono
parents:
diff changeset
882 }
kono
parents:
diff changeset
883 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
kono
parents:
diff changeset
884 {
kono
parents:
diff changeset
885 if (!CR16_TARGET_DATA_NEAR)
kono
parents:
diff changeset
886 {
kono
parents:
diff changeset
887 data = DM_FAR;
kono
parents:
diff changeset
888 if (debug_print)
kono
parents:
diff changeset
889 fprintf (stderr, "\ndata:%d", data);
kono
parents:
diff changeset
890 retval = CR16_ABSOLUTE;
kono
parents:
diff changeset
891 }
kono
parents:
diff changeset
892 else
kono
parents:
diff changeset
893 return CR16_INVALID; /* ABS24 is not support in NEAR model. */
kono
parents:
diff changeset
894 }
kono
parents:
diff changeset
895 else
kono
parents:
diff changeset
896 return CR16_INVALID;
kono
parents:
diff changeset
897 break;
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 case CONST:
kono
parents:
diff changeset
900 /* A CONST is an expression of PLUS or MINUS with
kono
parents:
diff changeset
901 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
kono
parents:
diff changeset
902 result of assembly-time arithmetic computation. */
kono
parents:
diff changeset
903 retval = CR16_ABSOLUTE;
kono
parents:
diff changeset
904 disp = addr;
kono
parents:
diff changeset
905 /* Call the helper function to check the validity. */
kono
parents:
diff changeset
906 cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
kono
parents:
diff changeset
907 if ((code == 0) && (data == ILLEGAL_DM))
kono
parents:
diff changeset
908 /* CONST is not valid code or data address. */
kono
parents:
diff changeset
909 return CR16_INVALID;
kono
parents:
diff changeset
910 if (debug_print)
kono
parents:
diff changeset
911 {
kono
parents:
diff changeset
912 fprintf (stderr, "\ndisp:");
kono
parents:
diff changeset
913 debug_rtx (disp);
kono
parents:
diff changeset
914 fprintf (stderr, "\ncode:%d", code);
kono
parents:
diff changeset
915 fprintf (stderr, "\ndata:%d", data);
kono
parents:
diff changeset
916 }
kono
parents:
diff changeset
917 break;
kono
parents:
diff changeset
918
kono
parents:
diff changeset
919 case LABEL_REF:
kono
parents:
diff changeset
920 retval = CR16_ABSOLUTE;
kono
parents:
diff changeset
921 disp = addr;
kono
parents:
diff changeset
922 /* 1 - indicates non-function symbol. */
kono
parents:
diff changeset
923 code = 1;
kono
parents:
diff changeset
924 if (debug_print)
kono
parents:
diff changeset
925 {
kono
parents:
diff changeset
926 fprintf (stderr, "\ndisp:");
kono
parents:
diff changeset
927 debug_rtx (disp);
kono
parents:
diff changeset
928 fprintf (stderr, "\ncode:%d", code);
kono
parents:
diff changeset
929 }
kono
parents:
diff changeset
930 break;
kono
parents:
diff changeset
931
kono
parents:
diff changeset
932 case SYMBOL_REF:
kono
parents:
diff changeset
933 /* Absolute address (known at link time). */
kono
parents:
diff changeset
934 retval = CR16_ABSOLUTE;
kono
parents:
diff changeset
935 disp = addr;
kono
parents:
diff changeset
936 /* This is a code address if symbol_ref is a function. */
kono
parents:
diff changeset
937 /* 2 indicates func sym. */
kono
parents:
diff changeset
938 code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
kono
parents:
diff changeset
939 if (debug_print)
kono
parents:
diff changeset
940 {
kono
parents:
diff changeset
941 fprintf (stderr, "\ndisp:");
kono
parents:
diff changeset
942 debug_rtx (disp);
kono
parents:
diff changeset
943 fprintf (stderr, "\ncode:%d", code);
kono
parents:
diff changeset
944 }
kono
parents:
diff changeset
945 /* If not function ref then check if valid data ref. */
kono
parents:
diff changeset
946 if (code == 0)
kono
parents:
diff changeset
947 {
kono
parents:
diff changeset
948 if (CR16_TARGET_DATA_NEAR)
kono
parents:
diff changeset
949 data = DM_DEFAULT;
kono
parents:
diff changeset
950 else if (CR16_TARGET_DATA_MEDIUM)
kono
parents:
diff changeset
951 data = DM_FAR;
kono
parents:
diff changeset
952 else if (CR16_TARGET_DATA_FAR)
kono
parents:
diff changeset
953 {
kono
parents:
diff changeset
954 if (treat_as_const)
kono
parents:
diff changeset
955 /* This will be used only for printing the
kono
parents:
diff changeset
956 qualifier. This call is (may be) made
kono
parents:
diff changeset
957 by cr16_print_operand_address. */
kono
parents:
diff changeset
958 data = DM_FAR;
kono
parents:
diff changeset
959 else
kono
parents:
diff changeset
960 /* This call is (may be) made by
kono
parents:
diff changeset
961 cr16_legitimate_address_p. */
kono
parents:
diff changeset
962 return CR16_INVALID;
kono
parents:
diff changeset
963 }
kono
parents:
diff changeset
964 else
kono
parents:
diff changeset
965 data = DM_DEFAULT;
kono
parents:
diff changeset
966 }
kono
parents:
diff changeset
967 if (debug_print)
kono
parents:
diff changeset
968 fprintf (stderr, "\ndata:%d", data);
kono
parents:
diff changeset
969 break;
kono
parents:
diff changeset
970
kono
parents:
diff changeset
971 case REG:
kono
parents:
diff changeset
972 case SUBREG:
kono
parents:
diff changeset
973 /* Register relative address. */
kono
parents:
diff changeset
974 /* Assume REG fits in a single register. */
kono
parents:
diff changeset
975 retval = CR16_REG_REL;
kono
parents:
diff changeset
976 if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
kono
parents:
diff changeset
977 if (!LONG_REG_P (REGNO (addr)))
kono
parents:
diff changeset
978 /* REG will result in reg pair. */
kono
parents:
diff changeset
979 retval = CR16_REGP_REL;
kono
parents:
diff changeset
980 base = addr;
kono
parents:
diff changeset
981 if (debug_print)
kono
parents:
diff changeset
982 {
kono
parents:
diff changeset
983 fprintf (stderr, "\nbase:");
kono
parents:
diff changeset
984 debug_rtx (base);
kono
parents:
diff changeset
985 }
kono
parents:
diff changeset
986 break;
kono
parents:
diff changeset
987
kono
parents:
diff changeset
988 case PLUS:
kono
parents:
diff changeset
989 switch (GET_CODE (XEXP (addr, 0)))
kono
parents:
diff changeset
990 {
kono
parents:
diff changeset
991 case REG:
kono
parents:
diff changeset
992 case SUBREG:
kono
parents:
diff changeset
993 /* REG + DISP20. */
kono
parents:
diff changeset
994 /* All Reg relative addresses having a displacement needs
kono
parents:
diff changeset
995 to fit in 20-bits. */
kono
parents:
diff changeset
996 disp = XEXP (addr, 1);
kono
parents:
diff changeset
997 if (debug_print)
kono
parents:
diff changeset
998 {
kono
parents:
diff changeset
999 fprintf (stderr, "\ndisp:");
kono
parents:
diff changeset
1000 debug_rtx (disp);
kono
parents:
diff changeset
1001 }
kono
parents:
diff changeset
1002 switch (GET_CODE (XEXP (addr, 1)))
kono
parents:
diff changeset
1003 {
kono
parents:
diff changeset
1004 case CONST_INT:
kono
parents:
diff changeset
1005 /* Shall fit in 20-bits. */
kono
parents:
diff changeset
1006 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
kono
parents:
diff changeset
1007 return CR16_INVALID;
kono
parents:
diff changeset
1008 code = 0;
kono
parents:
diff changeset
1009 if (debug_print)
kono
parents:
diff changeset
1010 fprintf (stderr, "\ncode:%d", code);
kono
parents:
diff changeset
1011 break;
kono
parents:
diff changeset
1012
kono
parents:
diff changeset
1013 case UNSPEC:
kono
parents:
diff changeset
1014 switch (XINT (XEXP (addr, 1), 1))
kono
parents:
diff changeset
1015 {
kono
parents:
diff changeset
1016 case UNSPEC_LIBRARY_OFFSET:
kono
parents:
diff changeset
1017 default:
kono
parents:
diff changeset
1018 gcc_unreachable ();
kono
parents:
diff changeset
1019 }
kono
parents:
diff changeset
1020 break;
kono
parents:
diff changeset
1021
kono
parents:
diff changeset
1022 case LABEL_REF:
kono
parents:
diff changeset
1023 case SYMBOL_REF:
kono
parents:
diff changeset
1024 case CONST:
kono
parents:
diff changeset
1025 /* This is also a valid expression for address.
kono
parents:
diff changeset
1026 However, we cannot ascertain if the resultant
kono
parents:
diff changeset
1027 displacement will be valid 20-bit value. Therefore,
kono
parents:
diff changeset
1028 lets not allow such an expression for now. This will
kono
parents:
diff changeset
1029 be updated when we find a way to validate this
kono
parents:
diff changeset
1030 expression as legitimate address.
kono
parents:
diff changeset
1031 Till then fall through CR16_INVALID. */
kono
parents:
diff changeset
1032 default:
kono
parents:
diff changeset
1033 return CR16_INVALID;
kono
parents:
diff changeset
1034 }
kono
parents:
diff changeset
1035
kono
parents:
diff changeset
1036 /* Now check if REG can fit into single or pair regs. */
kono
parents:
diff changeset
1037 retval = CR16_REG_REL;
kono
parents:
diff changeset
1038 base = XEXP (addr, 0);
kono
parents:
diff changeset
1039 if (debug_print)
kono
parents:
diff changeset
1040 {
kono
parents:
diff changeset
1041 fprintf (stderr, "\nbase:");
kono
parents:
diff changeset
1042 debug_rtx (base);
kono
parents:
diff changeset
1043 }
kono
parents:
diff changeset
1044 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
kono
parents:
diff changeset
1045 {
kono
parents:
diff changeset
1046 if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
kono
parents:
diff changeset
1047 /* REG will result in reg pair. */
kono
parents:
diff changeset
1048 retval = CR16_REGP_REL;
kono
parents:
diff changeset
1049 }
kono
parents:
diff changeset
1050 break;
kono
parents:
diff changeset
1051
kono
parents:
diff changeset
1052 case PLUS:
kono
parents:
diff changeset
1053 /* Valid expr:
kono
parents:
diff changeset
1054 plus
kono
parents:
diff changeset
1055 /\
kono
parents:
diff changeset
1056 / \
kono
parents:
diff changeset
1057 plus idx
kono
parents:
diff changeset
1058 /\
kono
parents:
diff changeset
1059 / \
kono
parents:
diff changeset
1060 reg const_int
kono
parents:
diff changeset
1061
kono
parents:
diff changeset
1062 Check if the operand 1 is valid index register. */
kono
parents:
diff changeset
1063 data = ILLEGAL_DM;
kono
parents:
diff changeset
1064 if (debug_print)
kono
parents:
diff changeset
1065 fprintf (stderr, "\ndata:%d", data);
kono
parents:
diff changeset
1066 switch (GET_CODE (XEXP (addr, 1)))
kono
parents:
diff changeset
1067 {
kono
parents:
diff changeset
1068 case REG:
kono
parents:
diff changeset
1069 case SUBREG:
kono
parents:
diff changeset
1070 if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
kono
parents:
diff changeset
1071 return CR16_INVALID;
kono
parents:
diff changeset
1072 /* OK. REG is a valid index register. */
kono
parents:
diff changeset
1073 index = XEXP (addr, 1);
kono
parents:
diff changeset
1074 if (debug_print)
kono
parents:
diff changeset
1075 {
kono
parents:
diff changeset
1076 fprintf (stderr, "\nindex:");
kono
parents:
diff changeset
1077 debug_rtx (index);
kono
parents:
diff changeset
1078 }
kono
parents:
diff changeset
1079 break;
kono
parents:
diff changeset
1080 default:
kono
parents:
diff changeset
1081 return CR16_INVALID;
kono
parents:
diff changeset
1082 }
kono
parents:
diff changeset
1083 /* Check if operand 0 of operand 0 is REGP. */
kono
parents:
diff changeset
1084 switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
kono
parents:
diff changeset
1085 {
kono
parents:
diff changeset
1086 case REG:
kono
parents:
diff changeset
1087 case SUBREG:
kono
parents:
diff changeset
1088 /* Now check if REG is a REGP and not in LONG regs. */
kono
parents:
diff changeset
1089 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
kono
parents:
diff changeset
1090 > BITS_PER_WORD)
kono
parents:
diff changeset
1091 {
kono
parents:
diff changeset
1092 if (REGNO (XEXP (XEXP (addr, 0), 0))
kono
parents:
diff changeset
1093 >= CR16_FIRST_DWORD_REGISTER)
kono
parents:
diff changeset
1094 return CR16_INVALID;
kono
parents:
diff changeset
1095 base = XEXP (XEXP (addr, 0), 0);
kono
parents:
diff changeset
1096 if (debug_print)
kono
parents:
diff changeset
1097 {
kono
parents:
diff changeset
1098 fprintf (stderr, "\nbase:");
kono
parents:
diff changeset
1099 debug_rtx (base);
kono
parents:
diff changeset
1100 }
kono
parents:
diff changeset
1101 }
kono
parents:
diff changeset
1102 else
kono
parents:
diff changeset
1103 return CR16_INVALID;
kono
parents:
diff changeset
1104 break;
kono
parents:
diff changeset
1105 default:
kono
parents:
diff changeset
1106 return CR16_INVALID;
kono
parents:
diff changeset
1107 }
kono
parents:
diff changeset
1108 /* Now check if the operand 1 of operand 0 is const_int. */
kono
parents:
diff changeset
1109 if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
kono
parents:
diff changeset
1110 {
kono
parents:
diff changeset
1111 disp = XEXP (XEXP (addr, 0), 1);
kono
parents:
diff changeset
1112 if (debug_print)
kono
parents:
diff changeset
1113 {
kono
parents:
diff changeset
1114 fprintf (stderr, "\ndisp:");
kono
parents:
diff changeset
1115 debug_rtx (disp);
kono
parents:
diff changeset
1116 }
kono
parents:
diff changeset
1117 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
kono
parents:
diff changeset
1118 return CR16_INVALID;
kono
parents:
diff changeset
1119 }
kono
parents:
diff changeset
1120 else
kono
parents:
diff changeset
1121 return CR16_INVALID;
kono
parents:
diff changeset
1122 retval = CR16_INDEX_REGP_REL;
kono
parents:
diff changeset
1123 break;
kono
parents:
diff changeset
1124 default:
kono
parents:
diff changeset
1125 return CR16_INVALID;
kono
parents:
diff changeset
1126 }
kono
parents:
diff changeset
1127 break;
kono
parents:
diff changeset
1128
kono
parents:
diff changeset
1129 default:
kono
parents:
diff changeset
1130 return CR16_INVALID;
kono
parents:
diff changeset
1131 }
kono
parents:
diff changeset
1132
kono
parents:
diff changeset
1133 /* Check if the base and index registers are valid. */
kono
parents:
diff changeset
1134 if (base && !(cr16_addr_reg_p (base)))
kono
parents:
diff changeset
1135 return CR16_INVALID;
kono
parents:
diff changeset
1136 if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
kono
parents:
diff changeset
1137 return CR16_INVALID;
kono
parents:
diff changeset
1138 if (index && !(REG_OK_FOR_INDEX_P (index)))
kono
parents:
diff changeset
1139 return CR16_INVALID;
kono
parents:
diff changeset
1140
kono
parents:
diff changeset
1141 /* Write the decomposition to out parameter. */
kono
parents:
diff changeset
1142 out->base = base;
kono
parents:
diff changeset
1143 out->disp = disp;
kono
parents:
diff changeset
1144 out->index = index;
kono
parents:
diff changeset
1145 out->data = data;
kono
parents:
diff changeset
1146 out->code = code;
kono
parents:
diff changeset
1147
kono
parents:
diff changeset
1148 return retval;
kono
parents:
diff changeset
1149 }
kono
parents:
diff changeset
1150
kono
parents:
diff changeset
1151 /* Return non-zero value if 'x' is legitimate PIC operand
kono
parents:
diff changeset
1152 when generating PIC code. */
kono
parents:
diff changeset
1153 int
kono
parents:
diff changeset
1154 legitimate_pic_operand_p (rtx x)
kono
parents:
diff changeset
1155 {
kono
parents:
diff changeset
1156 switch (GET_CODE (x))
kono
parents:
diff changeset
1157 {
kono
parents:
diff changeset
1158 case SYMBOL_REF:
kono
parents:
diff changeset
1159 return 0;
kono
parents:
diff changeset
1160 case LABEL_REF:
kono
parents:
diff changeset
1161 return 0;
kono
parents:
diff changeset
1162 case CONST:
kono
parents:
diff changeset
1163 /* REVISIT: Use something like symbol_referenced_p. */
kono
parents:
diff changeset
1164 if (GET_CODE (XEXP (x, 0)) == PLUS
kono
parents:
diff changeset
1165 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
kono
parents:
diff changeset
1166 || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
kono
parents:
diff changeset
1167 && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
kono
parents:
diff changeset
1168 return 0;
kono
parents:
diff changeset
1169 break;
kono
parents:
diff changeset
1170 case MEM:
kono
parents:
diff changeset
1171 return legitimate_pic_operand_p (XEXP (x, 0));
kono
parents:
diff changeset
1172 default:
kono
parents:
diff changeset
1173 break;
kono
parents:
diff changeset
1174 }
kono
parents:
diff changeset
1175 return 1;
kono
parents:
diff changeset
1176 }
kono
parents:
diff changeset
1177
kono
parents:
diff changeset
1178 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
kono
parents:
diff changeset
1179
kono
parents:
diff changeset
1180 Input Output (-f pic) Output (-f PIC)
kono
parents:
diff changeset
1181 orig reg
kono
parents:
diff changeset
1182
kono
parents:
diff changeset
1183 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
kono
parents:
diff changeset
1184
kono
parents:
diff changeset
1185 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
kono
parents:
diff changeset
1186
kono
parents:
diff changeset
1187 NOTE: @BRO is added using unspec:BRO
kono
parents:
diff changeset
1188 NOTE: @GOT is added using unspec:GOT. */
kono
parents:
diff changeset
1189 rtx
kono
parents:
diff changeset
1190 legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1191 rtx reg)
kono
parents:
diff changeset
1192 {
kono
parents:
diff changeset
1193 /* First handle a simple SYMBOL_REF or LABEL_REF. */
kono
parents:
diff changeset
1194 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
kono
parents:
diff changeset
1195 {
kono
parents:
diff changeset
1196 if (reg == 0)
kono
parents:
diff changeset
1197 reg = gen_reg_rtx (Pmode);
kono
parents:
diff changeset
1198
kono
parents:
diff changeset
1199 if (flag_pic == NEAR_PIC)
kono
parents:
diff changeset
1200 {
kono
parents:
diff changeset
1201 /* Unspec to handle -fpic option. */
kono
parents:
diff changeset
1202 emit_insn (gen_unspec_bro_addr (reg, orig));
kono
parents:
diff changeset
1203 emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
kono
parents:
diff changeset
1204 }
kono
parents:
diff changeset
1205 else if (flag_pic == FAR_PIC)
kono
parents:
diff changeset
1206 {
kono
parents:
diff changeset
1207 /* Unspec to handle -fPIC option. */
kono
parents:
diff changeset
1208 emit_insn (gen_unspec_got_addr (reg, orig));
kono
parents:
diff changeset
1209 }
kono
parents:
diff changeset
1210 return reg;
kono
parents:
diff changeset
1211 }
kono
parents:
diff changeset
1212 else if (GET_CODE (orig) == CONST)
kono
parents:
diff changeset
1213 {
kono
parents:
diff changeset
1214 /* To handle (symbol + offset). */
kono
parents:
diff changeset
1215 rtx base, offset;
kono
parents:
diff changeset
1216
kono
parents:
diff changeset
1217 if (GET_CODE (XEXP (orig, 0)) == PLUS
kono
parents:
diff changeset
1218 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
kono
parents:
diff changeset
1219 return orig;
kono
parents:
diff changeset
1220
kono
parents:
diff changeset
1221 if (reg == 0)
kono
parents:
diff changeset
1222 {
kono
parents:
diff changeset
1223 gcc_assert (can_create_pseudo_p ());
kono
parents:
diff changeset
1224 reg = gen_reg_rtx (Pmode);
kono
parents:
diff changeset
1225 }
kono
parents:
diff changeset
1226
kono
parents:
diff changeset
1227 gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
kono
parents:
diff changeset
1228
kono
parents:
diff changeset
1229 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
kono
parents:
diff changeset
1230 offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
kono
parents:
diff changeset
1231 base == reg ? 0 : reg);
kono
parents:
diff changeset
1232
kono
parents:
diff changeset
1233 /* REVISIT: Optimize for const-offsets. */
kono
parents:
diff changeset
1234 emit_insn (gen_addsi3 (reg, base, offset));
kono
parents:
diff changeset
1235
kono
parents:
diff changeset
1236 return reg;
kono
parents:
diff changeset
1237 }
kono
parents:
diff changeset
1238 return orig;
kono
parents:
diff changeset
1239 }
kono
parents:
diff changeset
1240
kono
parents:
diff changeset
1241 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
kono
parents:
diff changeset
1242 static bool
kono
parents:
diff changeset
1243 cr16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1244 rtx addr, bool strict)
kono
parents:
diff changeset
1245 {
kono
parents:
diff changeset
1246 enum cr16_addrtype addrtype;
kono
parents:
diff changeset
1247 struct cr16_address address;
kono
parents:
diff changeset
1248
kono
parents:
diff changeset
1249 if (TARGET_DEBUG_ADDR)
kono
parents:
diff changeset
1250 {
kono
parents:
diff changeset
1251 fprintf (stderr,
kono
parents:
diff changeset
1252 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
kono
parents:
diff changeset
1253 GET_MODE_NAME (mode), strict);
kono
parents:
diff changeset
1254 debug_rtx (addr);
kono
parents:
diff changeset
1255 }
kono
parents:
diff changeset
1256 addrtype = cr16_decompose_address (addr, &address,
kono
parents:
diff changeset
1257 (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
kono
parents:
diff changeset
1258
kono
parents:
diff changeset
1259 if (TARGET_DEBUG_ADDR)
kono
parents:
diff changeset
1260 {
kono
parents:
diff changeset
1261 const char *typestr;
kono
parents:
diff changeset
1262
kono
parents:
diff changeset
1263 switch (addrtype)
kono
parents:
diff changeset
1264 {
kono
parents:
diff changeset
1265 case CR16_INVALID:
kono
parents:
diff changeset
1266 typestr = "invalid";
kono
parents:
diff changeset
1267 break;
kono
parents:
diff changeset
1268 case CR16_ABSOLUTE:
kono
parents:
diff changeset
1269 typestr = "absolute";
kono
parents:
diff changeset
1270 break;
kono
parents:
diff changeset
1271 case CR16_REG_REL:
kono
parents:
diff changeset
1272 typestr = "register relative";
kono
parents:
diff changeset
1273 break;
kono
parents:
diff changeset
1274 case CR16_REGP_REL:
kono
parents:
diff changeset
1275 typestr = "register pair relative";
kono
parents:
diff changeset
1276 break;
kono
parents:
diff changeset
1277 case CR16_INDEX_REGP_REL:
kono
parents:
diff changeset
1278 typestr = "index + register pair relative";
kono
parents:
diff changeset
1279 break;
kono
parents:
diff changeset
1280 default:
kono
parents:
diff changeset
1281 gcc_unreachable ();
kono
parents:
diff changeset
1282 }
kono
parents:
diff changeset
1283 fprintf (stderr, "\ncr16 address type: %s\n", typestr);
kono
parents:
diff changeset
1284 }
kono
parents:
diff changeset
1285
kono
parents:
diff changeset
1286 if (addrtype == CR16_INVALID)
kono
parents:
diff changeset
1287 return FALSE;
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 if (strict)
kono
parents:
diff changeset
1290 {
kono
parents:
diff changeset
1291 if (address.base
kono
parents:
diff changeset
1292 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
kono
parents:
diff changeset
1293 {
kono
parents:
diff changeset
1294 if (TARGET_DEBUG_ADDR)
kono
parents:
diff changeset
1295 fprintf (stderr, "base register not strict\n");
kono
parents:
diff changeset
1296 return FALSE;
kono
parents:
diff changeset
1297 }
kono
parents:
diff changeset
1298 if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
kono
parents:
diff changeset
1299 {
kono
parents:
diff changeset
1300 if (TARGET_DEBUG_ADDR)
kono
parents:
diff changeset
1301 fprintf (stderr, "index register not strict\n");
kono
parents:
diff changeset
1302 return FALSE;
kono
parents:
diff changeset
1303 }
kono
parents:
diff changeset
1304 }
kono
parents:
diff changeset
1305
kono
parents:
diff changeset
1306 /* Return true if addressing mode is register relative. */
kono
parents:
diff changeset
1307 if (flag_pic)
kono
parents:
diff changeset
1308 {
kono
parents:
diff changeset
1309 if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
kono
parents:
diff changeset
1310 return TRUE;
kono
parents:
diff changeset
1311 else
kono
parents:
diff changeset
1312 return FALSE;
kono
parents:
diff changeset
1313 }
kono
parents:
diff changeset
1314
kono
parents:
diff changeset
1315 return TRUE;
kono
parents:
diff changeset
1316 }
kono
parents:
diff changeset
1317
kono
parents:
diff changeset
1318 /* Routines to compute costs. */
kono
parents:
diff changeset
1319
kono
parents:
diff changeset
1320 /* Return cost of the memory address x. */
kono
parents:
diff changeset
1321 static int
kono
parents:
diff changeset
1322 cr16_address_cost (rtx addr, machine_mode mode ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1323 addr_space_t as ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1324 bool speed ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
1325 {
kono
parents:
diff changeset
1326 enum cr16_addrtype addrtype;
kono
parents:
diff changeset
1327 struct cr16_address address;
kono
parents:
diff changeset
1328 int cost = 2;
kono
parents:
diff changeset
1329
kono
parents:
diff changeset
1330 addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
kono
parents:
diff changeset
1331
kono
parents:
diff changeset
1332 gcc_assert (addrtype != CR16_INVALID);
kono
parents:
diff changeset
1333
kono
parents:
diff changeset
1334 /* CR16_ABSOLUTE : 3
kono
parents:
diff changeset
1335 CR16_REG_REL (disp !=0) : 4
kono
parents:
diff changeset
1336 CR16_REG_REL (disp ==0) : 5
kono
parents:
diff changeset
1337 CR16_REGP_REL (disp !=0) : 6
kono
parents:
diff changeset
1338 CR16_REGP_REL (disp ==0) : 7
kono
parents:
diff changeset
1339 CR16_INDEX_REGP_REL (disp !=0) : 8
kono
parents:
diff changeset
1340 CR16_INDEX_REGP_REL (disp ==0) : 9. */
kono
parents:
diff changeset
1341 switch (addrtype)
kono
parents:
diff changeset
1342 {
kono
parents:
diff changeset
1343 case CR16_ABSOLUTE:
kono
parents:
diff changeset
1344 cost += 1;
kono
parents:
diff changeset
1345 break;
kono
parents:
diff changeset
1346 case CR16_REGP_REL:
kono
parents:
diff changeset
1347 cost += 2;
kono
parents:
diff changeset
1348 /* Fall through. */
kono
parents:
diff changeset
1349 case CR16_REG_REL:
kono
parents:
diff changeset
1350 cost += 3;
kono
parents:
diff changeset
1351 if (address.disp)
kono
parents:
diff changeset
1352 cost -= 1;
kono
parents:
diff changeset
1353 break;
kono
parents:
diff changeset
1354 case CR16_INDEX_REGP_REL:
kono
parents:
diff changeset
1355 cost += 7;
kono
parents:
diff changeset
1356 if (address.disp)
kono
parents:
diff changeset
1357 cost -= 1;
kono
parents:
diff changeset
1358 default:
kono
parents:
diff changeset
1359 break;
kono
parents:
diff changeset
1360 }
kono
parents:
diff changeset
1361
kono
parents:
diff changeset
1362 if (TARGET_DEBUG_ADDR)
kono
parents:
diff changeset
1363 {
kono
parents:
diff changeset
1364 fprintf (stderr, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost);
kono
parents:
diff changeset
1365 debug_rtx (addr);
kono
parents:
diff changeset
1366 }
kono
parents:
diff changeset
1367
kono
parents:
diff changeset
1368 return cost;
kono
parents:
diff changeset
1369 }
kono
parents:
diff changeset
1370
kono
parents:
diff changeset
1371
kono
parents:
diff changeset
1372 /* Implement `TARGET_REGISTER_MOVE_COST'. */
kono
parents:
diff changeset
1373 static int
kono
parents:
diff changeset
1374 cr16_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1375 reg_class_t from ATTRIBUTE_UNUSED, reg_class_t to)
kono
parents:
diff changeset
1376 {
kono
parents:
diff changeset
1377 return (to != GENERAL_REGS ? 8 : 2);
kono
parents:
diff changeset
1378 }
kono
parents:
diff changeset
1379
kono
parents:
diff changeset
1380 /* Implement `TARGET_MEMORY_MOVE_COST'. */
kono
parents:
diff changeset
1381
kono
parents:
diff changeset
1382 /* Return the cost of moving data of mode MODE between a register of class
kono
parents:
diff changeset
1383 CLASS and memory; IN is zero if the value is to be written to memory,
kono
parents:
diff changeset
1384 nonzero if it is to be read in. This cost is relative to those in
kono
parents:
diff changeset
1385 REGISTER_MOVE_COST. */
kono
parents:
diff changeset
1386 static int
kono
parents:
diff changeset
1387 cr16_memory_move_cost (machine_mode mode,
kono
parents:
diff changeset
1388 reg_class_t rclass ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1389 bool in ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
1390 {
kono
parents:
diff changeset
1391 /* One LD or ST takes twice the time of a simple reg-reg move. */
kono
parents:
diff changeset
1392 if (reg_classes_intersect_p (rclass, GENERAL_REGS))
kono
parents:
diff changeset
1393 return (4 * cr16_hard_regno_nregs (0, mode));
kono
parents:
diff changeset
1394 else
kono
parents:
diff changeset
1395 return (100);
kono
parents:
diff changeset
1396 }
kono
parents:
diff changeset
1397
kono
parents:
diff changeset
1398 /* Instruction output. */
kono
parents:
diff changeset
1399
kono
parents:
diff changeset
1400 /* Check if a const_double is ok for cr16 store-immediate instructions. */
kono
parents:
diff changeset
1401 int
kono
parents:
diff changeset
1402 cr16_const_double_ok (rtx op)
kono
parents:
diff changeset
1403 {
kono
parents:
diff changeset
1404 if (GET_MODE (op) == SFmode)
kono
parents:
diff changeset
1405 {
kono
parents:
diff changeset
1406 long l;
kono
parents:
diff changeset
1407 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), l);
kono
parents:
diff changeset
1408 return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
kono
parents:
diff changeset
1409 }
kono
parents:
diff changeset
1410
kono
parents:
diff changeset
1411 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
kono
parents:
diff changeset
1412 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
kono
parents:
diff changeset
1413 }
kono
parents:
diff changeset
1414
kono
parents:
diff changeset
1415 /* Returns bit position of first 0 or 1 bit.
kono
parents:
diff changeset
1416 It is safe to assume val as 16-bit wide. */
kono
parents:
diff changeset
1417 int
kono
parents:
diff changeset
1418 cr16_operand_bit_pos (int val, int bitval)
kono
parents:
diff changeset
1419 {
kono
parents:
diff changeset
1420 int i;
kono
parents:
diff changeset
1421 if (bitval == 0)
kono
parents:
diff changeset
1422 val = ~val;
kono
parents:
diff changeset
1423
kono
parents:
diff changeset
1424 for (i = 0; i < 16; i++)
kono
parents:
diff changeset
1425 if (val & (1 << i))
kono
parents:
diff changeset
1426 break;
kono
parents:
diff changeset
1427 return i;
kono
parents:
diff changeset
1428 }
kono
parents:
diff changeset
1429
kono
parents:
diff changeset
1430 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
kono
parents:
diff changeset
1431 static void
kono
parents:
diff changeset
1432 cr16_print_operand (FILE * file, rtx x, int code)
kono
parents:
diff changeset
1433 {
kono
parents:
diff changeset
1434 int ptr_dereference = 0;
kono
parents:
diff changeset
1435
kono
parents:
diff changeset
1436 switch (code)
kono
parents:
diff changeset
1437 {
kono
parents:
diff changeset
1438 case 'd':
kono
parents:
diff changeset
1439 {
kono
parents:
diff changeset
1440 const char *cr16_cmp_str;
kono
parents:
diff changeset
1441 switch (GET_CODE (x))
kono
parents:
diff changeset
1442 {
kono
parents:
diff changeset
1443 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
kono
parents:
diff changeset
1444 -> swap all non symmetric ops. */
kono
parents:
diff changeset
1445 case EQ:
kono
parents:
diff changeset
1446 cr16_cmp_str = "eq";
kono
parents:
diff changeset
1447 break;
kono
parents:
diff changeset
1448 case NE:
kono
parents:
diff changeset
1449 cr16_cmp_str = "ne";
kono
parents:
diff changeset
1450 break;
kono
parents:
diff changeset
1451 case GT:
kono
parents:
diff changeset
1452 cr16_cmp_str = "lt";
kono
parents:
diff changeset
1453 break;
kono
parents:
diff changeset
1454 case GTU:
kono
parents:
diff changeset
1455 cr16_cmp_str = "lo";
kono
parents:
diff changeset
1456 break;
kono
parents:
diff changeset
1457 case LT:
kono
parents:
diff changeset
1458 cr16_cmp_str = "gt";
kono
parents:
diff changeset
1459 break;
kono
parents:
diff changeset
1460 case LTU:
kono
parents:
diff changeset
1461 cr16_cmp_str = "hi";
kono
parents:
diff changeset
1462 break;
kono
parents:
diff changeset
1463 case GE:
kono
parents:
diff changeset
1464 cr16_cmp_str = "le";
kono
parents:
diff changeset
1465 break;
kono
parents:
diff changeset
1466 case GEU:
kono
parents:
diff changeset
1467 cr16_cmp_str = "ls";
kono
parents:
diff changeset
1468 break;
kono
parents:
diff changeset
1469 case LE:
kono
parents:
diff changeset
1470 cr16_cmp_str = "ge";
kono
parents:
diff changeset
1471 break;
kono
parents:
diff changeset
1472 case LEU:
kono
parents:
diff changeset
1473 cr16_cmp_str = "hs";
kono
parents:
diff changeset
1474 break;
kono
parents:
diff changeset
1475 default:
kono
parents:
diff changeset
1476 gcc_unreachable ();
kono
parents:
diff changeset
1477 }
kono
parents:
diff changeset
1478 fprintf (file, "%s", cr16_cmp_str);
kono
parents:
diff changeset
1479 return;
kono
parents:
diff changeset
1480 }
kono
parents:
diff changeset
1481 case '$':
kono
parents:
diff changeset
1482 putc ('$', file);
kono
parents:
diff changeset
1483 return;
kono
parents:
diff changeset
1484
kono
parents:
diff changeset
1485 case 'p':
kono
parents:
diff changeset
1486 if (GET_CODE (x) == REG)
kono
parents:
diff changeset
1487 {
kono
parents:
diff changeset
1488 /* For Push instructions, we should not print register pairs. */
kono
parents:
diff changeset
1489 fprintf (file, "%s", reg_names[REGNO (x)]);
kono
parents:
diff changeset
1490 return;
kono
parents:
diff changeset
1491 }
kono
parents:
diff changeset
1492 break;
kono
parents:
diff changeset
1493
kono
parents:
diff changeset
1494 case 'b':
kono
parents:
diff changeset
1495 /* Print the immediate address for bal
kono
parents:
diff changeset
1496 'b' is used instead of 'a' to avoid compiler calling
kono
parents:
diff changeset
1497 the GO_IF_LEGITIMATE_ADDRESS which cannot
kono
parents:
diff changeset
1498 perform checks on const_int code addresses as it
kono
parents:
diff changeset
1499 assumes all const_int are data addresses. */
kono
parents:
diff changeset
1500 fprintf (file, "0x%lx", INTVAL (x));
kono
parents:
diff changeset
1501 return;
kono
parents:
diff changeset
1502
kono
parents:
diff changeset
1503 case 'r':
kono
parents:
diff changeset
1504 /* Print bit position of first 0. */
kono
parents:
diff changeset
1505 fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
kono
parents:
diff changeset
1506 return;
kono
parents:
diff changeset
1507
kono
parents:
diff changeset
1508 case 's':
kono
parents:
diff changeset
1509 /* Print bit position of first 1. */
kono
parents:
diff changeset
1510 fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
kono
parents:
diff changeset
1511 return;
kono
parents:
diff changeset
1512 case 'g':
kono
parents:
diff changeset
1513 /* 'g' is used for implicit mem: dereference. */
kono
parents:
diff changeset
1514 ptr_dereference = 1;
kono
parents:
diff changeset
1515 /* FALLTHRU */
kono
parents:
diff changeset
1516 case 'f':
kono
parents:
diff changeset
1517 case 0:
kono
parents:
diff changeset
1518 /* default. */
kono
parents:
diff changeset
1519 switch (GET_CODE (x))
kono
parents:
diff changeset
1520 {
kono
parents:
diff changeset
1521 case REG:
kono
parents:
diff changeset
1522 if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
kono
parents:
diff changeset
1523 {
kono
parents:
diff changeset
1524 if (LONG_REG_P (REGNO (x)))
kono
parents:
diff changeset
1525 fprintf (file, "(%s)", reg_names[REGNO (x)]);
kono
parents:
diff changeset
1526 else
kono
parents:
diff changeset
1527 fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
kono
parents:
diff changeset
1528 reg_names[REGNO (x)]);
kono
parents:
diff changeset
1529 }
kono
parents:
diff changeset
1530 else
kono
parents:
diff changeset
1531 fprintf (file, "%s", reg_names[REGNO (x)]);
kono
parents:
diff changeset
1532 return;
kono
parents:
diff changeset
1533
kono
parents:
diff changeset
1534 case MEM:
kono
parents:
diff changeset
1535 output_address (GET_MODE (x), XEXP (x, 0));
kono
parents:
diff changeset
1536 return;
kono
parents:
diff changeset
1537
kono
parents:
diff changeset
1538 case CONST_DOUBLE:
kono
parents:
diff changeset
1539 {
kono
parents:
diff changeset
1540 long l;
kono
parents:
diff changeset
1541
kono
parents:
diff changeset
1542 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
kono
parents:
diff changeset
1543
kono
parents:
diff changeset
1544 fprintf (file, "$0x%lx", l);
kono
parents:
diff changeset
1545 return;
kono
parents:
diff changeset
1546 }
kono
parents:
diff changeset
1547 case CONST_INT:
kono
parents:
diff changeset
1548 {
kono
parents:
diff changeset
1549 fprintf (file, "$%ld", INTVAL (x));
kono
parents:
diff changeset
1550 return;
kono
parents:
diff changeset
1551 }
kono
parents:
diff changeset
1552 case UNSPEC:
kono
parents:
diff changeset
1553 switch (XINT (x, 1))
kono
parents:
diff changeset
1554 {
kono
parents:
diff changeset
1555 default:
kono
parents:
diff changeset
1556 gcc_unreachable ();
kono
parents:
diff changeset
1557 }
kono
parents:
diff changeset
1558 break;
kono
parents:
diff changeset
1559
kono
parents:
diff changeset
1560 default:
kono
parents:
diff changeset
1561 if (!ptr_dereference)
kono
parents:
diff changeset
1562 {
kono
parents:
diff changeset
1563 putc ('$', file);
kono
parents:
diff changeset
1564 }
kono
parents:
diff changeset
1565 cr16_print_operand_address (file, VOIDmode, x);
kono
parents:
diff changeset
1566 return;
kono
parents:
diff changeset
1567 }
kono
parents:
diff changeset
1568 gcc_unreachable ();
kono
parents:
diff changeset
1569 default:
kono
parents:
diff changeset
1570 output_operand_lossage ("invalid %%xn code");
kono
parents:
diff changeset
1571 }
kono
parents:
diff changeset
1572
kono
parents:
diff changeset
1573 gcc_unreachable ();
kono
parents:
diff changeset
1574 }
kono
parents:
diff changeset
1575
kono
parents:
diff changeset
1576 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
kono
parents:
diff changeset
1577
kono
parents:
diff changeset
1578 static void
kono
parents:
diff changeset
1579 cr16_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr)
kono
parents:
diff changeset
1580 {
kono
parents:
diff changeset
1581 enum cr16_addrtype addrtype;
kono
parents:
diff changeset
1582 struct cr16_address address;
kono
parents:
diff changeset
1583
kono
parents:
diff changeset
1584 /* Decompose the address. Also ask it to treat address as constant. */
kono
parents:
diff changeset
1585 addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
kono
parents:
diff changeset
1586
kono
parents:
diff changeset
1587 if (address.disp && GET_CODE (address.disp) == UNSPEC)
kono
parents:
diff changeset
1588 {
kono
parents:
diff changeset
1589 debug_rtx (addr);
kono
parents:
diff changeset
1590 }
kono
parents:
diff changeset
1591
kono
parents:
diff changeset
1592 switch (addrtype)
kono
parents:
diff changeset
1593 {
kono
parents:
diff changeset
1594 case CR16_REG_REL:
kono
parents:
diff changeset
1595 if (address.disp)
kono
parents:
diff changeset
1596 {
kono
parents:
diff changeset
1597 if (GET_CODE (address.disp) == UNSPEC)
kono
parents:
diff changeset
1598 cr16_print_operand (file, address.disp, 0);
kono
parents:
diff changeset
1599 else
kono
parents:
diff changeset
1600 output_addr_const (file, address.disp);
kono
parents:
diff changeset
1601 }
kono
parents:
diff changeset
1602 else
kono
parents:
diff changeset
1603 fprintf (file, "0");
kono
parents:
diff changeset
1604 fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
kono
parents:
diff changeset
1605 break;
kono
parents:
diff changeset
1606
kono
parents:
diff changeset
1607 case CR16_ABSOLUTE:
kono
parents:
diff changeset
1608 if (address.disp)
kono
parents:
diff changeset
1609 output_addr_const (file, address.disp);
kono
parents:
diff changeset
1610 else
kono
parents:
diff changeset
1611 fprintf (file, "0");
kono
parents:
diff changeset
1612 break;
kono
parents:
diff changeset
1613
kono
parents:
diff changeset
1614 case CR16_INDEX_REGP_REL:
kono
parents:
diff changeset
1615 fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
kono
parents:
diff changeset
1616 /* Fall through. */
kono
parents:
diff changeset
1617 case CR16_REGP_REL:
kono
parents:
diff changeset
1618 if (address.disp)
kono
parents:
diff changeset
1619 {
kono
parents:
diff changeset
1620 if (GET_CODE (address.disp) == UNSPEC)
kono
parents:
diff changeset
1621 cr16_print_operand (file, address.disp, 0);
kono
parents:
diff changeset
1622 else
kono
parents:
diff changeset
1623 output_addr_const (file, address.disp);
kono
parents:
diff changeset
1624 }
kono
parents:
diff changeset
1625 else
kono
parents:
diff changeset
1626 fprintf (file, "0");
kono
parents:
diff changeset
1627 fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
kono
parents:
diff changeset
1628 reg_names[REGNO (address.base)]);
kono
parents:
diff changeset
1629 break;
kono
parents:
diff changeset
1630 default:
kono
parents:
diff changeset
1631 debug_rtx (addr);
kono
parents:
diff changeset
1632 gcc_unreachable ();
kono
parents:
diff changeset
1633 }
kono
parents:
diff changeset
1634 /* Add qualifiers to the address expression that was just printed. */
kono
parents:
diff changeset
1635 if (flag_pic < NEAR_PIC && address.code == 0)
kono
parents:
diff changeset
1636 {
kono
parents:
diff changeset
1637 if (address.data == DM_FAR)
kono
parents:
diff changeset
1638 /* Addr contains SYMBOL_REF & far data ptr. */
kono
parents:
diff changeset
1639 fprintf (file, "@l");
kono
parents:
diff changeset
1640 else if (address.data == DM_DEFAULT)
kono
parents:
diff changeset
1641 /* Addr contains SYMBOL_REF & medium data ptr. */
kono
parents:
diff changeset
1642 fprintf (file, "@m");
kono
parents:
diff changeset
1643 /* Addr contains SYMBOL_REF & medium data ptr. */
kono
parents:
diff changeset
1644 else if (address.data == DM_NEAR)
kono
parents:
diff changeset
1645 /* Addr contains SYMBOL_REF & near data ptr. */
kono
parents:
diff changeset
1646 fprintf (file, "@s");
kono
parents:
diff changeset
1647 }
kono
parents:
diff changeset
1648 else if (flag_pic == NEAR_PIC
kono
parents:
diff changeset
1649 && (address.code == 0) && (address.data == DM_FAR
kono
parents:
diff changeset
1650 || address.data == DM_DEFAULT
kono
parents:
diff changeset
1651 || address.data == DM_NEAR))
kono
parents:
diff changeset
1652 {
kono
parents:
diff changeset
1653 fprintf (file, "@l");
kono
parents:
diff changeset
1654 }
kono
parents:
diff changeset
1655 else if (flag_pic == NEAR_PIC && address.code == 2)
kono
parents:
diff changeset
1656 {
kono
parents:
diff changeset
1657 fprintf (file, "pic");
kono
parents:
diff changeset
1658 }
kono
parents:
diff changeset
1659 else if (flag_pic == NEAR_PIC && address.code == 1)
kono
parents:
diff changeset
1660 {
kono
parents:
diff changeset
1661 fprintf (file, "@cpic");
kono
parents:
diff changeset
1662 }
kono
parents:
diff changeset
1663
kono
parents:
diff changeset
1664 else if (flag_pic == FAR_PIC && address.code == 2)
kono
parents:
diff changeset
1665 {
kono
parents:
diff changeset
1666 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
kono
parents:
diff changeset
1667 address ! GOTc tells assembler this symbol is a text-address
kono
parents:
diff changeset
1668 This needs to be fixed in such a way that this offset is done
kono
parents:
diff changeset
1669 only in the case where an address is being used for indirect jump
kono
parents:
diff changeset
1670 or call. Determining the potential usage of loadd is of course not
kono
parents:
diff changeset
1671 possible always. Eventually, this has to be fixed in the
kono
parents:
diff changeset
1672 processor. */
kono
parents:
diff changeset
1673 fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
kono
parents:
diff changeset
1674 }
kono
parents:
diff changeset
1675 else if (flag_pic == FAR_PIC && address.code == 1)
kono
parents:
diff changeset
1676 {
kono
parents:
diff changeset
1677 fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
kono
parents:
diff changeset
1678 }
kono
parents:
diff changeset
1679
kono
parents:
diff changeset
1680 else if (flag_pic == FAR_PIC &&
kono
parents:
diff changeset
1681 (address.data == DM_FAR || address.data == DM_DEFAULT
kono
parents:
diff changeset
1682 || address.data == DM_NEAR))
kono
parents:
diff changeset
1683 {
kono
parents:
diff changeset
1684 fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
kono
parents:
diff changeset
1685 }
kono
parents:
diff changeset
1686 }
kono
parents:
diff changeset
1687
kono
parents:
diff changeset
1688 /* Machine description helper functions. */
kono
parents:
diff changeset
1689
kono
parents:
diff changeset
1690 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
kono
parents:
diff changeset
1691 When push_or_pop is zero -> string for push instructions of prologue.
kono
parents:
diff changeset
1692 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
kono
parents:
diff changeset
1693 Relies on the assumptions:
kono
parents:
diff changeset
1694 1. RA is the last register to be saved.
kono
parents:
diff changeset
1695 2. The maximal value of the counter is MAX_COUNT. */
kono
parents:
diff changeset
1696 char *
kono
parents:
diff changeset
1697 cr16_prepare_push_pop_string (int push_or_pop)
kono
parents:
diff changeset
1698 {
kono
parents:
diff changeset
1699 /* j is the number of registers being saved, takes care that there won't be
kono
parents:
diff changeset
1700 more than 8 in one push/pop instruction. */
kono
parents:
diff changeset
1701
kono
parents:
diff changeset
1702 /* For the register mask string. */
kono
parents:
diff changeset
1703 static char one_inst_str[50];
kono
parents:
diff changeset
1704
kono
parents:
diff changeset
1705 /* i is the index of current_frame_info.save_regs[], going from 0 until
kono
parents:
diff changeset
1706 current_frame_info.last_reg_to_save. */
kono
parents:
diff changeset
1707 int i, start_reg;
kono
parents:
diff changeset
1708 int word_cnt;
kono
parents:
diff changeset
1709 int print_ra;
kono
parents:
diff changeset
1710 char *return_str;
kono
parents:
diff changeset
1711
kono
parents:
diff changeset
1712 /* For reversing on the push instructions if there are more than one. */
kono
parents:
diff changeset
1713 char *temp_str;
kono
parents:
diff changeset
1714
kono
parents:
diff changeset
1715 return_str = (char *) xmalloc (160);
kono
parents:
diff changeset
1716 temp_str = (char *) xmalloc (160);
kono
parents:
diff changeset
1717
kono
parents:
diff changeset
1718 /* Initialize. */
kono
parents:
diff changeset
1719 memset (return_str, 0, 3);
kono
parents:
diff changeset
1720
kono
parents:
diff changeset
1721 i = 0;
kono
parents:
diff changeset
1722 while (i <= current_frame_info.last_reg_to_save)
kono
parents:
diff changeset
1723 {
kono
parents:
diff changeset
1724 /* Prepare mask for one instruction. */
kono
parents:
diff changeset
1725 one_inst_str[0] = 0;
kono
parents:
diff changeset
1726
kono
parents:
diff changeset
1727 /* To count number of words in one instruction. */
kono
parents:
diff changeset
1728 word_cnt = 0;
kono
parents:
diff changeset
1729 start_reg = i;
kono
parents:
diff changeset
1730 print_ra = 0;
kono
parents:
diff changeset
1731 while ((word_cnt < MAX_COUNT)
kono
parents:
diff changeset
1732 && (i <= current_frame_info.last_reg_to_save))
kono
parents:
diff changeset
1733 {
kono
parents:
diff changeset
1734 /* For each non consecutive save register,
kono
parents:
diff changeset
1735 a new instruction shall be generated. */
kono
parents:
diff changeset
1736 if (!current_frame_info.save_regs[i])
kono
parents:
diff changeset
1737 {
kono
parents:
diff changeset
1738 /* Move to next reg and break. */
kono
parents:
diff changeset
1739 ++i;
kono
parents:
diff changeset
1740 break;
kono
parents:
diff changeset
1741 }
kono
parents:
diff changeset
1742
kono
parents:
diff changeset
1743 if (i == RETURN_ADDRESS_REGNUM)
kono
parents:
diff changeset
1744 print_ra = 1;
kono
parents:
diff changeset
1745 else
kono
parents:
diff changeset
1746 {
kono
parents:
diff changeset
1747 /* Check especially if adding 2 does not cross the MAX_COUNT. */
kono
parents:
diff changeset
1748 if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
kono
parents:
diff changeset
1749 >= MAX_COUNT)
kono
parents:
diff changeset
1750 break;
kono
parents:
diff changeset
1751 /* Increase word count by 2 for long registers except RA. */
kono
parents:
diff changeset
1752 word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
kono
parents:
diff changeset
1753 }
kono
parents:
diff changeset
1754 ++i;
kono
parents:
diff changeset
1755 }
kono
parents:
diff changeset
1756
kono
parents:
diff changeset
1757 /* No need to generate any instruction as
kono
parents:
diff changeset
1758 no register or RA needs to be saved. */
kono
parents:
diff changeset
1759 if ((word_cnt == 0) && (print_ra == 0))
kono
parents:
diff changeset
1760 continue;
kono
parents:
diff changeset
1761
kono
parents:
diff changeset
1762 /* Now prepare the instruction operands. */
kono
parents:
diff changeset
1763 if (word_cnt > 0)
kono
parents:
diff changeset
1764 {
kono
parents:
diff changeset
1765 sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
kono
parents:
diff changeset
1766 if (print_ra)
kono
parents:
diff changeset
1767 strcat (one_inst_str, ", ra");
kono
parents:
diff changeset
1768 }
kono
parents:
diff changeset
1769 else
kono
parents:
diff changeset
1770 strcat (one_inst_str, "ra");
kono
parents:
diff changeset
1771
kono
parents:
diff changeset
1772 if (push_or_pop == 1)
kono
parents:
diff changeset
1773 {
kono
parents:
diff changeset
1774 /* Pop instruction. */
kono
parents:
diff changeset
1775 if (print_ra && !cr16_interrupt_function_p ()
kono
parents:
diff changeset
1776 && !crtl->calls_eh_return)
kono
parents:
diff changeset
1777 /* Print popret if RA is saved and its not a interrupt
kono
parents:
diff changeset
1778 function. */
kono
parents:
diff changeset
1779 strcpy (temp_str, "\n\tpopret\t");
kono
parents:
diff changeset
1780 else
kono
parents:
diff changeset
1781 strcpy (temp_str, "\n\tpop\t");
kono
parents:
diff changeset
1782
kono
parents:
diff changeset
1783 strcat (temp_str, one_inst_str);
kono
parents:
diff changeset
1784
kono
parents:
diff changeset
1785 /* Add the pop instruction list. */
kono
parents:
diff changeset
1786 strcat (return_str, temp_str);
kono
parents:
diff changeset
1787 }
kono
parents:
diff changeset
1788 else
kono
parents:
diff changeset
1789 {
kono
parents:
diff changeset
1790 /* Push instruction. */
kono
parents:
diff changeset
1791 strcpy (temp_str, "\n\tpush\t");
kono
parents:
diff changeset
1792 strcat (temp_str, one_inst_str);
kono
parents:
diff changeset
1793
kono
parents:
diff changeset
1794 /* We need to reverse the order of the instructions if there
kono
parents:
diff changeset
1795 are more than one. (since the pop will not be reversed in
kono
parents:
diff changeset
1796 the epilogue. */
kono
parents:
diff changeset
1797 strcat (temp_str, return_str);
kono
parents:
diff changeset
1798 strcpy (return_str, temp_str);
kono
parents:
diff changeset
1799 }
kono
parents:
diff changeset
1800 }
kono
parents:
diff changeset
1801
kono
parents:
diff changeset
1802 if (push_or_pop == 1)
kono
parents:
diff changeset
1803 {
kono
parents:
diff changeset
1804 /* POP. */
kono
parents:
diff changeset
1805 if (cr16_interrupt_function_p ())
kono
parents:
diff changeset
1806 strcat (return_str, "\n\tretx\n");
kono
parents:
diff changeset
1807 else if (crtl->calls_eh_return)
kono
parents:
diff changeset
1808 {
kono
parents:
diff changeset
1809 /* Add stack adjustment before returning to exception handler
kono
parents:
diff changeset
1810 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
kono
parents:
diff changeset
1811 strcat (return_str, "\n\taddd\t (r5, r4), (sp)\t\n");
kono
parents:
diff changeset
1812 strcat (return_str, "\n\tjump\t (ra)\n");
kono
parents:
diff changeset
1813
kono
parents:
diff changeset
1814 /* But before anything else, undo the adjustment addition done in
kono
parents:
diff changeset
1815 cr16_expand_epilogue (). */
kono
parents:
diff changeset
1816 strcpy (temp_str, "\n\tsubd\t (r5, r4), (sp)\t\n");
kono
parents:
diff changeset
1817 strcat (temp_str, return_str);
kono
parents:
diff changeset
1818 strcpy (return_str, temp_str);
kono
parents:
diff changeset
1819 }
kono
parents:
diff changeset
1820 else if (!FUNC_IS_NORETURN_P (current_function_decl)
kono
parents:
diff changeset
1821 && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]))
kono
parents:
diff changeset
1822 strcat (return_str, "\n\tjump\t (ra)\n");
kono
parents:
diff changeset
1823 }
kono
parents:
diff changeset
1824
kono
parents:
diff changeset
1825 /* Skip the newline and the tab in the start of return_str. */
kono
parents:
diff changeset
1826 return_str += 2;
kono
parents:
diff changeset
1827 return return_str;
kono
parents:
diff changeset
1828 }
kono
parents:
diff changeset
1829
kono
parents:
diff changeset
1830
kono
parents:
diff changeset
1831 /* Generate DWARF2 annotation for multi-push instruction. */
kono
parents:
diff changeset
1832 static void
kono
parents:
diff changeset
1833 cr16_create_dwarf_for_multi_push (rtx insn)
kono
parents:
diff changeset
1834 {
kono
parents:
diff changeset
1835 rtx dwarf, reg, tmp;
kono
parents:
diff changeset
1836 int i, j, from, to, word_cnt, dwarf_par_index, inc;
kono
parents:
diff changeset
1837 machine_mode mode;
kono
parents:
diff changeset
1838 int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
kono
parents:
diff changeset
1839
kono
parents:
diff changeset
1840 for (i = 0; i <= current_frame_info.last_reg_to_save; ++i)
kono
parents:
diff changeset
1841 {
kono
parents:
diff changeset
1842 if (current_frame_info.save_regs[i])
kono
parents:
diff changeset
1843 {
kono
parents:
diff changeset
1844 ++num_regs;
kono
parents:
diff changeset
1845 if (i < CR16_FIRST_DWORD_REGISTER)
kono
parents:
diff changeset
1846 total_push_bytes += 2;
kono
parents:
diff changeset
1847 else
kono
parents:
diff changeset
1848 total_push_bytes += 4;
kono
parents:
diff changeset
1849 }
kono
parents:
diff changeset
1850 }
kono
parents:
diff changeset
1851
kono
parents:
diff changeset
1852 if (!num_regs)
kono
parents:
diff changeset
1853 return;
kono
parents:
diff changeset
1854
kono
parents:
diff changeset
1855 dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
kono
parents:
diff changeset
1856 dwarf_par_index = num_regs;
kono
parents:
diff changeset
1857
kono
parents:
diff changeset
1858 from = current_frame_info.last_reg_to_save + 1;
kono
parents:
diff changeset
1859 to = current_frame_info.last_reg_to_save;
kono
parents:
diff changeset
1860 word_cnt = 0;
kono
parents:
diff changeset
1861
kono
parents:
diff changeset
1862 for (i = current_frame_info.last_reg_to_save; i >= 0;)
kono
parents:
diff changeset
1863 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1864 if (!current_frame_info.save_regs[i] || i == 0 || split_here)
111
kono
parents:
diff changeset
1865 {
kono
parents:
diff changeset
1866 /* This block of regs is pushed in one instruction. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1867 if (i == 0 && current_frame_info.save_regs[i])
111
kono
parents:
diff changeset
1868 from = 0;
kono
parents:
diff changeset
1869
kono
parents:
diff changeset
1870 for (j = to; j >= from; --j)
kono
parents:
diff changeset
1871 {
kono
parents:
diff changeset
1872 if (j < CR16_FIRST_DWORD_REGISTER)
kono
parents:
diff changeset
1873 {
kono
parents:
diff changeset
1874 mode = HImode;
kono
parents:
diff changeset
1875 inc = 1;
kono
parents:
diff changeset
1876 }
kono
parents:
diff changeset
1877 else
kono
parents:
diff changeset
1878 {
kono
parents:
diff changeset
1879 mode = SImode;
kono
parents:
diff changeset
1880 inc = 2;
kono
parents:
diff changeset
1881 }
kono
parents:
diff changeset
1882 reg = gen_rtx_REG (mode, j);
kono
parents:
diff changeset
1883 offset += 2 * inc;
kono
parents:
diff changeset
1884 tmp = gen_rtx_SET (gen_frame_mem (mode,
kono
parents:
diff changeset
1885 plus_constant
kono
parents:
diff changeset
1886 (Pmode, stack_pointer_rtx,
kono
parents:
diff changeset
1887 total_push_bytes - offset)),
kono
parents:
diff changeset
1888 reg);
kono
parents:
diff changeset
1889 RTX_FRAME_RELATED_P (tmp) = 1;
kono
parents:
diff changeset
1890 XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
kono
parents:
diff changeset
1891 }
kono
parents:
diff changeset
1892 from = i;
kono
parents:
diff changeset
1893 to = --i;
kono
parents:
diff changeset
1894 split_here = 0;
kono
parents:
diff changeset
1895 word_cnt = 0;
kono
parents:
diff changeset
1896 continue;
kono
parents:
diff changeset
1897 }
kono
parents:
diff changeset
1898
kono
parents:
diff changeset
1899 if (i != RETURN_ADDRESS_REGNUM)
kono
parents:
diff changeset
1900 {
kono
parents:
diff changeset
1901 inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
kono
parents:
diff changeset
1902 if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
kono
parents:
diff changeset
1903 {
kono
parents:
diff changeset
1904 split_here = 1;
kono
parents:
diff changeset
1905 from = i;
kono
parents:
diff changeset
1906 continue;
kono
parents:
diff changeset
1907 }
kono
parents:
diff changeset
1908 word_cnt += inc;
kono
parents:
diff changeset
1909 }
kono
parents:
diff changeset
1910
kono
parents:
diff changeset
1911 from = i--;
kono
parents:
diff changeset
1912 }
kono
parents:
diff changeset
1913
kono
parents:
diff changeset
1914 tmp = gen_rtx_SET (stack_pointer_rtx,
kono
parents:
diff changeset
1915 gen_rtx_PLUS (SImode, stack_pointer_rtx,
kono
parents:
diff changeset
1916 GEN_INT (-offset)));
kono
parents:
diff changeset
1917 RTX_FRAME_RELATED_P (tmp) = 1;
kono
parents:
diff changeset
1918 XVECEXP (dwarf, 0, 0) = tmp;
kono
parents:
diff changeset
1919
kono
parents:
diff changeset
1920 add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
kono
parents:
diff changeset
1921 }
kono
parents:
diff changeset
1922
kono
parents:
diff changeset
1923 /*
kono
parents:
diff changeset
1924 CompactRISC CR16 Architecture stack layout:
kono
parents:
diff changeset
1925
kono
parents:
diff changeset
1926 0 +---------------------
kono
parents:
diff changeset
1927 |
kono
parents:
diff changeset
1928 .
kono
parents:
diff changeset
1929 .
kono
parents:
diff changeset
1930 |
kono
parents:
diff changeset
1931 +==================== Sp (x) = Ap (x+1)
kono
parents:
diff changeset
1932 A | Args for functions
kono
parents:
diff changeset
1933 | | called by X and Dynamically
kono
parents:
diff changeset
1934 | | Dynamic allocations allocated and
kono
parents:
diff changeset
1935 | | (alloca, variable deallocated
kono
parents:
diff changeset
1936 Stack | length arrays).
kono
parents:
diff changeset
1937 grows +-------------------- Fp (x)
kono
parents:
diff changeset
1938 down| | Local variables of X
kono
parents:
diff changeset
1939 ward| +--------------------
kono
parents:
diff changeset
1940 | | Regs saved for X-1
kono
parents:
diff changeset
1941 | +==================== Sp (x-1) = Ap (x)
kono
parents:
diff changeset
1942 | Args for func X
kono
parents:
diff changeset
1943 | pushed by X-1
kono
parents:
diff changeset
1944 +-------------------- Fp (x-1)
kono
parents:
diff changeset
1945 |
kono
parents:
diff changeset
1946 |
kono
parents:
diff changeset
1947 V
kono
parents:
diff changeset
1948 */
kono
parents:
diff changeset
1949 void
kono
parents:
diff changeset
1950 cr16_expand_prologue (void)
kono
parents:
diff changeset
1951 {
kono
parents:
diff changeset
1952 rtx insn;
kono
parents:
diff changeset
1953
kono
parents:
diff changeset
1954 cr16_compute_frame ();
kono
parents:
diff changeset
1955 cr16_compute_save_regs ();
kono
parents:
diff changeset
1956
kono
parents:
diff changeset
1957 /* If there is no need in push and adjustment to sp, return. */
kono
parents:
diff changeset
1958 if ((current_frame_info.total_size + current_frame_info.reg_size) == 0)
kono
parents:
diff changeset
1959 return;
kono
parents:
diff changeset
1960
kono
parents:
diff changeset
1961 if (current_frame_info.last_reg_to_save != -1)
kono
parents:
diff changeset
1962 {
kono
parents:
diff changeset
1963 /* If there are registers to push. */
kono
parents:
diff changeset
1964 insn = emit_insn (gen_push_for_prologue
kono
parents:
diff changeset
1965 (GEN_INT (current_frame_info.reg_size)));
kono
parents:
diff changeset
1966 cr16_create_dwarf_for_multi_push (insn);
kono
parents:
diff changeset
1967 RTX_FRAME_RELATED_P (insn) = 1;
kono
parents:
diff changeset
1968 }
kono
parents:
diff changeset
1969
kono
parents:
diff changeset
1970
kono
parents:
diff changeset
1971 if (current_frame_info.total_size > 0)
kono
parents:
diff changeset
1972 {
kono
parents:
diff changeset
1973 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
kono
parents:
diff changeset
1974 GEN_INT (-current_frame_info.total_size)));
kono
parents:
diff changeset
1975 RTX_FRAME_RELATED_P (insn) = 1;
kono
parents:
diff changeset
1976 }
kono
parents:
diff changeset
1977
kono
parents:
diff changeset
1978 if (frame_pointer_needed)
kono
parents:
diff changeset
1979 {
kono
parents:
diff changeset
1980 /* Initialize the frame pointer with the value of the stack pointer
kono
parents:
diff changeset
1981 pointing now to the locals. */
kono
parents:
diff changeset
1982 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
kono
parents:
diff changeset
1983 }
kono
parents:
diff changeset
1984 }
kono
parents:
diff changeset
1985
kono
parents:
diff changeset
1986 /* Generate insn that updates the stack for local variables and padding
kono
parents:
diff changeset
1987 for registers we save. - Generate the appropriate return insn. */
kono
parents:
diff changeset
1988 void
kono
parents:
diff changeset
1989 cr16_expand_epilogue (void)
kono
parents:
diff changeset
1990 {
kono
parents:
diff changeset
1991 rtx insn;
kono
parents:
diff changeset
1992
kono
parents:
diff changeset
1993 /* Nonzero if we need to return and pop only RA. This will generate a
kono
parents:
diff changeset
1994 different insn. This differentiate is for the peepholes for call as
kono
parents:
diff changeset
1995 last statement in function. */
kono
parents:
diff changeset
1996 int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]
kono
parents:
diff changeset
1997 && (current_frame_info.reg_size
kono
parents:
diff changeset
1998 == CR16_UNITS_PER_DWORD));
kono
parents:
diff changeset
1999
kono
parents:
diff changeset
2000 if (frame_pointer_needed)
kono
parents:
diff changeset
2001 {
kono
parents:
diff changeset
2002 /* Restore the stack pointer with the frame pointers value. */
kono
parents:
diff changeset
2003 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
kono
parents:
diff changeset
2004 }
kono
parents:
diff changeset
2005
kono
parents:
diff changeset
2006 if (current_frame_info.total_size > 0)
kono
parents:
diff changeset
2007 {
kono
parents:
diff changeset
2008 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
kono
parents:
diff changeset
2009 GEN_INT (current_frame_info.total_size)));
kono
parents:
diff changeset
2010 RTX_FRAME_RELATED_P (insn) = 1;
kono
parents:
diff changeset
2011 }
kono
parents:
diff changeset
2012
kono
parents:
diff changeset
2013 if (crtl->calls_eh_return)
kono
parents:
diff changeset
2014 {
kono
parents:
diff changeset
2015 /* Add this here so that (r5, r4) is actually loaded with the adjustment
kono
parents:
diff changeset
2016 value; otherwise, the load might be optimized away...
kono
parents:
diff changeset
2017 NOTE: remember to subtract the adjustment before popping the regs
kono
parents:
diff changeset
2018 and add it back before returning. */
kono
parents:
diff changeset
2019 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
kono
parents:
diff changeset
2020 EH_RETURN_STACKADJ_RTX));
kono
parents:
diff changeset
2021 }
kono
parents:
diff changeset
2022
kono
parents:
diff changeset
2023 if (cr16_interrupt_function_p ())
kono
parents:
diff changeset
2024 {
kono
parents:
diff changeset
2025 insn = emit_jump_insn (gen_interrupt_return ());
kono
parents:
diff changeset
2026 RTX_FRAME_RELATED_P (insn) = 1;
kono
parents:
diff changeset
2027 }
kono
parents:
diff changeset
2028 else if (crtl->calls_eh_return)
kono
parents:
diff changeset
2029 {
kono
parents:
diff changeset
2030 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
kono
parents:
diff changeset
2031 insn = emit_jump_insn (gen_pop_and_popret_return
kono
parents:
diff changeset
2032 (GEN_INT (current_frame_info.reg_size)));
kono
parents:
diff changeset
2033 RTX_FRAME_RELATED_P (insn) = 1;
kono
parents:
diff changeset
2034 }
kono
parents:
diff changeset
2035 else if (current_frame_info.last_reg_to_save == -1)
kono
parents:
diff changeset
2036 /* Nothing to pop. */
kono
parents:
diff changeset
2037 /* Don't output jump for interrupt routine, only retx. */
kono
parents:
diff changeset
2038 emit_jump_insn (gen_jump_return ());
kono
parents:
diff changeset
2039 else if (only_popret_RA)
kono
parents:
diff changeset
2040 {
kono
parents:
diff changeset
2041 insn = emit_jump_insn (gen_popret_RA_return ());
kono
parents:
diff changeset
2042 RTX_FRAME_RELATED_P (insn) = 1;
kono
parents:
diff changeset
2043 }
kono
parents:
diff changeset
2044 else
kono
parents:
diff changeset
2045 {
kono
parents:
diff changeset
2046 insn = emit_jump_insn (gen_pop_and_popret_return
kono
parents:
diff changeset
2047 (GEN_INT (current_frame_info.reg_size)));
kono
parents:
diff changeset
2048 RTX_FRAME_RELATED_P (insn) = 1;
kono
parents:
diff changeset
2049 }
kono
parents:
diff changeset
2050 }
kono
parents:
diff changeset
2051
kono
parents:
diff changeset
2052 /* Implements FRAME_POINTER_REQUIRED. */
kono
parents:
diff changeset
2053 static bool
kono
parents:
diff changeset
2054 cr16_frame_pointer_required (void)
kono
parents:
diff changeset
2055 {
kono
parents:
diff changeset
2056 return (cfun->calls_alloca || crtl->calls_eh_return
kono
parents:
diff changeset
2057 || cfun->has_nonlocal_label || crtl->calls_eh_return);
kono
parents:
diff changeset
2058 }
kono
parents:
diff changeset
2059
kono
parents:
diff changeset
2060 static bool
kono
parents:
diff changeset
2061 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
kono
parents:
diff changeset
2062 {
kono
parents:
diff changeset
2063 return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
kono
parents:
diff changeset
2064 }
kono
parents:
diff changeset
2065
kono
parents:
diff changeset
2066
kono
parents:
diff changeset
2067 /* A C compound statement that attempts to replace X with
kono
parents:
diff changeset
2068 a valid memory address for an operand of mode MODE. WIN
kono
parents:
diff changeset
2069 will be a C statement label elsewhere in the code.
kono
parents:
diff changeset
2070 X will always be the result of a call to break_out_memory_refs (),
kono
parents:
diff changeset
2071 and OLDX will be the operand that was given to that function to
kono
parents:
diff changeset
2072 produce X.
kono
parents:
diff changeset
2073 The code generated by this macro should not alter the
kono
parents:
diff changeset
2074 substructure of X. If it transforms X into a more legitimate form,
kono
parents:
diff changeset
2075 it should assign X (which will always be a C variable) a new value. */
kono
parents:
diff changeset
2076 static rtx
kono
parents:
diff changeset
2077 cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
2078 machine_mode mode ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2079 {
kono
parents:
diff changeset
2080 if (flag_pic)
kono
parents:
diff changeset
2081 return legitimize_pic_address (orig_x, mode, NULL_RTX);
kono
parents:
diff changeset
2082 else
kono
parents:
diff changeset
2083 return x;
kono
parents:
diff changeset
2084 }
kono
parents:
diff changeset
2085
kono
parents:
diff changeset
2086 /* Implement TARGET_LEGITIMATE_CONSTANT_P
kono
parents:
diff changeset
2087 Nonzero if X is a legitimate constant for an immediate
kono
parents:
diff changeset
2088 operand on the target machine. You can assume that X
kono
parents:
diff changeset
2089 satisfies CONSTANT_P. In cr16c treat legitimize float
kono
parents:
diff changeset
2090 constant as an immediate operand. */
kono
parents:
diff changeset
2091 static bool
kono
parents:
diff changeset
2092 cr16_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
2093 rtx x ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2094 {
kono
parents:
diff changeset
2095 return 1;
kono
parents:
diff changeset
2096 }
kono
parents:
diff changeset
2097
kono
parents:
diff changeset
2098 void
kono
parents:
diff changeset
2099 notice_update_cc (rtx exp)
kono
parents:
diff changeset
2100 {
kono
parents:
diff changeset
2101 if (GET_CODE (exp) == SET)
kono
parents:
diff changeset
2102 {
kono
parents:
diff changeset
2103 /* Jumps do not alter the cc's. */
kono
parents:
diff changeset
2104 if (SET_DEST (exp) == pc_rtx)
kono
parents:
diff changeset
2105 return;
kono
parents:
diff changeset
2106
kono
parents:
diff changeset
2107 /* Moving register or memory into a register:
kono
parents:
diff changeset
2108 it doesn't alter the cc's, but it might invalidate
kono
parents:
diff changeset
2109 the RTX's which we remember the cc's came from.
kono
parents:
diff changeset
2110 (Note that moving a constant 0 or 1 MAY set the cc's). */
kono
parents:
diff changeset
2111 if (REG_P (SET_DEST (exp))
kono
parents:
diff changeset
2112 && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
kono
parents:
diff changeset
2113 {
kono
parents:
diff changeset
2114 return;
kono
parents:
diff changeset
2115 }
kono
parents:
diff changeset
2116
kono
parents:
diff changeset
2117 /* Moving register into memory doesn't alter the cc's.
kono
parents:
diff changeset
2118 It may invalidate the RTX's which we remember the cc's came from. */
kono
parents:
diff changeset
2119 if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
kono
parents:
diff changeset
2120 {
kono
parents:
diff changeset
2121 return;
kono
parents:
diff changeset
2122 }
kono
parents:
diff changeset
2123 }
kono
parents:
diff changeset
2124
kono
parents:
diff changeset
2125 CC_STATUS_INIT;
kono
parents:
diff changeset
2126 return;
kono
parents:
diff changeset
2127 }
kono
parents:
diff changeset
2128
kono
parents:
diff changeset
2129 static scalar_int_mode
kono
parents:
diff changeset
2130 cr16_unwind_word_mode (void)
kono
parents:
diff changeset
2131 {
kono
parents:
diff changeset
2132 return SImode;
kono
parents:
diff changeset
2133 }
kono
parents:
diff changeset
2134
kono
parents:
diff changeset
2135 /* Helper function for md file. This function is used to emit arithmetic
kono
parents:
diff changeset
2136 DI instructions. The argument "num" decides which instruction to be
kono
parents:
diff changeset
2137 printed. */
kono
parents:
diff changeset
2138 const char *
kono
parents:
diff changeset
2139 cr16_emit_add_sub_di (rtx *operands, enum rtx_code code)
kono
parents:
diff changeset
2140 {
kono
parents:
diff changeset
2141 rtx lo_op[2] ;
kono
parents:
diff changeset
2142 rtx hi0_op[2] ;
kono
parents:
diff changeset
2143 rtx hi1_op[2] ;
kono
parents:
diff changeset
2144
kono
parents:
diff changeset
2145 lo_op[0] = gen_lowpart (SImode, operands[0]);
kono
parents:
diff changeset
2146 hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4);
kono
parents:
diff changeset
2147 hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6);
kono
parents:
diff changeset
2148
kono
parents:
diff changeset
2149 lo_op[1] = gen_lowpart (SImode, operands[2]);
kono
parents:
diff changeset
2150 hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4);
kono
parents:
diff changeset
2151 hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6);
kono
parents:
diff changeset
2152
kono
parents:
diff changeset
2153 switch (code)
kono
parents:
diff changeset
2154 {
kono
parents:
diff changeset
2155 case PLUS:
kono
parents:
diff changeset
2156 {
kono
parents:
diff changeset
2157 output_asm_insn ("addd\t%1, %0", lo_op) ;
kono
parents:
diff changeset
2158 output_asm_insn ("addcw\t%1, %0", hi0_op) ;
kono
parents:
diff changeset
2159 output_asm_insn ("addcw\t%1, %0", hi1_op) ;
kono
parents:
diff changeset
2160 break;
kono
parents:
diff changeset
2161 }
kono
parents:
diff changeset
2162 case MINUS:
kono
parents:
diff changeset
2163 {
kono
parents:
diff changeset
2164 output_asm_insn ("subd\t%1, %0", lo_op) ;
kono
parents:
diff changeset
2165 output_asm_insn ("subcw\t%1, %0", hi0_op) ;
kono
parents:
diff changeset
2166 output_asm_insn ("subcw\t%1, %0", hi1_op) ;
kono
parents:
diff changeset
2167 break;
kono
parents:
diff changeset
2168 }
kono
parents:
diff changeset
2169 default:
kono
parents:
diff changeset
2170 break;
kono
parents:
diff changeset
2171 }
kono
parents:
diff changeset
2172
kono
parents:
diff changeset
2173 return "";
kono
parents:
diff changeset
2174 }
kono
parents:
diff changeset
2175
kono
parents:
diff changeset
2176
kono
parents:
diff changeset
2177 /* Helper function for md file. This function is used to emit logical
kono
parents:
diff changeset
2178 DI instructions. The argument "num" decides which instruction to be
kono
parents:
diff changeset
2179 printed. */
kono
parents:
diff changeset
2180 const char *
kono
parents:
diff changeset
2181 cr16_emit_logical_di (rtx *operands, enum rtx_code code)
kono
parents:
diff changeset
2182 {
kono
parents:
diff changeset
2183 rtx lo_op[2] ;
kono
parents:
diff changeset
2184 rtx hi_op[2] ;
kono
parents:
diff changeset
2185
kono
parents:
diff changeset
2186 lo_op[0] = gen_lowpart (SImode, operands[0]);
kono
parents:
diff changeset
2187 hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4);
kono
parents:
diff changeset
2188
kono
parents:
diff changeset
2189 lo_op[1] = gen_lowpart (SImode, operands[2]);
kono
parents:
diff changeset
2190 hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4);
kono
parents:
diff changeset
2191
kono
parents:
diff changeset
2192 switch (code)
kono
parents:
diff changeset
2193 {
kono
parents:
diff changeset
2194 case AND:
kono
parents:
diff changeset
2195 {
kono
parents:
diff changeset
2196 output_asm_insn ("andd\t%1, %0", lo_op) ;
kono
parents:
diff changeset
2197 output_asm_insn ("andd\t%1, %0", hi_op) ;
kono
parents:
diff changeset
2198 return "";
kono
parents:
diff changeset
2199 }
kono
parents:
diff changeset
2200 case IOR:
kono
parents:
diff changeset
2201 {
kono
parents:
diff changeset
2202 output_asm_insn ("ord\t%1, %0", lo_op) ;
kono
parents:
diff changeset
2203 output_asm_insn ("ord\t%1, %0", hi_op) ;
kono
parents:
diff changeset
2204 return "";
kono
parents:
diff changeset
2205 }
kono
parents:
diff changeset
2206 case XOR:
kono
parents:
diff changeset
2207 {
kono
parents:
diff changeset
2208 output_asm_insn ("xord\t%1, %0", lo_op) ;
kono
parents:
diff changeset
2209 output_asm_insn ("xord\t%1, %0", hi_op) ;
kono
parents:
diff changeset
2210 return "";
kono
parents:
diff changeset
2211 }
kono
parents:
diff changeset
2212 default:
kono
parents:
diff changeset
2213 break;
kono
parents:
diff changeset
2214 }
kono
parents:
diff changeset
2215
kono
parents:
diff changeset
2216 return "";
kono
parents:
diff changeset
2217 }
kono
parents:
diff changeset
2218
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2219 /* Implement PUSH_ROUNDING. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2220
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2221 poly_int64
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2222 cr16_push_rounding (poly_int64 bytes)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2223 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2224 return (bytes + 1) & ~1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2225 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2226
111
kono
parents:
diff changeset
2227 /* Initialize 'targetm' variable which contains pointers to functions
kono
parents:
diff changeset
2228 and data relating to the target machine. */
kono
parents:
diff changeset
2229
kono
parents:
diff changeset
2230 struct gcc_target targetm = TARGET_INITIALIZER;