Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/csky/csky.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* GCC backend functions for C-SKY targets. | |
2 Copyright (C) 2018 Free Software Foundation, Inc. | |
3 Contributed by C-SKY Microsystems and Mentor Graphics. | |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published | |
9 by the Free Software Foundation; either version 3, or (at your | |
10 option) any later version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GCC; see the file COPYING3. If not see | |
19 <http://www.gnu.org/licenses/>. */ | |
20 | |
21 #define IN_TARGET_CODE 1 | |
22 | |
23 #include "config.h" | |
24 #include "system.h" | |
25 #include "coretypes.h" | |
26 #include "memmodel.h" | |
27 #include "backend.h" | |
28 #include "target.h" | |
29 #include "rtl.h" | |
30 #include "tree.h" | |
31 #include "cfghooks.h" | |
32 #include "df.h" | |
33 #include "tm_p.h" | |
34 #include "stringpool.h" | |
35 #include "attribs.h" | |
36 #include "optabs.h" | |
37 #include "regs.h" | |
38 #include "emit-rtl.h" | |
39 #include "recog.h" | |
40 #include "cgraph.h" | |
41 #include "c-family/c-common.h" | |
42 #include "cpplib.h" | |
43 #include "diagnostic-core.h" | |
44 #include "alias.h" | |
45 #include "fold-const.h" | |
46 #include "stor-layout.h" | |
47 #include "calls.h" | |
48 #include "varasm.h" | |
49 #include "output.h" | |
50 #include "insn-attr.h" | |
51 #include "flags.h" | |
52 #include "reload.h" | |
53 #include "explow.h" | |
54 #include "expr.h" | |
55 #include "cfgrtl.h" | |
56 #include "sched-int.h" | |
57 #include "common/common-target.h" | |
58 #include "langhooks.h" | |
59 #include "intl.h" | |
60 #include "libfuncs.h" | |
61 #include "params.h" | |
62 #include "opts.h" | |
63 #include "dumpfile.h" | |
64 #include "target-globals.h" | |
65 #include "builtins.h" | |
66 #include "tm-constrs.h" | |
67 #include "rtl-iter.h" | |
68 #include "pass_manager.h" | |
69 #include "tree-pass.h" | |
70 #include "context.h" | |
71 | |
72 /* This file should be included last. */ | |
73 #include "target-def.h" | |
74 | |
75 /* Stack and register size macros. */ | |
76 | |
77 #define CSKY_NUM_WORDS(SIZE) \ | |
78 (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) | |
79 #define CSKY_NUM_REGS(MODE) \ | |
80 CSKY_NUM_WORDS (GET_MODE_SIZE (MODE)) | |
81 #define CSKY_STACK_ALIGN(SIZE) \ | |
82 (CSKY_NUM_WORDS (SIZE) * UNITS_PER_WORD) | |
83 | |
84 /* Offsets and range macros. */ | |
85 | |
86 #define CSKY_LD16_MAX_OFFSET(MODE) \ | |
87 (31 * GET_MODE_SIZE (MODE)) | |
88 #define CSKY_LD32_MAX_OFFSET(MODE) \ | |
89 (4095 * GET_MODE_SIZE (MODE)) | |
90 #define CSKY_LD16_OFFSET_MASK(MODE) \ | |
91 (CSKY_LD16_MAX_OFFSET (MODE) + GET_MODE_SIZE (MODE) - 1) | |
92 | |
93 #define CSKY_ADDI16_MAX_IMM 256 | |
94 #define CSKY_SUBI16_MAX_IMM 256 | |
95 | |
96 #define CSKY_CONSTPOOL_LABEL_PREFIX "LCP" | |
97 | |
98 /* Array of the smallest class containing reg number REGNO, indexed by | |
99 REGNO. Used by REGNO_REG_CLASS. */ | |
100 enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER] = | |
101 { | |
102 /* Registers r0-r7. */ | |
103 MINI_REGS, MINI_REGS, MINI_REGS, MINI_REGS, | |
104 MINI_REGS, MINI_REGS, MINI_REGS, MINI_REGS, | |
105 /* Registers r8-r15. */ | |
106 LOW_REGS, LOW_REGS, LOW_REGS, LOW_REGS, | |
107 LOW_REGS, LOW_REGS, SP_REGS, LOW_REGS, | |
108 /* Registers r16-r31. */ | |
109 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, | |
110 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, | |
111 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, | |
112 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, | |
113 /* Reserved. */ | |
114 RESERVE_REGS, | |
115 /* CC,HI,LO registers. */ | |
116 C_REGS, HI_REGS, LO_REGS, | |
117 /* Reserved. */ | |
118 RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, | |
119 RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, | |
120 RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, | |
121 RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, RESERVE_REGS, | |
122 /* Vec registers. */ | |
123 V_REGS, V_REGS, V_REGS, V_REGS, | |
124 V_REGS, V_REGS, V_REGS, V_REGS, | |
125 V_REGS, V_REGS, V_REGS, V_REGS, | |
126 V_REGS, V_REGS, V_REGS, V_REGS, | |
127 /* Reserved. */ | |
128 RESERVE_REGS, RESERVE_REGS, | |
129 /* Register epc. */ | |
130 OTHER_REGS | |
131 }; | |
132 | |
133 /* Arrays that map GCC register numbers to debugger register numbers, | |
134 '-1' means that is INVALID_REGNUM. | |
135 TODO: which rules according to here ? */ | |
136 const int csky_dbx_regno[FIRST_PSEUDO_REGISTER] = | |
137 { | |
138 0, 1, 2, 3, 4, 5, 6, 7, | |
139 8, 9, 10, 11, 12, 13, 14, 15, | |
140 16, 17, 18, 19, 20, 21, 22, 23, | |
141 24, 25, 26, 27, 28, 29, 30, 31, | |
142 -1, -1, 36, 37, -1, -1, -1, -1, | |
143 -1, -1, -1, -1, -1, -1, -1, -1, | |
144 -1, -1, -1, -1, 56, 57, 58, 59, | |
145 60, 61, 62, 63, 64, 65, 66, 67, | |
146 68, 69, 70, 71, -1, -1, 72 | |
147 }; | |
148 | |
149 /* Table of machine attributes. */ | |
150 static tree csky_handle_fndecl_attribute (tree *, tree, tree, int, bool *); | |
151 static tree csky_handle_isr_attribute (tree *, tree, tree, int, bool *); | |
152 static const struct attribute_spec csky_attribute_table[] = | |
153 { | |
154 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, | |
155 affects_type_identity, handler, exclude } */ | |
156 { "naked", 0, 0, true, false, false, false, csky_handle_fndecl_attribute, NULL }, | |
157 /* Interrupt Service Routines have special prologue and epilogue requirements. */ | |
158 { "interrupt", 0, 1, false, false, false, false, csky_handle_isr_attribute, NULL }, | |
159 { "isr", 0, 1, false, false, false, false, csky_handle_isr_attribute, NULL }, | |
160 { NULL, 0, 0, false, false, false, false, NULL, NULL } | |
161 }; | |
162 | |
163 /* A C structure for machine-specific, per-function data. | |
164 This is added to the cfun structure. */ | |
165 typedef struct GTY(()) machine_function | |
166 { | |
167 /* Records if LR has to be saved for far jumps. */ | |
168 int far_jump_used; | |
169 /* Records the type of the current function. */ | |
170 unsigned long func_type; | |
171 /* Record if the function has a variable argument list. */ | |
172 int uses_anonymous_args; | |
173 | |
174 /* Stack frame layout information. If frame_init_p is true, | |
175 these fields have been initialized and don't need to be | |
176 recomputed. */ | |
177 unsigned int reg_mask; /* non-volatile reg saves */ | |
178 int arg_size; /* stdarg spills (bytes) */ | |
179 int reg_size; /* non-volatile reg saves (bytes) */ | |
180 int local_size; /* locals */ | |
181 int outbound_size; /* arg overflow on calls out */ | |
182 int frame_size; /* total static size of stack frame */ | |
183 int local_offset; | |
184 int reg_offset; | |
185 int arg_offset; | |
186 int frame_init_p; | |
187 | |
188 } machine_function; | |
189 | |
190 /* These macros are for the func_type values above. */ | |
191 #define CSKY_FT_TYPE_MASK ((1 << 3) - 1) | |
192 #define CSKY_FT_UNKNOWN 0 /* Type not been determined */ | |
193 #define CSKY_FT_NORMAL 1 /* Normal function */ | |
194 #define CSKY_FT_ISR 4 /* Interrupt service routine */ | |
195 #define CSKY_FT_FIQ 5 /* Fast interrupt service routine */ | |
196 #define CSKY_FT_EXCEPTION 6 /* Exception handler */ | |
197 #define CSKY_FT_INTERRUPT (1 << 2) /* overlap CSKY_FT_ISR */ | |
198 #define CSKY_FT_NAKED (1 << 3) /* No prologue and epilogue */ | |
199 #define CSKY_FUNCTION_TYPE(t) ((t) & CSKY_FT_TYPE_MASK) | |
200 #define CSKY_FUNCTION_IS_INTERRUPT(t) ((t) & CSKY_FT_INTERRUPT) | |
201 #define CSKY_FUNCTION_IS_NAKED(t) ((t) & CSKY_FT_NAKED) | |
202 | |
203 struct csky_processors | |
204 { | |
205 const char *const name; | |
206 enum csky_processor_type core; | |
207 const char *arch; | |
208 enum csky_base_architecture base_arch; | |
209 enum csky_isa_feature isa_bits[CSKY_ISA_FEATURE_GET (max)]; | |
210 }; | |
211 | |
212 static struct csky_processors all_cores[] = | |
213 { | |
214 #undef CSKY_CORE | |
215 #define CSKY_CORE(NAME, CORE, X, ARCH, ISA) \ | |
216 {NAME, TARGET_CPU_##CORE, #ARCH, CSKY_BASE_ARCH_##ARCH, \ | |
217 {ISA CSKY_ISA_FEATURE_GET (none)}}, | |
218 #include "csky_cores.def" | |
219 #undef CSKY_CORE | |
220 {NULL, TARGET_CPU_csky_none, NULL, CSKY_BASE_ARCH_NONE, \ | |
221 {CSKY_ISA_FEATURE_GET (none)}} | |
222 }; | |
223 | |
224 static struct csky_processors all_architectures[] = | |
225 { | |
226 #undef CSKY_ARCH | |
227 #define CSKY_ARCH(NAME, CORE, ARCH, ISA) \ | |
228 {NAME, TARGET_CPU_##CORE, #ARCH, CSKY_BASE_ARCH_##ARCH, \ | |
229 {ISA CSKY_ISA_FEATURE_GET (none)}}, | |
230 #include "csky_cores.def" | |
231 #undef CSKY_ARCH | |
232 {NULL, TARGET_CPU_csky_none, NULL, CSKY_BASE_ARCH_NONE, \ | |
233 {CSKY_ISA_FEATURE_GET (none)}} | |
234 }; | |
235 | |
236 struct csky_fpu_desc | |
237 { | |
238 const char *name; | |
239 enum csky_isa_feature isa_bits[CSKY_ISA_FEATURE_GET (max)]; | |
240 }; | |
241 | |
242 static const struct csky_fpu_desc all_fpus[] = | |
243 { | |
244 #undef CSKY_FPU | |
245 #define CSKY_FPU(NAME, CNAME, ISA) \ | |
246 {NAME, {ISA CSKY_ISA_FEATURE_GET (none)}}, | |
247 #include "csky_cores.def" | |
248 #undef CSKY_FPU | |
249 }; | |
250 | |
251 /* Active target architecture. */ | |
252 struct csky_build_target | |
253 { | |
254 /* Name of the target CPU, if known, or NULL if the target CPU was not | |
255 specified by the user (and inferred from the -march option). */ | |
256 const char *core_name; | |
257 /* Name of the target ARCH. NULL if there is a selected CPU. */ | |
258 const char *arch_name; | |
259 /* Preprocessor substring (never NULL). */ | |
260 const char *arch_pp_name; | |
261 /* CPU identifier for the core we're compiling for (architecturally). */ | |
262 enum csky_processor_type arch_core; | |
263 /* The base architecture value. */ | |
264 enum csky_base_architecture base_arch; | |
265 /* Bitmap encapsulating the isa_bits for the target environment. */ | |
266 sbitmap isa; | |
267 }; | |
268 | |
269 struct csky_build_target csky_active_target; | |
270 | |
271 /* The following are used in the .md file as equivalents to bits. */ | |
272 int csky_arch_isa_features[CSKY_ISA_FEATURE_GET (max)] = {0}; | |
273 | |
274 /* The highest CSKY architecture version supported by the target. */ | |
275 enum csky_base_architecture csky_base_arch = CSKY_TARGET_ARCH_GET (NONE); | |
276 | |
277 /* Forward definitions of types. */ | |
278 typedef struct minipool_node Mnode; | |
279 typedef struct minipool_fixup Mfix; | |
280 | |
281 static GTY(()) int tls_labelno; | |
282 | |
283 | |
284 /* Maximum constant offset that can be added/subtracted from SP in a | |
285 single instruction. For ck801, this is for addsp/subsp, otherwise | |
286 it is the range of addi/subi. */ | |
287 #define CSKY_MAX_SP_ADJUST \ | |
288 (CSKY_TARGET_ARCH (CK801) ? 508 : 4096) | |
289 | |
290 | |
291 /* Implement TARGET_CPU_CPP_BUILTINS. */ | |
292 | |
293 #define builtin_define(MACRO) cpp_define (pfile, MACRO) | |
294 | |
295 void | |
296 csky_cpu_cpp_builtins (cpp_reader *pfile) | |
297 { | |
298 const char *arch_name = csky_active_target.arch_pp_name; | |
299 char *pp_name = (char *) alloca (1 + strlen (arch_name) + 4); | |
300 sprintf (pp_name, "__%s__", arch_name); | |
301 builtin_define (pp_name); | |
302 | |
303 builtin_define ("__csky__=2"); | |
304 builtin_define ("__CSKY__=2"); | |
305 builtin_define ("__ckcore__=2"); | |
306 builtin_define ("__CKCORE__=2"); | |
307 | |
308 builtin_define ("__CSKYABIV2__"); | |
309 builtin_define ("__cskyabiv2__"); | |
310 builtin_define ("__CSKYABI__=2"); | |
311 builtin_define ("__cskyabi__=2"); | |
312 | |
313 if (TARGET_BIG_ENDIAN) | |
314 { | |
315 builtin_define ("__ckcoreBE__"); | |
316 builtin_define ("__cskyBE__"); | |
317 builtin_define ("__cskybe__"); | |
318 builtin_define ("__CSKYBE__"); | |
319 } | |
320 else | |
321 { | |
322 builtin_define ("__ckcoreLE__"); | |
323 builtin_define ("__cskyLE__"); | |
324 builtin_define ("__cskyle__"); | |
325 builtin_define ("__CSKYLE__"); | |
326 } | |
327 | |
328 if (TARGET_HARD_FLOAT) | |
329 { | |
330 builtin_define ("__csky_hard_float__"); | |
331 builtin_define ("__CSKY_HARD_FLOAT__"); | |
332 } | |
333 else | |
334 { | |
335 builtin_define ("__csky_soft_float__"); | |
336 builtin_define ("__CSKY_SOFT_FLOAT__"); | |
337 } | |
338 | |
339 if (CSKY_ISA_FEATURE (fpv2_sf)) | |
340 { | |
341 builtin_define ("__csky_fpuv2__"); | |
342 builtin_define ("__CSKY_FPUV2__"); | |
343 } | |
344 | |
345 if (TARGET_ELRW) | |
346 { | |
347 builtin_define ("__csky_elrw__"); | |
348 builtin_define ("__CSKY_ELRW__"); | |
349 } | |
350 if (TARGET_ISTACK) | |
351 { | |
352 builtin_define ("__csky_istack__"); | |
353 builtin_define ("__CSKY_ISTACK__"); | |
354 } | |
355 if (TARGET_MP) | |
356 { | |
357 builtin_define ("__csky_mp__"); | |
358 builtin_define ("__CSKY_MP__"); | |
359 } | |
360 if (TARGET_CP) | |
361 { | |
362 builtin_define ("__csky_cp__"); | |
363 builtin_define ("__CSKY_CP__"); | |
364 } | |
365 if (TARGET_CACHE) | |
366 { | |
367 builtin_define ("__csky_cache__"); | |
368 builtin_define ("__CSKY_CACHE__"); | |
369 } | |
370 if (TARGET_SECURITY) | |
371 { | |
372 builtin_define ("__csky_security__"); | |
373 builtin_define ("__CSKY_SECURITY__"); | |
374 } | |
375 if (TARGET_TRUST) | |
376 { | |
377 builtin_define ("__csky_trust__"); | |
378 builtin_define ("__CSKY_TRUST__"); | |
379 } | |
380 if (TARGET_DSP) | |
381 { | |
382 builtin_define ("__csky_dsp__"); | |
383 builtin_define ("__CSKY_DSP__"); | |
384 } | |
385 if (TARGET_EDSP) | |
386 { | |
387 builtin_define ("__csky_edsp__"); | |
388 builtin_define ("__CSKY_EDSP__"); | |
389 } | |
390 if (TARGET_VDSP) | |
391 { | |
392 builtin_define ("__csky_vdsp__"); | |
393 builtin_define ("__CSKY_VDSP__"); | |
394 } | |
395 } | |
396 | |
397 | |
398 /****************************************************************** | |
399 * Storage Layout * | |
400 ******************************************************************/ | |
401 | |
402 | |
403 #undef TARGET_PROMOTE_FUNCTION_MODE | |
404 #define TARGET_PROMOTE_FUNCTION_MODE \ | |
405 default_promote_function_mode_always_promote | |
406 | |
407 #undef TARGET_CONSTANT_ALIGNMENT | |
408 #define TARGET_CONSTANT_ALIGNMENT csky_constant_alignment | |
409 | |
410 | |
411 /****************************************************************** | |
412 * Stack Layout and Calling Conventions * | |
413 ******************************************************************/ | |
414 | |
415 #undef TARGET_CAN_ELIMINATE | |
416 #define TARGET_CAN_ELIMINATE csky_can_eliminate | |
417 | |
418 #undef TARGET_FUNCTION_ARG | |
419 #define TARGET_FUNCTION_ARG csky_function_arg | |
420 | |
421 #undef TARGET_FUNCTION_ARG_ADVANCE | |
422 #define TARGET_FUNCTION_ARG_ADVANCE csky_function_arg_advance | |
423 | |
424 #undef TARGET_FUNCTION_VALUE | |
425 #define TARGET_FUNCTION_VALUE csky_function_value | |
426 | |
427 #undef TARGET_LIBCALL_VALUE | |
428 #define TARGET_LIBCALL_VALUE csky_libcall_value | |
429 | |
430 #undef TARGET_FUNCTION_VALUE_REGNO_P | |
431 #define TARGET_FUNCTION_VALUE_REGNO_P csky_function_value_regno_p | |
432 | |
433 #undef TARGET_SPLIT_COMPLEX_ARG | |
434 #define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true | |
435 | |
436 #undef TARGET_PROMOTE_PROTOTYPES | |
437 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true | |
438 | |
439 #undef TARGET_MUST_PASS_IN_STACK | |
440 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size | |
441 | |
442 #undef TARGET_ARG_PARTIAL_BYTES | |
443 #define TARGET_ARG_PARTIAL_BYTES csky_arg_partial_bytes | |
444 | |
445 #undef TARGET_PASS_BY_REFERENCE | |
446 #define TARGET_PASS_BY_REFERENCE hook_pass_by_reference_must_pass_in_stack | |
447 | |
448 #undef TARGET_ASM_OUTPUT_MI_THUNK | |
449 #define TARGET_ASM_OUTPUT_MI_THUNK csky_output_mi_thunk | |
450 | |
451 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK | |
452 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \ | |
453 hook_bool_const_tree_hwi_hwi_const_tree_true | |
454 | |
455 #undef TARGET_ASM_FUNCTION_PROLOGUE | |
456 #define TARGET_ASM_FUNCTION_PROLOGUE csky_output_function_prologue | |
457 | |
458 #undef TARGET_ASM_FUNCTION_EPILOGUE | |
459 #define TARGET_ASM_FUNCTION_EPILOGUE csky_output_function_epilogue | |
460 | |
461 #undef TARGET_WARN_FUNC_RETURN | |
462 #define TARGET_WARN_FUNC_RETURN csky_warn_func_return | |
463 | |
464 #undef TARGET_RETURN_IN_MEMORY | |
465 #define TARGET_RETURN_IN_MEMORY csky_return_in_memory | |
466 | |
467 | |
468 /****************************************************************** | |
469 * Implementing the Varargs Macros * | |
470 ******************************************************************/ | |
471 | |
472 | |
473 #undef TARGET_SETUP_INCOMING_VARARGS | |
474 #define TARGET_SETUP_INCOMING_VARARGS csky_setup_incoming_varargs | |
475 | |
476 | |
477 /****************************************************************** | |
478 * Implicit Calls to Library Routines * | |
479 ******************************************************************/ | |
480 | |
481 | |
482 #undef TARGET_INIT_LIBFUNCS | |
483 #define TARGET_INIT_LIBFUNCS csky_init_libfuncs | |
484 | |
485 | |
486 /****************************************************************** | |
487 * Dividing the Output into Sections (Texts, Data, . . . ) * | |
488 ******************************************************************/ | |
489 | |
490 | |
491 #undef TARGET_HAVE_TLS | |
492 #define TARGET_HAVE_TLS TARGET_CSKY_LINUX | |
493 | |
494 | |
495 /****************************************************************** | |
496 * Defining target-specific uses of __attribute__ * | |
497 ******************************************************************/ | |
498 | |
499 | |
500 #undef TARGET_ATTRIBUTE_TABLE | |
501 #define TARGET_ATTRIBUTE_TABLE csky_attribute_table | |
502 | |
503 #undef TARGET_OPTION_OVERRIDE | |
504 #define TARGET_OPTION_OVERRIDE csky_option_override | |
505 | |
506 | |
507 /* Implement the BRANCH_COST target macro. */ | |
508 | |
509 int | |
510 csky_default_branch_cost (bool speed_p ATTRIBUTE_UNUSED, | |
511 bool predictable_p ATTRIBUTE_UNUSED) | |
512 { | |
513 return csky_branch_cost; | |
514 } | |
515 | |
516 bool | |
517 csky_default_logical_op_non_short_circuit (void) | |
518 { | |
519 return BRANCH_COST (optimize_function_for_speed_p (cfun), false) >= 2; | |
520 } | |
521 | |
522 /****************************************************************** | |
523 * Register Usage * | |
524 ******************************************************************/ | |
525 | |
526 #undef TARGET_HARD_REGNO_NREGS | |
527 #define TARGET_HARD_REGNO_NREGS csky_hard_regno_nregs | |
528 | |
529 #undef TARGET_HARD_REGNO_MODE_OK | |
530 #define TARGET_HARD_REGNO_MODE_OK csky_hard_regno_mode_ok | |
531 | |
532 #undef TARGET_MODES_TIEABLE_P | |
533 #define TARGET_MODES_TIEABLE_P csky_modes_tieable_p | |
534 | |
535 #undef TARGET_CAN_CHANGE_MODE_CLASS | |
536 #define TARGET_CAN_CHANGE_MODE_CLASS csky_can_change_mode_class | |
537 | |
538 #undef TARGET_CONDITIONAL_REGISTER_USAGE | |
539 #define TARGET_CONDITIONAL_REGISTER_USAGE csky_conditional_register_usage | |
540 | |
541 #undef TARGET_CLASS_LIKELY_SPILLED_P | |
542 #define TARGET_CLASS_LIKELY_SPILLED_P csky_class_likely_spilled_p | |
543 | |
544 #undef TARGET_PREFERRED_RELOAD_CLASS | |
545 #define TARGET_PREFERRED_RELOAD_CLASS csky_preferred_reload_class | |
546 | |
547 #undef TARGET_CLASS_MAX_NREGS | |
548 #define TARGET_CLASS_MAX_NREGS csky_class_max_nregs | |
549 | |
550 #undef TARGET_SECONDARY_RELOAD | |
551 #define TARGET_SECONDARY_RELOAD csky_secondary_reload | |
552 | |
553 #undef TARGET_SPILL_CLASS | |
554 #define TARGET_SPILL_CLASS csky_spill_class | |
555 | |
556 | |
557 /****************************************************************** | |
558 * Addressing Modes * | |
559 ******************************************************************/ | |
560 | |
561 | |
562 #undef TARGET_CANNOT_FORCE_CONST_MEM | |
563 #define TARGET_CANNOT_FORCE_CONST_MEM csky_cannot_force_const_mem | |
564 | |
565 #undef TARGET_LEGITIMATE_CONSTANT_P | |
566 #define TARGET_LEGITIMATE_CONSTANT_P csky_legitimate_constant_p | |
567 | |
568 #undef TARGET_LEGITIMIZE_ADDRESS | |
569 #define TARGET_LEGITIMIZE_ADDRESS csky_legitimize_address | |
570 | |
571 #undef TARGET_LEGITIMATE_ADDRESS_P | |
572 #define TARGET_LEGITIMATE_ADDRESS_P csky_legitimate_address_p | |
573 | |
574 | |
575 /****************************************************************** | |
576 * Others * | |
577 ******************************************************************/ | |
578 | |
579 | |
580 #undef TARGET_CANNOT_COPY_INSN_P | |
581 #define TARGET_CANNOT_COPY_INSN_P csky_cannot_copy_insn_p | |
582 | |
583 | |
584 /****************************************************************** | |
585 * Assembler Format * | |
586 ******************************************************************/ | |
587 | |
588 | |
589 #undef TARGET_PRINT_OPERAND | |
590 #define TARGET_PRINT_OPERAND csky_print_operand | |
591 | |
592 #undef TARGET_PRINT_OPERAND_ADDRESS | |
593 #define TARGET_PRINT_OPERAND_ADDRESS csky_print_operand_address | |
594 | |
595 #undef TARGET_ASM_UNALIGNED_HI_OP | |
596 #define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t" | |
597 | |
598 #undef TARGET_ASM_UNALIGNED_SI_OP | |
599 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t" | |
600 | |
601 #undef TARGET_DWARF_REGISTER_SPAN | |
602 #define TARGET_DWARF_REGISTER_SPAN csky_dwarf_register_span | |
603 | |
604 | |
605 /****************************************************************** | |
606 * Miscellaneous Parameters * | |
607 ******************************************************************/ | |
608 | |
609 | |
610 #undef TARGET_MACHINE_DEPENDENT_REORG | |
611 #define TARGET_MACHINE_DEPENDENT_REORG csky_reorg | |
612 | |
613 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS | |
614 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS csky_allocate_stack_slots_for_args | |
615 | |
616 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE | |
617 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed | |
618 | |
619 | |
620 /****************************************************************** | |
621 * Trampolines for Nested Functions * | |
622 ******************************************************************/ | |
623 | |
624 | |
625 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | |
626 #define TARGET_ASM_TRAMPOLINE_TEMPLATE csky_asm_trampoline_template | |
627 #undef TARGET_TRAMPOLINE_INIT | |
628 #define TARGET_TRAMPOLINE_INIT csky_trampoline_init | |
629 | |
630 /* The low bit is ignored by jsr and jmp instructions so is safe to use. */ | |
631 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS | |
632 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1 | |
633 | |
634 /****************************************************************** | |
635 * Describing Relative Costs of Operations * | |
636 ******************************************************************/ | |
637 | |
638 | |
639 #undef TARGET_REGISTER_MOVE_COST | |
640 #define TARGET_REGISTER_MOVE_COST csky_register_move_cost | |
641 | |
642 #undef TARGET_MEMORY_MOVE_COST | |
643 #define TARGET_MEMORY_MOVE_COST csky_memory_move_cost | |
644 | |
645 #undef TARGET_RTX_COSTS | |
646 #define TARGET_RTX_COSTS csky_rtx_costs | |
647 | |
648 #undef TARGET_ADDRESS_COST | |
649 #define TARGET_ADDRESS_COST csky_address_cost | |
650 | |
651 | |
652 /****************************************************************** | |
653 * Anchor address * | |
654 ******************************************************************/ | |
655 | |
656 | |
657 /* FIXME: the max offset is related to mode size, the following is | |
658 defined according to SImode. How to deal with HImode and | |
659 QImode, and should the min offset be defined? */ | |
660 #undef TARGET_MAX_ANCHOR_OFFSET | |
661 #define TARGET_MAX_ANCHOR_OFFSET \ | |
662 ((TARGET_MINI_REGISTERS && optimize_size) ? 127 : 4095) | |
663 | |
664 | |
665 /****************************************************************** | |
666 * Condition Code Status * | |
667 ******************************************************************/ | |
668 | |
669 | |
670 #undef TARGET_FIXED_CONDITION_CODE_REGS | |
671 #define TARGET_FIXED_CONDITION_CODE_REGS csky_fixed_condition_code_regs | |
672 | |
673 | |
674 /****************************************************************** | |
675 * Adjusting the Instruction Scheduler * | |
676 ******************************************************************/ | |
677 | |
678 | |
679 #undef TARGET_SCHED_ISSUE_RATE | |
680 #define TARGET_SCHED_ISSUE_RATE csky_sched_issue_rate | |
681 | |
682 #undef TARGET_SCHED_ADJUST_COST | |
683 #define TARGET_SCHED_ADJUST_COST csky_sched_adjust_cost | |
684 | |
685 | |
686 /* The declaration of functions. */ | |
687 static void push_csky_minipool_fix (rtx_insn *, HOST_WIDE_INT, rtx *, | |
688 machine_mode, rtx); | |
689 static void csky_print_operand (FILE *stream, rtx x, int code); | |
690 | |
691 | |
692 /* Define a table to map ISR attribute arguments onto function type | |
693 modifiers. */ | |
694 | |
695 typedef struct | |
696 { | |
697 const char *const arg; | |
698 const unsigned long return_value; | |
699 } isr_attribute_entry; | |
700 | |
701 static const isr_attribute_entry isr_attribute_map[] = | |
702 { | |
703 {"irq", CSKY_FT_ISR }, | |
704 {"IRQ", CSKY_FT_ISR }, | |
705 {"fiq", CSKY_FT_FIQ }, | |
706 {"FIQ", CSKY_FT_FIQ }, | |
707 {NULL, CSKY_FT_NORMAL } | |
708 }; | |
709 | |
710 | |
711 /* Return the function type of the current function, if it has not been | |
712 determined, return CSKY_FT_UNKNOWN. */ | |
713 | |
714 static unsigned long | |
715 get_csky_isr_type (tree argument) | |
716 { | |
717 const isr_attribute_entry *ptr; | |
718 const char *arg; | |
719 | |
720 /* if argument is NULL, set default value ISR. */ | |
721 if (argument == NULL_TREE) | |
722 return CSKY_FT_ISR; | |
723 | |
724 if (TREE_VALUE (argument) == NULL_TREE | |
725 || TREE_CODE (TREE_VALUE (argument)) != STRING_CST) | |
726 return CSKY_FT_UNKNOWN; | |
727 | |
728 arg = TREE_STRING_POINTER (TREE_VALUE (argument)); | |
729 | |
730 for (ptr = isr_attribute_map; ptr->arg != NULL; ptr++) | |
731 if (strcmp (arg, ptr->arg) == 0) | |
732 return ptr->return_value; | |
733 | |
734 return CSKY_FT_UNKNOWN; | |
735 } | |
736 | |
737 /* Classify cfun as a normal function or some sort of interrupt | |
738 handler, and set the corresponding bits in cfun->machine->func_type. */ | |
739 | |
740 static unsigned long | |
741 get_csky_current_func_type (void) | |
742 { | |
743 if (CSKY_FUNCTION_TYPE (cfun->machine->func_type) == CSKY_FT_UNKNOWN) | |
744 { | |
745 unsigned long type = CSKY_FT_UNKNOWN; | |
746 tree a; | |
747 tree attr; | |
748 | |
749 gcc_assert (TREE_CODE (current_function_decl) == FUNCTION_DECL); | |
750 | |
751 attr = DECL_ATTRIBUTES (current_function_decl); | |
752 a = lookup_attribute ("naked", attr); | |
753 if (a != NULL_TREE) | |
754 type |= CSKY_FT_NAKED; | |
755 a = lookup_attribute ("isr", attr); | |
756 if (a == NULL_TREE) | |
757 a = lookup_attribute ("interrupt", attr); | |
758 if (a == NULL_TREE) | |
759 type |= CSKY_FT_NORMAL; | |
760 else | |
761 type |= get_csky_isr_type (TREE_VALUE (a)); | |
762 | |
763 cfun->machine->func_type = type; | |
764 } | |
765 | |
766 return cfun->machine->func_type; | |
767 } | |
768 | |
769 /* These typedefs are located at the start of this file, so that | |
770 they can be used in the prototypes there. This comment is to | |
771 remind readers of that fact so that the following structures | |
772 can be understood more easily. | |
773 | |
774 typedef struct minipool_node Mnode; | |
775 typedef struct minipool_fixup Mfix; */ | |
776 | |
777 struct minipool_node | |
778 { | |
779 /* Doubly linked chain of entries. */ | |
780 Mnode *next; | |
781 Mnode *prev; | |
782 /* The maximum offset into the code that this entry can be placed. While | |
783 pushing fixes for forward references, all entries are sorted in order | |
784 of increasing max_address. */ | |
785 HOST_WIDE_INT max_address; | |
786 /* Similarly for an entry inserted for a backwards ref. */ | |
787 HOST_WIDE_INT min_address; | |
788 /* The number of fixes referencing this entry. This can become zero | |
789 if we "unpush" an entry. In this case we ignore the entry when we | |
790 come to emit the code. */ | |
791 int refcount; | |
792 /* The offset from the start of the minipool. */ | |
793 HOST_WIDE_INT offset; | |
794 /* The value in table. */ | |
795 rtx value; | |
796 /* The mode of value. */ | |
797 machine_mode mode; | |
798 /* The size of the value. */ | |
799 int fix_size; | |
800 }; | |
801 | |
802 struct minipool_fixup | |
803 { | |
804 Mfix *next; | |
805 rtx_insn *insn; | |
806 HOST_WIDE_INT address; | |
807 rtx *loc; | |
808 machine_mode mode; | |
809 int fix_size; | |
810 rtx value; | |
811 Mnode *minipool; | |
812 HOST_WIDE_INT forwards; | |
813 HOST_WIDE_INT backwards; | |
814 }; | |
815 | |
816 static Mnode *minipool_vector_head; | |
817 static Mnode *minipool_vector_tail; | |
818 static rtx minipool_vector_label; | |
819 static HOST_WIDE_INT constpool_label_no = 0; | |
820 | |
821 /* Obstack for minipool constant handling. */ | |
822 static struct obstack minipool_obstack; | |
823 static char *minipool_startobj; | |
824 /* The linked list of all minipool fixes required for this function. */ | |
825 Mfix *minipool_fix_head; | |
826 Mfix *minipool_fix_tail; | |
827 /* The fix entry for the current minipool, once it has been placed. */ | |
828 Mfix *minipool_barrier; | |
829 | |
830 /* Allow GC scanning of the minipool obstack. */ | |
831 static void | |
832 csky_add_gc_roots (void) | |
833 { | |
834 gcc_obstack_init (&minipool_obstack); | |
835 minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0); | |
836 } | |
837 | |
838 /* Implement TARGET_CONSTANT_ALIGNMENT. | |
839 Make strings word-aligned so strcpy from constants will be faster. */ | |
840 static HOST_WIDE_INT | |
841 csky_constant_alignment (const_tree exp, HOST_WIDE_INT align) | |
842 { | |
843 if (TREE_CODE (exp) == STRING_CST | |
844 && !optimize_size | |
845 && align < BITS_PER_WORD) | |
846 return BITS_PER_WORD; | |
847 return align; | |
848 } | |
849 | |
850 /* Record that there is a natural barrier in the insn stream at | |
851 ADDRESS. */ | |
852 | |
853 static void | |
854 push_csky_minipool_barrier (rtx_insn *insn, HOST_WIDE_INT address) | |
855 { | |
856 Mfix *fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*fix)); | |
857 | |
858 fix->insn = insn; | |
859 fix->address = address; | |
860 | |
861 fix->next = NULL; | |
862 if (minipool_fix_head != NULL) | |
863 minipool_fix_tail->next = fix; | |
864 else | |
865 minipool_fix_head = fix; | |
866 | |
867 minipool_fix_tail = fix; | |
868 } | |
869 | |
870 /* Compute the size of a vector jump table. */ | |
871 | |
872 static HOST_WIDE_INT | |
873 get_csky_jump_table_size (rtx insn) | |
874 { | |
875 /* ADDR_VECs only take room if read-only data does into the text | |
876 section. */ | |
877 if (JUMP_TABLES_IN_TEXT_SECTION || readonly_data_section == text_section) | |
878 { | |
879 rtx body = PATTERN (insn); | |
880 int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0; | |
881 HOST_WIDE_INT size; | |
882 HOST_WIDE_INT modesize; | |
883 | |
884 modesize = GET_MODE_SIZE (GET_MODE (body)); | |
885 size = modesize * XVECLEN (body, elt); | |
886 switch (modesize) | |
887 { | |
888 case 1: | |
889 /* Round up size of TBB table to a halfword boundary. */ | |
890 size = (size + 1) & ~(HOST_WIDE_INT)1; | |
891 break; | |
892 case 2: | |
893 /* No padding necessary for TBH. */ | |
894 break; | |
895 case 4: | |
896 break; | |
897 default: | |
898 gcc_unreachable (); | |
899 } | |
900 return size; | |
901 } | |
902 | |
903 return 0; | |
904 } | |
905 | |
906 | |
907 /* Scan INSN and note any of its operands that need fixing. | |
908 If DO_PUSHES is false we do not actually push any of the fixups | |
909 needed. The function returns TRUE if any fixups were needed/pushed. */ | |
910 | |
911 static bool | |
912 note_csky_invalid_constants (rtx_insn *insn, HOST_WIDE_INT address, | |
913 int do_pushes) | |
914 { | |
915 bool result = false; | |
916 int opno; | |
917 | |
918 extract_constrain_insn (insn); | |
919 | |
920 if (recog_data.n_alternatives == 0) | |
921 return false; | |
922 | |
923 /* Fill in recog_op_alt with information about the constraints of | |
924 this insn. */ | |
925 preprocess_constraints (insn); | |
926 | |
927 const operand_alternative *op_alt = which_op_alt (); | |
928 for (opno = 0; opno < recog_data.n_operands; opno++) | |
929 { | |
930 /* Things we need to fix can only occur in inputs. */ | |
931 if (recog_data.operand_type[opno] != OP_IN) | |
932 continue; | |
933 | |
934 /* If this alternative is a memory reference, then any mention | |
935 of constants in this alternative is really to fool reload | |
936 into allowing us to accept one there. We need to fix them up | |
937 now so that we output the right code. */ | |
938 if (op_alt[opno].memory_ok) | |
939 { | |
940 rtx op = recog_data.operand[opno]; | |
941 | |
942 if (CONSTANT_P (op)) | |
943 { | |
944 if (do_pushes) | |
945 push_csky_minipool_fix (insn, address, | |
946 recog_data.operand_loc[opno], | |
947 recog_data.operand_mode[opno], op); | |
948 result = true; | |
949 } | |
950 } | |
951 } | |
952 | |
953 return result; | |
954 } | |
955 | |
956 | |
957 /* Add a constant to the minipool for a forward reference. Returns the | |
958 node added or NULL if the constant will not fit in this pool. */ | |
959 | |
960 static Mnode * | |
961 add_csky_minipool_forward_ref (Mfix *fix) | |
962 { | |
963 /* If set, max_mp is the first pool_entry that has a lower | |
964 constraint than the one we are trying to add. */ | |
965 Mnode *max_mp = NULL; | |
966 HOST_WIDE_INT max_address = fix->address + fix->forwards; | |
967 Mnode *mp; | |
968 | |
969 /* If the minipool starts before the end of FIX->INSN then this FIX | |
970 can not be placed into the current pool. Furthermore, adding the | |
971 new constant pool entry may cause the pool to start FIX_SIZE bytes | |
972 earlier. */ | |
973 if (minipool_vector_head | |
974 && (fix->address + get_attr_length (fix->insn) | |
975 >= minipool_vector_head->max_address - fix->fix_size)) | |
976 return NULL; | |
977 | |
978 /* Scan the pool to see if a constant with the same value has | |
979 already been added. While we are doing this, also note the | |
980 location where we must insert the constant if it doesn't already | |
981 exist. */ | |
982 for (mp = minipool_vector_head; mp != NULL; mp = mp->next) | |
983 { | |
984 if (GET_CODE (fix->value) == GET_CODE (mp->value) | |
985 && fix->mode == mp->mode | |
986 && (GET_CODE (fix->value) != CODE_LABEL | |
987 || (CODE_LABEL_NUMBER (fix->value) | |
988 == CODE_LABEL_NUMBER (mp->value))) | |
989 && rtx_equal_p (fix->value, mp->value)) | |
990 { | |
991 /* More than one fix references this entry. */ | |
992 mp->refcount++; | |
993 return mp; | |
994 } | |
995 | |
996 /* Note the insertion point if necessary. */ | |
997 if (max_mp == NULL && mp->max_address > max_address) | |
998 max_mp = mp; | |
999 } | |
1000 | |
1001 /* The value is not currently in the minipool, so we need to create | |
1002 a new entry for it. If MAX_MP is NULL, the entry will be put on | |
1003 the end of the list since the placement is less constrained than | |
1004 any existing entry. Otherwise, we insert the new fix before | |
1005 MAX_MP and, if necessary, adjust the constraints on the other | |
1006 entries. */ | |
1007 mp = XNEW (Mnode); | |
1008 mp->fix_size = fix->fix_size; | |
1009 mp->mode = fix->mode; | |
1010 mp->value = fix->value; | |
1011 mp->refcount = 1; | |
1012 /* Not yet required for a backwards ref. */ | |
1013 mp->min_address = -65536; | |
1014 | |
1015 if (max_mp == NULL) | |
1016 { | |
1017 mp->max_address = max_address; | |
1018 mp->next = NULL; | |
1019 mp->prev = minipool_vector_tail; | |
1020 | |
1021 if (mp->prev == NULL) | |
1022 { | |
1023 minipool_vector_head = mp; | |
1024 minipool_vector_label | |
1025 = gen_csky_constpool_label (gen_rtx_CONST_INT (VOIDmode, | |
1026 constpool_label_no++)); | |
1027 } | |
1028 else | |
1029 mp->prev->next = mp; | |
1030 | |
1031 minipool_vector_tail = mp; | |
1032 } | |
1033 else | |
1034 { | |
1035 if (max_address > max_mp->max_address - mp->fix_size) | |
1036 mp->max_address = max_mp->max_address - mp->fix_size; | |
1037 else | |
1038 mp->max_address = max_address; | |
1039 | |
1040 mp->next = max_mp; | |
1041 mp->prev = max_mp->prev; | |
1042 max_mp->prev = mp; | |
1043 if (mp->prev != NULL) | |
1044 mp->prev->next = mp; | |
1045 else | |
1046 minipool_vector_head = mp; | |
1047 } | |
1048 | |
1049 /* Save the new entry. */ | |
1050 max_mp = mp; | |
1051 | |
1052 /* Scan over the preceding entries and adjust their addresses as | |
1053 required. */ | |
1054 while (mp->prev != NULL | |
1055 && mp->prev->max_address > mp->max_address - mp->prev->fix_size) | |
1056 { | |
1057 mp->prev->max_address = mp->max_address - mp->prev->fix_size; | |
1058 mp = mp->prev; | |
1059 } | |
1060 | |
1061 return max_mp; | |
1062 } | |
1063 | |
1064 | |
1065 /* Return the cost of forcibly inserting a barrier after INSN. */ | |
1066 | |
1067 static int | |
1068 get_csky_barrier_cost (rtx_insn *insn) | |
1069 { | |
1070 /* Basing the location of the pool on the loop depth is preferable, | |
1071 but at the moment, the basic block information seems to be | |
1072 corrupt by this stage of the compilation. */ | |
1073 int base_cost = 50; | |
1074 rtx next = next_nonnote_insn (insn); | |
1075 | |
1076 if (next != NULL && GET_CODE (next) == CODE_LABEL) | |
1077 base_cost -= 20; | |
1078 | |
1079 switch (GET_CODE (insn)) | |
1080 { | |
1081 case CODE_LABEL: | |
1082 /* It will always be better to place the table before the label, rather | |
1083 than after it. */ | |
1084 return 50; | |
1085 | |
1086 case INSN: | |
1087 case CALL_INSN: | |
1088 return base_cost; | |
1089 | |
1090 case JUMP_INSN: | |
1091 return base_cost - 10; | |
1092 | |
1093 default: | |
1094 return base_cost + 10; | |
1095 } | |
1096 } | |
1097 | |
1098 | |
1099 /* Find the best place in the insn stream in the range | |
1100 (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier. | |
1101 Create the barrier by inserting a jump and add a new fix entry for | |
1102 it. */ | |
1103 static Mfix * | |
1104 create_csky_fix_barrier (Mfix *fix, Mfix *fix_next, | |
1105 HOST_WIDE_INT max_address) | |
1106 { | |
1107 rtx_barrier *barrier; | |
1108 rtx_insn *from = (fix ? fix->insn : get_insns ()); | |
1109 /* The instruction after which we will insert the jump. */ | |
1110 rtx_insn *selected = NULL; | |
1111 int selected_cost; | |
1112 /* The address at which the jump instruction will be placed. */ | |
1113 HOST_WIDE_INT selected_address = 0; | |
1114 Mfix *new_fix; | |
1115 HOST_WIDE_INT count = (fix ? fix->address : 0); | |
1116 HOST_WIDE_INT max_count = max_address; | |
1117 rtx_code_label *label = gen_label_rtx (); | |
1118 | |
1119 selected_cost = get_csky_barrier_cost (from); | |
1120 | |
1121 while (from && count < max_count) | |
1122 { | |
1123 int new_cost; | |
1124 rtx_jump_table_data *table; | |
1125 | |
1126 /* Count the length of this insn. */ | |
1127 count += get_attr_length (from); | |
1128 | |
1129 /* If there is a jump table, add its length. */ | |
1130 if (tablejump_p (from, NULL, &table)) | |
1131 { | |
1132 count += get_csky_jump_table_size (table); | |
1133 | |
1134 /* Jump tables aren't in a basic block, so base the cost on | |
1135 the dispatch insn. If we select this location, we will | |
1136 still put the pool after the table. */ | |
1137 new_cost = get_csky_barrier_cost (from); | |
1138 | |
1139 if (count < max_count | |
1140 && (!selected || new_cost <= selected_cost)) | |
1141 { | |
1142 selected = table; | |
1143 selected_cost = new_cost; | |
1144 selected_address = count; | |
1145 } | |
1146 | |
1147 /* Continue after the dispatch table. */ | |
1148 from = NEXT_INSN (table); | |
1149 continue; | |
1150 } | |
1151 | |
1152 new_cost = get_csky_barrier_cost (from); | |
1153 | |
1154 if (count < max_count | |
1155 && (!selected || new_cost <= selected_cost)) | |
1156 { | |
1157 selected = from; | |
1158 selected_cost = new_cost; | |
1159 selected_address = count; | |
1160 } | |
1161 | |
1162 from = NEXT_INSN (from); | |
1163 } | |
1164 | |
1165 /* Make sure that we found a place to insert the jump. */ | |
1166 gcc_assert (selected); | |
1167 | |
1168 /* Create a new JUMP_INSN that branches around a barrier. */ | |
1169 from = emit_jump_insn_after (gen_jump (label), selected); | |
1170 JUMP_LABEL (from) = label; | |
1171 barrier = emit_barrier_after (from); | |
1172 emit_label_after (label, barrier); | |
1173 | |
1174 /* Create a minipool barrier entry for the new barrier. */ | |
1175 new_fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (* new_fix)); | |
1176 new_fix->insn = barrier; | |
1177 new_fix->address = selected_address; | |
1178 if (fix) | |
1179 { | |
1180 new_fix->next = fix->next; | |
1181 fix->next = new_fix; | |
1182 } | |
1183 else | |
1184 new_fix->next = fix_next; | |
1185 | |
1186 return new_fix; | |
1187 } | |
1188 | |
1189 | |
1190 /* Print a symbolic form of the constant X to the dump file F. | |
1191 This is used for dump output for -mconstpool in the target-dependent | |
1192 reorg pass. */ | |
1193 | |
1194 static void | |
1195 print_csky_value (FILE *f, rtx x) | |
1196 { | |
1197 switch (GET_CODE (x)) | |
1198 { | |
1199 case CONST_INT: | |
1200 fprintf (f, HOST_WIDE_INT_PRINT_HEX, INTVAL (x)); | |
1201 return; | |
1202 | |
1203 case CONST_DOUBLE: | |
1204 fprintf (f, "<0x%lx,0x%lx>", (long)XWINT (x, 2), (long)XWINT (x, 3)); | |
1205 return; | |
1206 | |
1207 case CONST_VECTOR: | |
1208 { | |
1209 int i; | |
1210 | |
1211 fprintf (f, "<"); | |
1212 for (i = 0; i < CONST_VECTOR_NUNITS (x); i++) | |
1213 { | |
1214 fprintf (f, HOST_WIDE_INT_PRINT_HEX, | |
1215 INTVAL (CONST_VECTOR_ELT (x, i))); | |
1216 if (i < (CONST_VECTOR_NUNITS (x) - 1)) | |
1217 fputc (',', f); | |
1218 } | |
1219 fprintf (f, ">"); | |
1220 } | |
1221 return; | |
1222 | |
1223 case CONST_STRING: | |
1224 fprintf (f, "\"%s\"", XSTR (x, 0)); | |
1225 return; | |
1226 | |
1227 case SYMBOL_REF: | |
1228 fprintf (f, "`%s'", XSTR (x, 0)); | |
1229 return; | |
1230 | |
1231 case LABEL_REF: | |
1232 fprintf (f, "L%d", INSN_UID (XEXP (x, 0))); | |
1233 return; | |
1234 | |
1235 case CONST: | |
1236 print_csky_value (f, XEXP (x, 0)); | |
1237 return; | |
1238 | |
1239 case PLUS: | |
1240 print_csky_value (f, XEXP (x, 0)); | |
1241 fprintf (f, "+"); | |
1242 print_csky_value (f, XEXP (x, 1)); | |
1243 return; | |
1244 | |
1245 case PC: | |
1246 fprintf (f, "pc"); | |
1247 return; | |
1248 | |
1249 default: | |
1250 fprintf (f, "????"); | |
1251 return; | |
1252 } | |
1253 } | |
1254 | |
1255 | |
1256 /* Record INSN, which will need fixing up to load a value from the | |
1257 minipool. ADDRESS is the offset of the insn since the start of the | |
1258 function; LOC is a pointer to the part of the insn which requires | |
1259 fixing; VALUE is the constant that must be loaded, which is of type | |
1260 MODE. */ | |
1261 | |
1262 static void | |
1263 push_csky_minipool_fix (rtx_insn *insn, HOST_WIDE_INT address, rtx *loc, | |
1264 machine_mode mode, rtx value) | |
1265 { | |
1266 #define CSKY_ELRW16_RANGE 1400 | |
1267 #define CSKY_LRW16_RANGE 700 | |
1268 #define CSKY_CONSTANT_POOL_RANGE (TARGET_ELRW ? CSKY_ELRW16_RANGE \ | |
1269 : CSKY_LRW16_RANGE) | |
1270 | |
1271 /* Fixes less than a word need padding out to a word boundary. */ | |
1272 #define CSKY_MINIPOOL_FIX_SIZE(mode) \ | |
1273 (GET_MODE_SIZE ((mode)) >= 4 ? GET_MODE_SIZE ((mode)) : 4) | |
1274 | |
1275 Mfix *fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*fix)); | |
1276 | |
1277 fix->insn = insn; | |
1278 fix->address = address; | |
1279 fix->loc = loc; | |
1280 fix->mode = mode; | |
1281 fix->fix_size = CSKY_MINIPOOL_FIX_SIZE (mode); | |
1282 fix->value = value; | |
1283 fix->forwards = CSKY_CONSTANT_POOL_RANGE; | |
1284 fix->backwards = 0; | |
1285 fix->minipool = NULL; | |
1286 | |
1287 /* If an insn doesn't have a range defined for it, then it isn't | |
1288 expecting to be reworked by this code. Better to stop now than | |
1289 to generate duff assembly code. */ | |
1290 gcc_assert (fix->forwards || fix->backwards); | |
1291 | |
1292 if (dump_file) | |
1293 { | |
1294 fprintf (dump_file, | |
1295 ";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ", | |
1296 GET_MODE_NAME (mode), | |
1297 INSN_UID (insn), (unsigned long) address, | |
1298 -1 * (long)fix->backwards, (long)fix->forwards); | |
1299 print_csky_value (dump_file, fix->value); | |
1300 fprintf (dump_file, "\n"); | |
1301 } | |
1302 | |
1303 /* Add it to the chain of fixes. */ | |
1304 fix->next = NULL; | |
1305 | |
1306 if (minipool_fix_head != NULL) | |
1307 minipool_fix_tail->next = fix; | |
1308 else | |
1309 minipool_fix_head = fix; | |
1310 | |
1311 minipool_fix_tail = fix; | |
1312 } | |
1313 | |
1314 | |
1315 /* Fill in the offsets for minipool entries. */ | |
1316 | |
1317 static void | |
1318 assign_csky_minipool_offsets (Mfix *barrier) | |
1319 { | |
1320 HOST_WIDE_INT offset = 0; | |
1321 Mnode *mp; | |
1322 | |
1323 minipool_barrier = barrier; | |
1324 | |
1325 for (mp = minipool_vector_head; mp != NULL; mp = mp->next) | |
1326 { | |
1327 mp->offset = offset; | |
1328 | |
1329 if (mp->refcount > 0) | |
1330 offset += mp->fix_size; | |
1331 } | |
1332 } | |
1333 | |
1334 | |
1335 /* Output the literal table. */ | |
1336 | |
1337 static HOST_WIDE_INT | |
1338 dump_csky_minipool (rtx_insn *scan) | |
1339 { | |
1340 Mnode *mp; | |
1341 Mnode *nmp; | |
1342 HOST_WIDE_INT pool_length = 0; | |
1343 | |
1344 if (dump_file) | |
1345 fprintf (dump_file, | |
1346 ";; Emitting minipool after insn %u;\ | |
1347 address %ld; align %d (bytes)\n", | |
1348 INSN_UID (scan), (unsigned long) minipool_barrier->address, 4); | |
1349 | |
1350 scan = emit_insn_after (gen_align_4 (), scan); | |
1351 scan = emit_insn_after (minipool_vector_label, scan); | |
1352 | |
1353 for (mp = minipool_vector_head; mp != NULL; mp = nmp) | |
1354 { | |
1355 if (mp->refcount > 0) | |
1356 { | |
1357 if (dump_file) | |
1358 { | |
1359 fprintf (dump_file, ";; Offset %u, min %ld, max %ld ", | |
1360 (unsigned) mp->offset, (unsigned long) mp->min_address, | |
1361 (unsigned long) mp->max_address); | |
1362 print_csky_value (dump_file, mp->value); | |
1363 fputc ('\n', dump_file); | |
1364 } | |
1365 | |
1366 switch (mp->fix_size) | |
1367 { | |
1368 case 4: | |
1369 scan = emit_insn_after (gen_consttable_4 (mp->value), scan); | |
1370 pool_length += 4; | |
1371 break; | |
1372 case 8: | |
1373 scan = emit_insn_after (gen_consttable_8 (mp->value), scan); | |
1374 pool_length += 8; | |
1375 break; | |
1376 default: | |
1377 gcc_unreachable (); | |
1378 } | |
1379 } | |
1380 | |
1381 nmp = mp->next; | |
1382 free (mp); | |
1383 } | |
1384 | |
1385 minipool_vector_head = minipool_vector_tail = NULL; | |
1386 scan = emit_barrier_after (scan); | |
1387 | |
1388 return pool_length; | |
1389 } | |
1390 | |
1391 /* Return true if INSN is a minipool load or instruction that will be | |
1392 converted to one. It is assumed that INSN has type attribute "load". */ | |
1393 | |
1394 bool | |
1395 csky_minipool_load_p (rtx_insn *insn) | |
1396 { | |
1397 rtx op1, addr; | |
1398 | |
1399 extract_insn_cached (insn); | |
1400 | |
1401 op1 = recog_data.operand[1]; | |
1402 | |
1403 /* This is a constant that has not yet been turned into | |
1404 a minipool load. */ | |
1405 if (CONSTANT_P (op1)) | |
1406 return true; | |
1407 | |
1408 /* Constant pool loads are label_refs. */ | |
1409 if (GET_CODE (op1) == ZERO_EXTEND || GET_CODE (op1) == SIGN_EXTEND) | |
1410 op1 = XEXP (op1, 0); | |
1411 if (GET_CODE (op1) != MEM) | |
1412 return false; | |
1413 addr = XEXP (op1, 0); | |
1414 if (GET_CODE (addr) == PLUS && CONST_INT_P (XEXP (addr, 1))) | |
1415 addr = XEXP (addr, 0); | |
1416 return GET_CODE (addr) == LABEL_REF; | |
1417 } | |
1418 | |
1419 | |
1420 /* Compute the attribute "length" of push or pop insn, according to | |
1421 the registers it uses. */ | |
1422 | |
1423 int | |
1424 csky_compute_pushpop_length (rtx *operands) | |
1425 { | |
1426 rtx parallel_op = operands[2]; | |
1427 /* Initialize to elements number of PARALLEL. */ | |
1428 unsigned indx = XVECLEN (parallel_op, 0) - 1; | |
1429 unsigned first_indx = 0; | |
1430 unsigned regno = REGNO (operands[1]); | |
1431 | |
1432 if (regno > CSKY_LR_REGNUM) | |
1433 return 4; | |
1434 | |
1435 /* Check each register in the list. */ | |
1436 for (; indx > first_indx; indx--) | |
1437 { | |
1438 regno = REGNO (XEXP (XVECEXP (parallel_op, 0, indx), 0)); | |
1439 /* If a register number higher than 15 is included, a 32-bit insn | |
1440 is used. */ | |
1441 if (regno > CSKY_LR_REGNUM) | |
1442 return 4; | |
1443 } | |
1444 | |
1445 return 2; | |
1446 } | |
1447 | |
1448 /* Emit constant pools for -mconstpool. */ | |
1449 static void | |
1450 csky_emit_constant_pools (void) | |
1451 { | |
1452 rtx_insn *insn; | |
1453 HOST_WIDE_INT address = 0; | |
1454 Mfix *fix; | |
1455 | |
1456 minipool_fix_head = minipool_fix_tail = NULL; | |
1457 | |
1458 /* The first insn must always be a note, or the code below won't | |
1459 scan it properly. */ | |
1460 insn = get_insns (); | |
1461 gcc_assert (NOTE_P (insn)); | |
1462 | |
1463 /* Scan the insns and record the operands that need fixing. */ | |
1464 for (insn = next_nonnote_insn (insn); insn; | |
1465 insn = next_nonnote_insn (insn)) | |
1466 { | |
1467 if (BARRIER_P (insn)) | |
1468 push_csky_minipool_barrier (insn, address); | |
1469 else if (INSN_P (insn)) | |
1470 { | |
1471 rtx_jump_table_data *table; | |
1472 | |
1473 note_csky_invalid_constants (insn, address, true); | |
1474 address += get_attr_length (insn); | |
1475 | |
1476 /* If the insn is a vector jump, add the size of the table | |
1477 and skip the table. */ | |
1478 if (tablejump_p (insn, NULL, &table)) | |
1479 { | |
1480 address += get_csky_jump_table_size (table); | |
1481 insn = table; | |
1482 } | |
1483 } | |
1484 } | |
1485 | |
1486 fix = minipool_fix_head; | |
1487 | |
1488 /* Now scan the fixups and perform the required changes. */ | |
1489 while (fix) | |
1490 { | |
1491 Mfix *ftmp; | |
1492 Mfix *last_added_fix; | |
1493 Mfix *last_barrier = NULL; | |
1494 Mfix *this_fix; | |
1495 Mnode *mp; | |
1496 bool has_pending_const = false; | |
1497 | |
1498 /* Check if there is any pending constant not processed. */ | |
1499 for (mp = minipool_vector_head; mp; mp = mp->next) | |
1500 if (mp->refcount > 0) | |
1501 { | |
1502 has_pending_const = true; | |
1503 break; | |
1504 } | |
1505 | |
1506 /* If no pending constant, skip over barrier insns. */ | |
1507 if (has_pending_const == false) | |
1508 { | |
1509 while (fix && BARRIER_P (fix->insn)) | |
1510 fix = fix->next; | |
1511 if (fix == NULL) | |
1512 break; | |
1513 } | |
1514 | |
1515 last_added_fix = NULL; | |
1516 | |
1517 for (ftmp = fix; ftmp; ftmp = ftmp->next) | |
1518 { | |
1519 if (BARRIER_P (ftmp->insn)) | |
1520 { | |
1521 if (minipool_vector_head | |
1522 && ftmp->address >= minipool_vector_head->max_address) | |
1523 break; | |
1524 | |
1525 last_barrier = ftmp; | |
1526 } | |
1527 else | |
1528 { | |
1529 ftmp->minipool = add_csky_minipool_forward_ref (ftmp); | |
1530 if (ftmp->minipool == NULL) | |
1531 break; | |
1532 } | |
1533 last_added_fix = ftmp; /* Keep track of the last fix added. */ | |
1534 } | |
1535 | |
1536 /* If the last added fix is a barrier, dump minipool after it. */ | |
1537 if (last_added_fix && BARRIER_P (last_added_fix->insn)) | |
1538 ftmp = last_barrier; | |
1539 else | |
1540 { | |
1541 /* ftmp is first fix that we can't fit into this pool. | |
1542 Insert a new barrier in the code somewhere between the previous | |
1543 fix and this one, and arrange to jump around it. */ | |
1544 HOST_WIDE_INT max_address; | |
1545 | |
1546 /* The last item on the list of fixes must be a barrier, so | |
1547 we can never run off the end of the list of fixes without | |
1548 last_barrier being set. */ | |
1549 gcc_assert (ftmp); | |
1550 | |
1551 /* Check that there isn't another fix that is in range that | |
1552 we couldn't fit into this pool because the pool was | |
1553 already too large: we need to put the pool before such an | |
1554 instruction. The pool itself may come just after the | |
1555 fix because create_csky_fix_barrier also allows space for a | |
1556 jump instruction. */ | |
1557 max_address = minipool_vector_head->max_address; | |
1558 if (ftmp->address < max_address) | |
1559 max_address = ftmp->address + 1; | |
1560 last_barrier = create_csky_fix_barrier (last_added_fix, ftmp, | |
1561 max_address); | |
1562 } | |
1563 | |
1564 assign_csky_minipool_offsets (last_barrier); | |
1565 | |
1566 /* Scan over the fixes we have identified for this pool, fixing them | |
1567 up and adding the constants to the pool itself. */ | |
1568 for (this_fix = fix; this_fix && ftmp != this_fix; | |
1569 this_fix = this_fix->next) | |
1570 { | |
1571 if (GET_CODE (this_fix->insn) != BARRIER) | |
1572 { | |
1573 rtx addr | |
1574 = plus_constant (Pmode, | |
1575 gen_rtx_LABEL_REF (VOIDmode, | |
1576 minipool_vector_label), | |
1577 this_fix->minipool->offset); | |
1578 rtx insn_body = PATTERN (this_fix->insn); | |
1579 rtx src = XEXP (insn_body, 1); | |
1580 *this_fix->loc = gen_rtx_MEM (this_fix->mode, addr); | |
1581 if (GET_CODE (this_fix->value) == SYMBOL_REF) | |
1582 emit_insn_after (gen_rtx_UNSPEC_VOLATILE (VOIDmode, | |
1583 gen_rtvec (1, src), | |
1584 VUNSPEC_SYMBOL_REF), | |
1585 this_fix->insn); | |
1586 } | |
1587 } | |
1588 dump_csky_minipool (last_barrier->insn); | |
1589 fix = ftmp; | |
1590 if (fix->next == NULL) | |
1591 break; | |
1592 } | |
1593 | |
1594 /* Free the minipool memory. */ | |
1595 obstack_free (&minipool_obstack, minipool_startobj); | |
1596 } | |
1597 | |
1598 | |
1599 /* Implement TARGET_MACHINE_DEPENDENT_REORG. This handles | |
1600 -mconstpool output. */ | |
1601 | |
1602 static void | |
1603 csky_reorg (void) | |
1604 { | |
1605 if (TARGET_CONSTANT_POOL) | |
1606 csky_emit_constant_pools (); | |
1607 } | |
1608 | |
1609 | |
1610 /* Check to see if the current function contains a branch insn with the | |
1611 far jump attribute set. Such a function uses the LR register. */ | |
1612 | |
1613 static bool | |
1614 csky_far_jump_used_p (void) | |
1615 { | |
1616 rtx_insn *insn; | |
1617 if (cfun->machine->far_jump_used) | |
1618 return true; | |
1619 | |
1620 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) | |
1621 if (GET_CODE (insn) == JUMP_INSN | |
1622 /* Ignore tablejump patterns. */ | |
1623 && GET_CODE (PATTERN (insn)) != ADDR_VEC | |
1624 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC | |
1625 && get_attr_far_jump (insn) == FAR_JUMP_YES) | |
1626 { | |
1627 cfun->machine->far_jump_used = 1; | |
1628 return true; | |
1629 } | |
1630 return false; | |
1631 } | |
1632 | |
1633 | |
1634 /* Return the mask of registers used by the current function. Set | |
1635 COUNT to the number of registers used. */ | |
1636 | |
1637 static unsigned int | |
1638 get_csky_live_regs (int *count) | |
1639 { | |
1640 int reg; | |
1641 unsigned int live_regs_mask = 0; | |
1642 | |
1643 *count = 0; | |
1644 for (reg = 0; reg < CSKY_NGPR_REGS; reg++) | |
1645 { | |
1646 bool save = false; | |
1647 | |
1648 /* Ignore unsupported registers. */ | |
1649 if (CSKY_TARGET_ARCH (CK801) && reg > 8 && reg < 13) | |
1650 continue; | |
1651 if ((CSKY_TARGET_ARCH (CK801) | |
1652 || CSKY_TARGET_ARCH (CK802) | |
1653 || CSKY_TARGET_ARCH (CK803)) | |
1654 && reg > 15) | |
1655 break; | |
1656 | |
1657 /* Caller-saved registers marked as used. */ | |
1658 if (df_regs_ever_live_p (reg) && !call_really_used_regs[reg]) | |
1659 save = true; | |
1660 | |
1661 /* Frame pointer marked used. */ | |
1662 else if (frame_pointer_needed && reg == FRAME_POINTER_REGNUM) | |
1663 save = true; | |
1664 | |
1665 /* This is required for CK801/802 where FP is a fixed reg, otherwise | |
1666 we end up with no FP value available to the DWARF-2 unwinder. */ | |
1667 else if (crtl->calls_eh_return && reg == FRAME_POINTER_REGNUM) | |
1668 save = true; | |
1669 | |
1670 /* CK801/802 also need special handling for LR because it's clobbered | |
1671 by far jumps. */ | |
1672 else if ((CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802)) | |
1673 && reg == CSKY_LR_REGNUM | |
1674 && (!crtl->is_leaf || csky_far_jump_used_p ())) | |
1675 save = true; | |
1676 | |
1677 /* Register is used for EH data return. */ | |
1678 else if (crtl->calls_eh_return | |
1679 && reg >= CSKY_FIRST_EH_RETDATA_REGNUM | |
1680 && reg <= CSKY_LAST_EH_RETDATA_REGNUM) | |
1681 save = true; | |
1682 | |
1683 /* We need a temporary reg to hold the offset for adjusting the SP | |
1684 for a large stack frame. */ | |
1685 if (reg == CSKY_STACKADJUST_REGNUM | |
1686 && cfun->machine->reg_offset > CSKY_MAX_SP_ADJUST * 2) | |
1687 save = true; | |
1688 | |
1689 /* Add reg to the mask. */ | |
1690 if (save) | |
1691 { | |
1692 (*count)++; | |
1693 live_regs_mask |= (1 << reg); | |
1694 } | |
1695 } | |
1696 return live_regs_mask; | |
1697 } | |
1698 | |
1699 /* Compute the stack frame layout, storing sizes of the various pieces | |
1700 in cfun->machine. | |
1701 | |
1702 Stack frames constructed in the prologue look like: | |
1703 ... caller's frame ... | |
1704 incoming SP -> caller's outbound argument overflow | |
1705 argument spill | |
1706 optional FP -> register save | |
1707 local variables | |
1708 alloca() space | |
1709 adjusted SP -> outbound argument overflow | |
1710 | |
1711 with SP/FP pointing at the base (low address) of the respective area, | |
1712 and each area aligned to a word boundary. */ | |
1713 | |
1714 static void | |
1715 csky_layout_stack_frame (void) | |
1716 { | |
1717 machine_function *infp = cfun->machine; | |
1718 int reg_count; | |
1719 | |
1720 if (infp->frame_init_p) | |
1721 return; | |
1722 | |
1723 /* Get sizes of local variables & outbound arguments. */ | |
1724 infp->outbound_size = CSKY_STACK_ALIGN (crtl->outgoing_args_size); | |
1725 infp->local_offset = infp->outbound_size; | |
1726 infp->local_size = CSKY_STACK_ALIGN (get_frame_size ()); | |
1727 infp->reg_offset = infp->local_offset + infp->local_size; | |
1728 | |
1729 /* Now compute size of argument spill + saved regs. These do not | |
1730 need explicit alignment since they are already word-sized. */ | |
1731 infp->reg_mask = get_csky_live_regs (®_count); | |
1732 infp->reg_size = reg_count * UNITS_PER_WORD; | |
1733 infp->arg_offset = infp->reg_offset + infp->reg_size; | |
1734 infp->arg_size = crtl->args.pretend_args_size; | |
1735 infp->frame_size = infp->arg_offset + infp->arg_size; | |
1736 infp->frame_init_p = reload_completed; | |
1737 } | |
1738 | |
1739 /* Implement TARGET_CAN_ELIMINATE. */ | |
1740 static bool | |
1741 csky_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) | |
1742 { | |
1743 if (to == STACK_POINTER_REGNUM) | |
1744 return !frame_pointer_needed; | |
1745 return true; | |
1746 } | |
1747 | |
1748 /* Worker function for INITIAL_ELIMINATION_OFFSET macro. | |
1749 Define the offset between two registers, one to be eliminated, and | |
1750 the other its replacement, at the start of a routine. */ | |
1751 | |
1752 HOST_WIDE_INT | |
1753 csky_initial_elimination_offset (int from, int to) | |
1754 { | |
1755 int offset; | |
1756 | |
1757 csky_layout_stack_frame (); | |
1758 | |
1759 /* Set OFFSET to the offset to the initial stack pointer. */ | |
1760 switch (from) | |
1761 { | |
1762 case FRAME_POINTER_REGNUM: | |
1763 offset = cfun->machine->reg_offset; | |
1764 break; | |
1765 | |
1766 case ARG_POINTER_REGNUM: | |
1767 offset = cfun->machine->arg_offset; | |
1768 break; | |
1769 | |
1770 default: | |
1771 gcc_unreachable (); | |
1772 } | |
1773 | |
1774 /* If we are asked for the offset to the frame pointer instead, | |
1775 then subtract the difference between the frame pointer and stack | |
1776 pointer. */ | |
1777 if (to == FRAME_POINTER_REGNUM) | |
1778 offset -= cfun->machine->reg_offset; | |
1779 return offset; | |
1780 } | |
1781 | |
1782 | |
1783 /* Determine where to put an argument to a function. | |
1784 Value is zero to push the argument on the stack, | |
1785 or a hard register in which to store the argument. | |
1786 | |
1787 MODE is the argument's machine mode. | |
1788 TYPE is the data type of the argument (as a tree). | |
1789 This is null for libcalls where that information may | |
1790 not be available. | |
1791 CUM is a variable of type CUMULATIVE_ARGS which gives info about | |
1792 the preceding args and about the function being called. | |
1793 NAMED is nonzero if this argument is a named parameter | |
1794 (otherwise it is an extra parameter matching an ellipsis). */ | |
1795 static rtx | |
1796 csky_function_arg (cumulative_args_t pcum_v, machine_mode mode, | |
1797 const_tree type ATTRIBUTE_UNUSED, | |
1798 bool named ATTRIBUTE_UNUSED) | |
1799 { | |
1800 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); | |
1801 | |
1802 if (*pcum < CSKY_NPARM_REGS) | |
1803 return gen_rtx_REG (mode, CSKY_FIRST_PARM_REGNUM + *pcum); | |
1804 | |
1805 return NULL_RTX; | |
1806 } | |
1807 | |
1808 | |
1809 /* Return the number of registers (words) needed to pass an argument of | |
1810 MODE and TYPE. */ | |
1811 | |
1812 static int | |
1813 csky_num_arg_regs (machine_mode mode, const_tree type) | |
1814 { | |
1815 int size; | |
1816 | |
1817 if (type && mode == BLKmode) | |
1818 size = int_size_in_bytes (type); | |
1819 else | |
1820 size = GET_MODE_SIZE (mode); | |
1821 | |
1822 return CSKY_NUM_WORDS (size); | |
1823 } | |
1824 | |
1825 | |
1826 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */ | |
1827 | |
1828 static void | |
1829 csky_function_arg_advance (cumulative_args_t pcum_v, machine_mode mode, | |
1830 const_tree type, bool named ATTRIBUTE_UNUSED) | |
1831 { | |
1832 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); | |
1833 int param_size = csky_num_arg_regs (mode, type); | |
1834 | |
1835 if (*pcum + param_size > CSKY_NPARM_REGS) | |
1836 *pcum = CSKY_NPARM_REGS; | |
1837 else | |
1838 *pcum += param_size; | |
1839 } | |
1840 | |
1841 | |
1842 /* Implement TARGET_FUNCTION_VALUE. */ | |
1843 static rtx | |
1844 csky_function_value (const_tree type, const_tree func, | |
1845 bool outgoing ATTRIBUTE_UNUSED) | |
1846 { | |
1847 machine_mode mode; | |
1848 int unsignedp ATTRIBUTE_UNUSED; | |
1849 int size; | |
1850 | |
1851 mode = TYPE_MODE (type); | |
1852 size = int_size_in_bytes (type); | |
1853 | |
1854 /* Since we promote return types, we must promote the mode here too. */ | |
1855 if (INTEGRAL_TYPE_P (type)) | |
1856 { | |
1857 mode = promote_function_mode (type, mode, &unsignedp, func, 1); | |
1858 return gen_rtx_REG (mode, CSKY_FIRST_RET_REGNUM); | |
1859 } | |
1860 | |
1861 if (mode == BLKmode && size > UNITS_PER_WORD | |
1862 && size <= UNITS_PER_WORD * 2) | |
1863 { | |
1864 rtx ret_regs[2]; | |
1865 ret_regs[0] = gen_rtx_EXPR_LIST (SImode, | |
1866 gen_rtx_REG (SImode, | |
1867 CSKY_FIRST_RET_REGNUM), | |
1868 GEN_INT (0 * UNITS_PER_WORD)); | |
1869 ret_regs[1] = gen_rtx_EXPR_LIST (SImode, | |
1870 gen_rtx_REG (SImode, | |
1871 CSKY_FIRST_RET_REGNUM + 1), | |
1872 GEN_INT (1 * UNITS_PER_WORD)); | |
1873 | |
1874 rtvec vec = gen_rtvec (2, ret_regs[0], ret_regs[1]); | |
1875 | |
1876 return gen_rtx_PARALLEL (mode, vec); | |
1877 } | |
1878 | |
1879 return gen_rtx_REG (mode, CSKY_FIRST_RET_REGNUM); | |
1880 } | |
1881 | |
1882 | |
1883 /* Implement TARGET_LIBCALL_VALUE. */ | |
1884 static rtx | |
1885 csky_libcall_value (machine_mode mode, | |
1886 const_rtx libcall ATTRIBUTE_UNUSED) | |
1887 { | |
1888 return gen_rtx_REG (mode, CSKY_FIRST_RET_REGNUM); | |
1889 } | |
1890 | |
1891 | |
1892 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. | |
1893 On C-SKY, only r0 can return results. */ | |
1894 | |
1895 static bool | |
1896 csky_function_value_regno_p (const unsigned int regno) | |
1897 { | |
1898 return (regno == CSKY_FIRST_RET_REGNUM); | |
1899 } | |
1900 | |
1901 | |
1902 /* Return an RTX indicating where the return address to the | |
1903 calling function can be found. */ | |
1904 rtx | |
1905 csky_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) | |
1906 { | |
1907 if (count != 0) | |
1908 return NULL_RTX; | |
1909 | |
1910 return get_hard_reg_initial_val (Pmode, CSKY_LR_REGNUM); | |
1911 } | |
1912 | |
1913 | |
1914 /* Implement TARGET_ARG_PARTIAL_BYTES. | |
1915 Return the number of bytes at the beginning of an argument | |
1916 that must be put in registers. The value must be zero for arguments | |
1917 that are passed entirely in registers or | |
1918 that are entirely pushed on the stack. */ | |
1919 static int | |
1920 csky_arg_partial_bytes (cumulative_args_t pcum_v, machine_mode mode, | |
1921 tree type, bool named ATTRIBUTE_UNUSED) | |
1922 { | |
1923 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); | |
1924 int param_size = csky_num_arg_regs (mode, type); | |
1925 | |
1926 if (*pcum < CSKY_NPARM_REGS | |
1927 && *pcum + param_size > CSKY_NPARM_REGS) | |
1928 return (CSKY_NPARM_REGS - *pcum) * UNITS_PER_WORD; | |
1929 | |
1930 return 0; | |
1931 } | |
1932 | |
1933 | |
1934 /* Implement TARGET_SETUP_INCOMING_VARARGS. | |
1935 On C-Sky the copy from the argument registers to the stack is emitted | |
1936 by the prologue hooks, so here we just have to note how much stack space | |
1937 to save. */ | |
1938 | |
1939 static void | |
1940 csky_setup_incoming_varargs (cumulative_args_t pcum_v, | |
1941 machine_mode mode, | |
1942 tree type, | |
1943 int *pretend_size, | |
1944 int second_time ATTRIBUTE_UNUSED) | |
1945 { | |
1946 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); | |
1947 CUMULATIVE_ARGS local_cum; | |
1948 cumulative_args_t local_cum_v = pack_cumulative_args (&local_cum); | |
1949 int regs_to_push; | |
1950 | |
1951 cfun->machine->uses_anonymous_args = 1; | |
1952 local_cum = *pcum; | |
1953 csky_function_arg_advance (local_cum_v, mode, type, true); | |
1954 regs_to_push = CSKY_NPARM_REGS - local_cum; | |
1955 if (regs_to_push) | |
1956 *pretend_size = regs_to_push * UNITS_PER_WORD; | |
1957 } | |
1958 | |
1959 | |
1960 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. | |
1961 Output code to add DELTA to the first argument, and then jump | |
1962 to FUNCTION. Used for C++ multiple inheritance. */ | |
1963 | |
1964 static void | |
1965 csky_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, | |
1966 HOST_WIDE_INT delta, | |
1967 HOST_WIDE_INT vcall_offset, | |
1968 tree function) | |
1969 { | |
1970 const char *thiz = "a0"; | |
1971 const char *reg0 = "t0"; | |
1972 const char *reg1 = "t1"; | |
1973 int maxoff = 4096; /* Constant range for addi/subi. */ | |
1974 | |
1975 final_start_function (emit_barrier (), file, 1); | |
1976 | |
1977 rtx fnaddr = XEXP (DECL_RTL (function), 0); | |
1978 | |
1979 if (CSKY_TARGET_ARCH (CK801)) | |
1980 { | |
1981 /* CK801 can't use t registers and has only 16-bit addi/subi. */ | |
1982 reg0 = "l0"; | |
1983 reg1 = "l1"; | |
1984 maxoff = 256; | |
1985 if (vcall_offset > maxoff || vcall_offset < -maxoff) | |
1986 fprintf (file, "\tpush\tl0, l1\n"); | |
1987 else if (delta > maxoff || delta < -maxoff) | |
1988 fprintf (file, "\tpush\tl0\n"); | |
1989 } | |
1990 | |
1991 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) | |
1992 thiz = "a1"; | |
1993 | |
1994 /* Add delta to this_rtx. */ | |
1995 if (delta != 0) | |
1996 { | |
1997 if (delta > maxoff || delta < -maxoff) | |
1998 { | |
1999 fprintf (file, "\tlrw\t%s, %ld\n", reg0, (long)delta); | |
2000 fprintf (file, "\taddu\t%s, %s, %s\n", thiz, thiz, reg0); | |
2001 } | |
2002 else | |
2003 fprintf (file, "\t%s\t%s, %s, %ld\n", | |
2004 (delta > 0 ? "addi" : "subi"), thiz, thiz, | |
2005 (long)(delta > 0 ? delta : -delta)); | |
2006 } | |
2007 | |
2008 /* If needed, add *(*this_rtx + vcall_offset) to this_rtx. */ | |
2009 if (vcall_offset != 0) | |
2010 { | |
2011 fprintf (file, "\tld.w\t%s, (%s, 0)\n", reg0, thiz); | |
2012 | |
2013 if (vcall_offset > maxoff || vcall_offset < -maxoff) | |
2014 { | |
2015 fprintf (file, "\tlrw\t%s, %ld\n", reg1, (long)vcall_offset); | |
2016 fprintf (file, "\taddu\t%s, %s, %s\n", reg0, reg0, reg1); | |
2017 } | |
2018 else | |
2019 fprintf (file, "\t%s\t%s, %s, %ld\n", | |
2020 (vcall_offset > 0 ? "addi" : "subi"), reg0, reg0, | |
2021 (long)(vcall_offset > 0 ? vcall_offset : -vcall_offset)); | |
2022 | |
2023 /* Load the offset and add it to this_rtx */ | |
2024 fprintf (file, "\tld.w\t%s, (%s, 0)\n", reg0, reg0); | |
2025 fprintf (file, "\taddu\t%s, %s, %s\n", thiz, thiz, reg0); | |
2026 } | |
2027 | |
2028 /* We must pop the scratch regs individually instead of using the | |
2029 "pop" insn, which also does a return. */ | |
2030 if (CSKY_TARGET_ARCH (CK801)) | |
2031 { | |
2032 if (vcall_offset > maxoff || vcall_offset < -maxoff) | |
2033 { | |
2034 fprintf (file, "\tld.w\tl0, (sp, 0)\n"); | |
2035 fprintf (file, "\tld.w\tl1, (sp, 4)\n"); | |
2036 fprintf (file, "\taddi\t sp, sp, 8\n"); | |
2037 } | |
2038 else if (delta > maxoff || delta < -maxoff) | |
2039 { | |
2040 fprintf (file, "\tld.w\tl0, (sp, 0)\n"); | |
2041 fprintf (file, "\taddi\tsp, sp, 4\n"); | |
2042 } | |
2043 } | |
2044 | |
2045 fprintf (file, "\tjbr\t"); | |
2046 output_addr_const (file, fnaddr); | |
2047 fprintf (file, "\n"); | |
2048 | |
2049 final_end_function (); | |
2050 } | |
2051 | |
2052 | |
2053 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. | |
2054 Conditionally modify five variables fixed_regs, call_used_regs, global_regs, | |
2055 reg_names, and reg_class_contents, to take into account any dependence of | |
2056 these register sets on target flags. | |
2057 | |
2058 CK801 has registers r0-r8 and r13-r15. CK802 and CK803 have registers | |
2059 r0-r15 (the "low" registers). Other cpus use registers r0-r31 with | |
2060 -mhigh-registers, otherwise also only r0-r15. | |
2061 | |
2062 CK801 only has 16-bit instructions, most of which can only reference | |
2063 r0-r7 (the "mini" registers). So we mark regs outside that range as | |
2064 fixed. -msmart can be used on other arch variants to force the same | |
2065 behavior because it results in smaller code size. | |
2066 | |
2067 TODO: investigate whether it's beneficial to use r8-r13 as a spill | |
2068 class when TARGET_MINI_REGISTERS instead of making them unusable by | |
2069 the register allocator. */ | |
2070 | |
2071 static void | |
2072 csky_conditional_register_usage (void) | |
2073 { | |
2074 /* Only use mini registers in smart mode or 801. */ | |
2075 if (TARGET_MINI_REGISTERS) | |
2076 { | |
2077 int i; | |
2078 | |
2079 for (i = (CSKY_LAST_MINI_REGNUM + 1); i < 32; i++) | |
2080 { | |
2081 fixed_regs[i] = 1; | |
2082 call_used_regs[i] = 1; | |
2083 call_really_used_regs[i] = 1; | |
2084 } | |
2085 } | |
2086 /* For some targets, the high registers are not supported. | |
2087 CPUs other than ck801/ck802/ck803 use high registers | |
2088 depending on -mhigh-registers option. */ | |
2089 else if (CSKY_TARGET_ARCH (CK802) | |
2090 || CSKY_TARGET_ARCH (CK803) | |
2091 || !TARGET_HIGH_REGISTERS) | |
2092 { | |
2093 int i; | |
2094 | |
2095 for (i = CSKY_FIRST_HIGH_REGNUM; i <= CSKY_LAST_HIGH_REGNUM; i++) | |
2096 { | |
2097 fixed_regs[i] = 1; | |
2098 call_used_regs[i] = 1; | |
2099 call_really_used_regs[i] = 1; | |
2100 } | |
2101 } | |
2102 | |
2103 /* On CK801/CK802 we must mark lr as a fixed register because it is | |
2104 used to implement far jumps. | |
2105 FIXME: perhaps there should be a command-line option controlling | |
2106 use of lr for far jumps on ck802 when !TARGET_MINI_REGS, when | |
2107 you really want lr to be available to the register allocator and | |
2108 you know there are no far jumps in the code. */ | |
2109 if (CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802)) | |
2110 { | |
2111 fixed_regs[CSKY_LR_REGNUM] = 1; | |
2112 call_used_regs[CSKY_LR_REGNUM] = 1; | |
2113 call_really_used_regs[CSKY_LR_REGNUM] = 0; | |
2114 } | |
2115 | |
2116 /* The hi/lo registers are only supported in dsp mode. */ | |
2117 if (!TARGET_DSP) | |
2118 { | |
2119 fixed_regs[CSKY_HI_REGNUM] = 1; | |
2120 call_used_regs[CSKY_HI_REGNUM] = 1; | |
2121 call_really_used_regs[CSKY_HI_REGNUM] = 1; | |
2122 | |
2123 fixed_regs[CSKY_LO_REGNUM] = 1; | |
2124 call_used_regs[CSKY_LO_REGNUM] = 1; | |
2125 call_really_used_regs[CSKY_LO_REGNUM] = 1; | |
2126 } | |
2127 | |
2128 /* The V_REGS are only supported in hard float mode. */ | |
2129 if (!TARGET_HARD_FLOAT) | |
2130 { | |
2131 int regno; | |
2132 | |
2133 for (regno = CSKY_FIRST_VFP_REGNUM; | |
2134 regno <= CSKY_LAST_VFP_REGNUM; regno++) | |
2135 { | |
2136 fixed_regs[regno] = 1; | |
2137 call_used_regs[regno] = 1; | |
2138 call_really_used_regs[regno] = 1; | |
2139 } | |
2140 } | |
2141 | |
2142 /* In pic mode, the gb register is not available for register | |
2143 allocation. Since gb is not clobbered by function | |
2144 calls, set its call_really_used_regs to 0. */ | |
2145 if (flag_pic) | |
2146 { | |
2147 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; | |
2148 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; | |
2149 call_really_used_regs[PIC_OFFSET_TABLE_REGNUM] = 0; | |
2150 } | |
2151 } | |
2152 | |
2153 /* Implement TARGET_HARD_REGNO_NREGS. */ | |
2154 static unsigned int | |
2155 csky_hard_regno_nregs (unsigned int regno, machine_mode mode) | |
2156 { | |
2157 if (regno >= CSKY_FIRST_VFP_REGNUM && !CSKY_TARGET_ARCH (CK803)) | |
2158 return 1; | |
2159 else | |
2160 return CSKY_NUM_REGS (mode); | |
2161 } | |
2162 | |
2163 /* Implement TARGET_HARD_REGNO_MODE_OK. Return true if REGNO is a | |
2164 valid register for holding a quantity of type MODE. */ | |
2165 | |
2166 static bool | |
2167 csky_hard_regno_mode_ok (unsigned int regno, machine_mode mode) | |
2168 { | |
2169 int nregs = CSKY_NUM_REGS (mode); | |
2170 | |
2171 /* We can't handle more than doubleword sizes for any register. */ | |
2172 if (nregs > 2) | |
2173 return false; | |
2174 | |
2175 /* For general registers, return true if mode is one word size. | |
2176 When the size is larger than one word size, there should | |
2177 be two successive hard registers to put the data. */ | |
2178 if (regno < CSKY_NGPR_REGS) | |
2179 { | |
2180 if (nregs < 2) | |
2181 return true; | |
2182 else if (TARGET_MINI_REGISTERS) | |
2183 return (regno < CSKY_LAST_MINI_REGNUM); | |
2184 else if (CSKY_TARGET_ARCH (CK802) | |
2185 || CSKY_TARGET_ARCH (CK803) | |
2186 || !TARGET_HIGH_REGISTERS) | |
2187 /* Without high register, r15 cannot hold doubleword data. */ | |
2188 return (regno < (CSKY_SP_REGNUM - 1)); | |
2189 else | |
2190 return (regno < (CSKY_SP_REGNUM - 1) | |
2191 || (regno >= CSKY_LR_REGNUM | |
2192 && regno < CSKY_LAST_HIGH_UNFIXED_REGNUM)); | |
2193 } | |
2194 else if (regno == CSKY_CC_REGNUM) | |
2195 return (mode == CCmode); | |
2196 else if (regno == CSKY_HI_REGNUM || regno == CSKY_LO_REGNUM) | |
2197 { | |
2198 /* Don't allocate hi,lo register for float data even | |
2199 if in dsp mode, because it will cause high cost | |
2200 to reload data from hi,lo register. */ | |
2201 if (!TARGET_DSP || mode == SFmode || mode == DFmode) | |
2202 return false; | |
2203 else if (nregs == 2) | |
2204 return (regno == CSKY_HI_REGNUM); | |
2205 else | |
2206 return true; | |
2207 } | |
2208 else if (CSKY_VREG_P (regno) && TARGET_HARD_FLOAT) | |
2209 return true; | |
2210 | |
2211 return false; | |
2212 } | |
2213 | |
2214 /* Implement TARGET_MODES_TIEABLE_P. We can't tie DFmode with other modes | |
2215 when V_REGs might be in use because those registers mess with the stored | |
2216 bits. */ | |
2217 static bool | |
2218 csky_modes_tieable_p (machine_mode mode1, machine_mode mode2) | |
2219 { | |
2220 return !(TARGET_HARD_FLOAT | |
2221 && mode1 != mode2 | |
2222 && (mode1 == DFmode || mode2 == DFmode)); | |
2223 } | |
2224 | |
2225 /* Implement TARGET_CAN_CHANGE_MODE_CLASS. | |
2226 V_REG registers can't do subreg as all values are reformatted to | |
2227 internal precision. */ | |
2228 static bool | |
2229 csky_can_change_mode_class (machine_mode from, | |
2230 machine_mode to, | |
2231 reg_class_t rclass) | |
2232 { | |
2233 return (GET_MODE_SIZE (from) == GET_MODE_SIZE (to) | |
2234 || !reg_classes_intersect_p (V_REGS, rclass)); | |
2235 } | |
2236 | |
2237 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. | |
2238 We need to define this for MINI_REGS when we only use r0 - r7. | |
2239 Otherwise we can end up using r0-r4 for function arguments, and don't | |
2240 have enough left over to do doubleword arithmetic. */ | |
2241 | |
2242 static bool | |
2243 csky_class_likely_spilled_p (reg_class_t rclass) | |
2244 { | |
2245 if ((TARGET_MINI_REGISTERS && rclass == MINI_REGS) | |
2246 || rclass == C_REGS) | |
2247 return true; | |
2248 | |
2249 return false; | |
2250 } | |
2251 | |
2252 | |
2253 /* Implement TARGET_PREFERRED_RELOAD_CLASS. | |
2254 Given an rtx X being reloaded into a reg required to be | |
2255 in class CLASS, return the class of reg to actually use. | |
2256 In general this is just CLASS. */ | |
2257 | |
2258 static reg_class_t | |
2259 csky_preferred_reload_class (rtx x, reg_class_t rclass) | |
2260 { | |
2261 if (TARGET_HARD_FLOAT | |
2262 && CONST_DOUBLE_P (x) | |
2263 && (GET_MODE (x) == DFmode || GET_MODE (x) == SFmode) | |
2264 && rclass == NO_REGS) | |
2265 return GENERAL_REGS; | |
2266 return rclass; | |
2267 } | |
2268 | |
2269 | |
2270 /* Implement TARGET_CLASS_MAX_NREGS. | |
2271 Return the maximum number of consecutive registers of class rclass needed | |
2272 to hold a value of mode mode. | |
2273 On the csky, this is the size of MODE in words, | |
2274 except in the FP regs, where a single reg is always enough. */ | |
2275 | |
2276 static unsigned char | |
2277 csky_class_max_nregs (reg_class_t rclass, machine_mode mode) | |
2278 { | |
2279 if (rclass == V_REGS) | |
2280 return 1; | |
2281 else | |
2282 return CSKY_NUM_REGS (mode); | |
2283 } | |
2284 | |
2285 | |
2286 /* Implement TARGET_SECONDARY_RELOAD. | |
2287 If copying a register of RCLASS from/to X requires an intermediate | |
2288 register, the hook should return the REGISTER_CLASS required for this | |
2289 intermediate register. | |
2290 If no intermediate register is required, it should return NO_REGS. | |
2291 If more than one intermediate register is required, describe the one | |
2292 that is closest in the copy chain to the reload register. */ | |
2293 | |
2294 reg_class_t | |
2295 csky_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, | |
2296 reg_class_t rclass, | |
2297 machine_mode mode, | |
2298 secondary_reload_info *sri ATTRIBUTE_UNUSED) | |
2299 { | |
2300 int regno = -1; | |
2301 | |
2302 /* Extract the real regno from X. */ | |
2303 if (GET_CODE (x) == SIGN_EXTEND) | |
2304 { | |
2305 int off = 0; | |
2306 | |
2307 x = XEXP (x, 0); | |
2308 | |
2309 if (reg_renumber) | |
2310 regno = true_regnum (x); | |
2311 else | |
2312 { | |
2313 while (GET_CODE (x) == SUBREG) | |
2314 { | |
2315 off += subreg_regno_offset (REGNO (SUBREG_REG (x)), | |
2316 GET_MODE (SUBREG_REG (x)), | |
2317 SUBREG_BYTE (x), GET_MODE (x)); | |
2318 x = SUBREG_REG (x); | |
2319 } | |
2320 | |
2321 if (GET_CODE (x) == REG) | |
2322 regno = REGNO (x) + off; | |
2323 } | |
2324 } | |
2325 else if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG) | |
2326 regno = true_regnum (x); | |
2327 | |
2328 /* We always require a general register when copying anything to | |
2329 HI/LO_REGNUM, except when copying an SImode value from HI/LO_REGNUM | |
2330 to a general register, or when copying from register 0. */ | |
2331 if ((rclass == HILO_REGS || rclass == LO_REGS || rclass == HI_REGS) | |
2332 && !CSKY_GENERAL_REGNO_P (regno)) | |
2333 return GENERAL_REGS; | |
2334 | |
2335 if (rclass == V_REGS && !CSKY_GENERAL_REGNO_P (regno)) | |
2336 { | |
2337 /* Reload between vector reg and memory does not need an | |
2338 intermediate register. */ | |
2339 if (MEM_P (x) && (mode == SFmode || mode == DFmode)) | |
2340 return NO_REGS; | |
2341 else | |
2342 return GENERAL_REGS; | |
2343 } | |
2344 | |
2345 return NO_REGS; | |
2346 } | |
2347 | |
2348 /* Implement TARGET_SPILL_CLASS. | |
2349 Try spilling to a larger register class before spilling to memory. */ | |
2350 | |
2351 static reg_class_t | |
2352 csky_spill_class (reg_class_t rclass, machine_mode mode ATTRIBUTE_UNUSED) | |
2353 { | |
2354 if ((rclass == MINI_REGS && !TARGET_MINI_REGISTERS) | |
2355 || (rclass == LOW_REGS && TARGET_HIGH_REGISTERS)) | |
2356 return GENERAL_REGS; | |
2357 return NO_REGS; | |
2358 } | |
2359 | |
2360 /* Convert a static initializer array of feature bits to sbitmap | |
2361 representation. */ | |
2362 static void | |
2363 csky_initialize_isa (sbitmap isa, const enum csky_isa_feature *isa_bits) | |
2364 { | |
2365 bitmap_clear (isa); | |
2366 while (*isa_bits != CSKY_ISA_FEATURE_GET (none)) | |
2367 bitmap_set_bit (isa, *(isa_bits++)); | |
2368 } | |
2369 | |
2370 | |
2371 /* Configure a build target TARGET from the user-specified options OPTS and | |
2372 OPTS_SET. */ | |
2373 static void | |
2374 csky_configure_build_target (struct csky_build_target *target, | |
2375 struct cl_target_option *opts, | |
2376 struct gcc_options *opts_set) | |
2377 { | |
2378 const struct csky_processors *csky_selected_tune = NULL; | |
2379 struct csky_processors *csky_selected_cpu = NULL; | |
2380 struct csky_processors *csky_selected_arch = NULL; | |
2381 sbitmap all_sbits = sbitmap_alloc (CSKY_ISA_FEATURE_GET (max)); | |
2382 bitmap_clear (all_sbits); | |
2383 | |
2384 bitmap_clear (target->isa); | |
2385 target->core_name = NULL; | |
2386 target->arch_name = NULL; | |
2387 | |
2388 if (opts_set->x_csky_arch_option) | |
2389 csky_selected_arch = &all_architectures[opts->x_csky_arch_option]; | |
2390 | |
2391 if (opts_set->x_csky_cpu_option) | |
2392 { | |
2393 csky_selected_cpu = &all_cores[opts->x_csky_cpu_option]; | |
2394 csky_selected_tune = &all_cores[opts->x_csky_cpu_option]; | |
2395 } | |
2396 | |
2397 if (csky_selected_cpu) | |
2398 { | |
2399 /* TODO: support combination of features | |
2400 between different cpu & arch, should based on arch. */ | |
2401 if (csky_selected_arch | |
2402 && (csky_selected_cpu->base_arch != csky_selected_arch->base_arch)) | |
2403 warning (0, "cpu %s is not based on arch %s, ignoring the arch", | |
2404 csky_selected_cpu->name, csky_selected_arch->name); | |
2405 if (!csky_selected_arch) | |
2406 csky_selected_arch = &all_architectures[csky_selected_cpu->base_arch]; | |
2407 csky_initialize_isa (all_sbits, csky_selected_arch->isa_bits); | |
2408 target->core_name = csky_selected_cpu->name; | |
2409 } | |
2410 else if (csky_selected_arch) | |
2411 { | |
2412 csky_selected_cpu = csky_selected_arch; | |
2413 target->arch_name = csky_selected_arch->name; | |
2414 } | |
2415 else /* If the user did not specify a processor, choose one for them. */ | |
2416 { | |
2417 csky_selected_cpu = &all_cores[TARGET_CPU_DEFAULT]; | |
2418 csky_selected_arch = &all_architectures[csky_selected_cpu->base_arch]; | |
2419 csky_initialize_isa (all_sbits, csky_selected_arch->isa_bits); | |
2420 target->core_name = csky_selected_cpu->name; | |
2421 } | |
2422 | |
2423 /* The selected cpu may be an architecture, so lookup tuning by core ID. */ | |
2424 if (!csky_selected_tune) | |
2425 csky_selected_tune = &all_cores[csky_selected_cpu->core]; | |
2426 gcc_assert (csky_selected_tune); | |
2427 | |
2428 gcc_assert (csky_selected_arch); | |
2429 gcc_assert (csky_selected_cpu); | |
2430 csky_initialize_isa (target->isa, csky_selected_cpu->isa_bits); | |
2431 bitmap_ior (target->isa, target->isa, all_sbits); | |
2432 | |
2433 /* Finish initializing the target structure. */ | |
2434 target->arch_pp_name = csky_selected_cpu->arch; | |
2435 target->base_arch = csky_selected_cpu->base_arch; | |
2436 target->arch_core = csky_selected_cpu->core; | |
2437 | |
2438 sbitmap_free (all_sbits); | |
2439 } | |
2440 | |
2441 | |
2442 /* Implement TARGET_OPTION_OVERRIDE. */ | |
2443 | |
2444 static void | |
2445 csky_option_override (void) | |
2446 { | |
2447 csky_active_target.isa = sbitmap_alloc (CSKY_ISA_FEATURE_GET (max)); | |
2448 | |
2449 /* Create the default target_options structure. We need this early | |
2450 to configure the overall build target. */ | |
2451 target_option_default_node = target_option_current_node | |
2452 = build_target_option_node (&global_options); | |
2453 | |
2454 csky_configure_build_target (&csky_active_target, | |
2455 TREE_TARGET_OPTION (target_option_default_node), | |
2456 &global_options_set); | |
2457 | |
2458 #ifdef SUBTARGET_OVERRIDE_OPTIONS | |
2459 SUBTARGET_OVERRIDE_OPTIONS; | |
2460 #endif | |
2461 | |
2462 csky_base_arch = csky_active_target.base_arch; | |
2463 | |
2464 if (flag_pic && !(CSKY_TARGET_ARCH (CK810) || CSKY_TARGET_ARCH (CK807))) | |
2465 { | |
2466 flag_pic = 0; | |
2467 warning (0, "%qs is not supported by arch %s", | |
2468 "-fPIC", csky_active_target.arch_pp_name); | |
2469 } | |
2470 | |
2471 /* Check floating-point options for consistency. */ | |
2472 if (TARGET_HARD_FLOAT) | |
2473 { | |
2474 const struct csky_fpu_desc *csky_selected_fpu = NULL; | |
2475 | |
2476 if (csky_fpu_index == TARGET_FPU_auto) | |
2477 { | |
2478 const char *target_fpu_name; | |
2479 bool ok; | |
2480 int fpu_index; | |
2481 | |
2482 #ifdef CSKY_FPUTYPE_DEFAULT | |
2483 target_fpu_name = CSKY_FPUTYPE_DEFAULT; | |
2484 #else | |
2485 target_fpu_name = "fpv2"; | |
2486 #endif | |
2487 | |
2488 if (csky_active_target.core_name != NULL | |
2489 && !strchr (csky_active_target.core_name, 'f')) | |
2490 target_fpu_name = "auto"; | |
2491 else if (CSKY_TARGET_ARCH (CK803) || !TARGET_DOUBLE_FLOAT) | |
2492 target_fpu_name = "fpv2_sf"; | |
2493 else if (TARGET_DOUBLE_FLOAT && TARGET_FDIVDU) | |
2494 target_fpu_name = "fpv2_divd"; | |
2495 | |
2496 ok = opt_enum_arg_to_value (OPT_mfpu_, target_fpu_name, &fpu_index, | |
2497 CL_TARGET); | |
2498 gcc_assert (ok); | |
2499 csky_fpu_index = (enum csky_fpu_type) fpu_index; | |
2500 } | |
2501 | |
2502 if (CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802)) | |
2503 error ("%qs is not supported by arch %s", | |
2504 "-mhard-float", csky_active_target.arch_pp_name); | |
2505 else if (csky_fpu_index == TARGET_FPU_auto) | |
2506 error ("%<-mhard-float%> is not supported by the selected CPU"); | |
2507 else | |
2508 { | |
2509 csky_selected_fpu = &all_fpus[csky_fpu_index]; | |
2510 sbitmap fpu_bits = sbitmap_alloc (CSKY_ISA_FEATURE_GET (max)); | |
2511 csky_initialize_isa (fpu_bits, csky_selected_fpu->isa_bits); | |
2512 | |
2513 bitmap_ior (csky_active_target.isa, csky_active_target.isa, | |
2514 fpu_bits); | |
2515 | |
2516 sbitmap_free (fpu_bits); | |
2517 } | |
2518 } | |
2519 else | |
2520 { | |
2521 if (TARGET_DOUBLE_FLOAT > 0) | |
2522 warning (0, "%<-mdouble-float%> ignored without %<-mhard-float%>"); | |
2523 TARGET_DOUBLE_FLOAT = 0; | |
2524 if (TARGET_FDIVDU > 0) | |
2525 warning (0, "%<-mfdivdu%> ignored without %<-mhard-float%>"); | |
2526 TARGET_FDIVDU = 0; | |
2527 } | |
2528 | |
2529 /* Extended LRW instructions are enabled by default on CK801, disabled | |
2530 otherwise. */ | |
2531 if (TARGET_ELRW == -1) | |
2532 TARGET_ELRW = CSKY_TARGET_ARCH (CK801); | |
2533 | |
2534 /* DSP is enabled either by the processor feature or -mdsp | |
2535 command-line option. There is no -mno-dsp option as the assembler | |
2536 doesn't take one. */ | |
2537 if (!TARGET_DSP) | |
2538 TARGET_DSP = CSKY_ISA_FEATURE (dsp); | |
2539 | |
2540 /* There's both -mdiv and -mno-div. Take default from processor if | |
2541 neither is specified explicitly. */ | |
2542 if (TARGET_DIV == -1) | |
2543 TARGET_DIV = CSKY_ISA_FEATURE (div); | |
2544 | |
2545 /* TARGET_CONSTANT_POOL is mandatory for CK801 and CK802 and optional | |
2546 for other CPUs. | |
2547 The reason why the compiler has to generate constant pools for CK801/2 | |
2548 instead of deferring to the assembler is that these cores don't have a | |
2549 long branch instruction other than jbsr, which clobbers lr. So for | |
2550 the compiler to correctly save/restore lr it has to know whether there | |
2551 are long branches, which depends on having accurate branch length | |
2552 counts, which in turn depends on having control over where constant | |
2553 pools are placed. */ | |
2554 if ((CSKY_TARGET_ARCH (CK801) || CSKY_TARGET_ARCH (CK802)) | |
2555 && !TARGET_CONSTANT_POOL) | |
2556 error ("%qs is not supported by arch %s", | |
2557 "-mno-constpool", csky_active_target.arch_pp_name); | |
2558 else if (TARGET_CONSTANT_POOL == -1) | |
2559 TARGET_CONSTANT_POOL = (CSKY_TARGET_ARCH (CK801) | |
2560 || CSKY_TARGET_ARCH (CK802)); | |
2561 | |
2562 /* TARGET_MINI_REGISTERS is mandatory for CK801, the default for CK802, | |
2563 and optional for other CPUs. TARGET_HIGH_REGISTERS is incompatible | |
2564 with TARGET_MINI_REGISTERS, is not supported by CK801/802/803, | |
2565 and is the default for other processors. | |
2566 See csky_conditional_register_usage. */ | |
2567 if (TARGET_MINI_REGISTERS > 0 && TARGET_HIGH_REGISTERS > 0) | |
2568 error ("%<-msmart%> is incompatible with %<-mhigh-registers%>"); | |
2569 else if (CSKY_TARGET_ARCH (CK801) | |
2570 || CSKY_TARGET_ARCH (CK802) | |
2571 || CSKY_TARGET_ARCH (CK803)) | |
2572 { | |
2573 if (CSKY_TARGET_ARCH (CK801) | |
2574 || (CSKY_TARGET_ARCH (CK802) && TARGET_MINI_REGISTERS == -1)) | |
2575 TARGET_MINI_REGISTERS = 1; | |
2576 else if (TARGET_MINI_REGISTERS == -1) | |
2577 TARGET_MINI_REGISTERS = 0; | |
2578 if (TARGET_HIGH_REGISTERS > 0) | |
2579 warning (0, "%qs is not supported by arch %s", | |
2580 "-mhigh-registers", csky_active_target.arch_pp_name); | |
2581 TARGET_HIGH_REGISTERS = 0; | |
2582 } | |
2583 else | |
2584 { | |
2585 if (TARGET_MINI_REGISTERS == -1) | |
2586 TARGET_MINI_REGISTERS = 0; | |
2587 if (TARGET_HIGH_REGISTERS == -1) | |
2588 TARGET_HIGH_REGISTERS = !TARGET_MINI_REGISTERS; | |
2589 } | |
2590 | |
2591 /* -mmultiple-stld is the default for everything but CK801, which | |
2592 doesn't support it. */ | |
2593 if (CSKY_TARGET_ARCH (CK801)) | |
2594 { | |
2595 if (TARGET_MULTIPLE_STLD > 0) | |
2596 warning (0, "%qs is not supported by arch %s", | |
2597 "-mmultiple-stld", csky_active_target.arch_pp_name); | |
2598 TARGET_MULTIPLE_STLD = 0; | |
2599 } | |
2600 | |
2601 /* Initialize boolean versions of the architectural flags, for use | |
2602 in the .md file. */ | |
2603 | |
2604 #undef CSKY_ISA | |
2605 #define CSKY_ISA(IDENT, DESC) \ | |
2606 { \ | |
2607 csky_arch_isa_features[CSKY_ISA_FEATURE_GET (IDENT)] = \ | |
2608 bitmap_bit_p (csky_active_target.isa, CSKY_ISA_FEATURE_GET (IDENT)); \ | |
2609 } | |
2610 #include "csky_isa.def" | |
2611 #undef CSKY_ISA | |
2612 | |
2613 /* TODO */ | |
2614 | |
2615 /* Resynchronize the saved target options. */ | |
2616 cl_target_option_save (TREE_TARGET_OPTION (target_option_default_node), | |
2617 &global_options); | |
2618 | |
2619 #ifdef ENABLE_TPF_DEBUG | |
2620 /* Don't emit DWARF4 unless specifically selected. The TPF | |
2621 debuggers do not yet support DWARF 3/4. */ | |
2622 if (!global_options_set.x_dwarf_strict) | |
2623 dwarf_strict = 1; | |
2624 if (!global_options_set.x_dwarf_version) | |
2625 dwarf_version = 3; | |
2626 #endif | |
2627 | |
2628 /* Don't run the scheduler before reload by default, | |
2629 since it tends to increase register pressure. */ | |
2630 if (!global_options_set.x_flag_schedule_insns) | |
2631 flag_schedule_insns = 0; | |
2632 | |
2633 csky_add_gc_roots (); | |
2634 } | |
2635 | |
2636 | |
2637 /* Return TRUE if X contains any references to TLS symbols. */ | |
2638 | |
2639 bool | |
2640 csky_tls_referenced_p (rtx x) | |
2641 { | |
2642 if (!TARGET_TLS) | |
2643 return false; | |
2644 | |
2645 subrtx_iterator::array_type array; | |
2646 FOR_EACH_SUBRTX (iter, array, x, ALL) | |
2647 { | |
2648 const_rtx x = *iter; | |
2649 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0) | |
2650 return true; | |
2651 | |
2652 /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are | |
2653 TLS offsets, not real symbol references. */ | |
2654 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS) | |
2655 iter.skip_subrtxes (); | |
2656 } | |
2657 return false; | |
2658 } | |
2659 | |
2660 | |
2661 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. | |
2662 Determine if it's legal to put X into the constant pool. This | |
2663 is not possible for the address of thread-local symbols, which | |
2664 is checked above. */ | |
2665 | |
2666 static bool | |
2667 csky_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, | |
2668 rtx x) | |
2669 { | |
2670 return csky_tls_referenced_p (x); | |
2671 } | |
2672 | |
2673 | |
2674 /* Implement TARGET_LEGITIMATE_CONSTANT_P. Returns nonzero if the | |
2675 constant value X is a legitimate general operand. | |
2676 It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ | |
2677 | |
2678 static bool | |
2679 csky_legitimate_constant_p (machine_mode mode, rtx x) | |
2680 { | |
2681 return (!csky_cannot_force_const_mem (mode, x) | |
2682 && CONSTANT_P (x)); | |
2683 } | |
2684 | |
2685 | |
2686 /* Return true if X is valid as an CSKY addressing register. */ | |
2687 | |
2688 static bool | |
2689 is_csky_address_register_rtx_p (rtx x, int strict_p) | |
2690 { | |
2691 int regno; | |
2692 | |
2693 if (!x) | |
2694 return false; | |
2695 if (!REG_P (x)) | |
2696 return false; | |
2697 | |
2698 regno = REGNO (x); | |
2699 | |
2700 if (strict_p) | |
2701 return (CSKY_GENERAL_REGNO_P (regno) | |
2702 || CSKY_GENERAL_REGNO_P (reg_renumber[regno])); | |
2703 else | |
2704 return CSKY_GENERAL_REGNO_P (regno) || regno >= FIRST_PSEUDO_REGISTER; | |
2705 } | |
2706 | |
2707 | |
2708 /* Return TRUE if X is a thread-local symbol. */ | |
2709 | |
2710 static bool | |
2711 csky_tls_symbol_p (rtx x) | |
2712 { | |
2713 if (!TARGET_TLS) | |
2714 return false; | |
2715 | |
2716 if (GET_CODE (x) != SYMBOL_REF) | |
2717 return false; | |
2718 | |
2719 return SYMBOL_REF_TLS_MODEL (x) != 0; | |
2720 } | |
2721 | |
2722 | |
2723 /* Handle lazy initialization of __tls_get_addr libfunc. */ | |
2724 static GTY(()) rtx tls_get_addr_libfunc; | |
2725 | |
2726 static rtx | |
2727 get_tls_get_addr (void) | |
2728 { | |
2729 if (!tls_get_addr_libfunc) | |
2730 tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr"); | |
2731 return tls_get_addr_libfunc; | |
2732 } | |
2733 | |
2734 | |
2735 /* Emit a call to __tls_get_addr. */ | |
2736 | |
2737 static rtx_insn * | |
2738 csky_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc) | |
2739 { | |
2740 rtx label, labelno, unspec, tmp; | |
2741 rtx_insn *insns; | |
2742 | |
2743 start_sequence (); | |
2744 | |
2745 labelno = GEN_INT (tls_labelno++); | |
2746 label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_TLS_LABEL); | |
2747 unspec = gen_rtx_UNSPEC (Pmode, | |
2748 gen_rtvec (3, x, GEN_INT (reloc), label), | |
2749 UNSPEC_TLS); | |
2750 tmp = gen_reg_rtx (SImode); | |
2751 emit_move_insn (reg, unspec); | |
2752 emit_move_insn (tmp, label); | |
2753 emit_insn (gen_addsi3 (reg, reg, tmp)); | |
2754 *valuep = emit_library_call_value (get_tls_get_addr (), | |
2755 NULL_RTX, LCT_PURE, /* LCT_CONST? */ | |
2756 Pmode, reg, Pmode); | |
2757 insns = get_insns (); | |
2758 end_sequence (); | |
2759 return insns; | |
2760 } | |
2761 | |
2762 /* Helper function for csky_legitimize_address, to handle the TLS cases. | |
2763 REG is a scratch register and may be null. */ | |
2764 | |
2765 rtx | |
2766 csky_legitimize_tls_address (rtx x, rtx reg) | |
2767 { | |
2768 rtx dest, tp, label, labelno, unspec, ret, eqv, addend, tmp; | |
2769 rtx_insn *insns; | |
2770 unsigned int model = SYMBOL_REF_TLS_MODEL (x); | |
2771 | |
2772 if (!reg) | |
2773 reg = gen_reg_rtx (SImode); | |
2774 | |
2775 switch (model) | |
2776 { | |
2777 case TLS_MODEL_GLOBAL_DYNAMIC: | |
2778 insns = csky_call_tls_get_addr (x, reg, &ret, TLS_GD32); | |
2779 dest = gen_reg_rtx (Pmode); | |
2780 emit_libcall_block (insns, dest, ret, x); | |
2781 return dest; | |
2782 | |
2783 case TLS_MODEL_LOCAL_DYNAMIC: | |
2784 insns = csky_call_tls_get_addr (x, reg, &ret, TLS_LDM32); | |
2785 | |
2786 /* Attach a unique REG_EQUIV, to allow the RTL optimizers to | |
2787 share the LDM result with other LD model accesses. */ | |
2788 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx), UNSPEC_TLS); | |
2789 dest = gen_reg_rtx (Pmode); | |
2790 emit_libcall_block (insns, dest, ret, eqv); | |
2791 | |
2792 /* Load the addend. */ | |
2793 addend = gen_rtx_UNSPEC (Pmode, | |
2794 gen_rtvec (2, x, GEN_INT (TLS_LDO32)), | |
2795 UNSPEC_TLS); | |
2796 addend = force_reg (SImode, addend); | |
2797 return gen_rtx_PLUS (Pmode, dest, addend); | |
2798 | |
2799 case TLS_MODEL_INITIAL_EXEC: | |
2800 labelno = GEN_INT (tls_labelno++); | |
2801 label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_TLS_LABEL); | |
2802 unspec = gen_rtx_UNSPEC (Pmode, | |
2803 gen_rtvec (3, x, GEN_INT (TLS_IE32), label), | |
2804 UNSPEC_TLS); | |
2805 tmp = gen_reg_rtx (SImode); | |
2806 emit_move_insn (reg, unspec); | |
2807 emit_move_insn (tmp, label); | |
2808 emit_insn (gen_addsi3 (reg, reg, tmp)); | |
2809 emit_move_insn (reg, gen_const_mem (Pmode, reg)); | |
2810 tp = gen_rtx_REG (SImode, CSKY_TLS_REGNUM); | |
2811 return gen_rtx_PLUS (Pmode, tp, reg); | |
2812 | |
2813 case TLS_MODEL_LOCAL_EXEC: | |
2814 unspec = gen_rtx_UNSPEC (Pmode, | |
2815 gen_rtvec (2, x, GEN_INT (TLS_LE32)), | |
2816 UNSPEC_TLS); | |
2817 emit_move_insn (reg, unspec); | |
2818 tp = gen_rtx_REG (SImode, CSKY_TLS_REGNUM); | |
2819 return gen_rtx_PLUS (Pmode, tp, reg); | |
2820 | |
2821 default: | |
2822 abort (); | |
2823 } | |
2824 } | |
2825 | |
2826 | |
2827 /* Implement TARGET_LEGITIMIZE_ADDRESS. */ | |
2828 | |
2829 static rtx | |
2830 csky_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED, | |
2831 machine_mode mode) | |
2832 { | |
2833 if (csky_tls_symbol_p (x)) | |
2834 return csky_legitimize_tls_address (x, NULL_RTX); | |
2835 | |
2836 if (GET_CODE (x) == PLUS) | |
2837 { | |
2838 rtx xop0 = XEXP (x, 0); | |
2839 rtx xop1 = XEXP (x, 1); | |
2840 | |
2841 if (is_csky_address_register_rtx_p (xop0, 0) | |
2842 && CONST_INT_P (xop1)) | |
2843 { | |
2844 HOST_WIDE_INT offset = INTVAL (xop1); | |
2845 | |
2846 /* Try to replace ld32 rx,(ry, offset), to addi16 rz, oimm8 | |
2847 and ld16 rx,(rz, new_ld_offset) to avoid emitting a | |
2848 32-bit ld, but this addi has a range limitation. */ | |
2849 if (optimize_size | |
2850 && offset > CSKY_LD16_MAX_OFFSET (mode) | |
2851 && offset <= (CSKY_ADDI16_MAX_IMM | |
2852 + CSKY_LD16_MAX_OFFSET (mode))) | |
2853 { | |
2854 HOST_WIDE_INT new_ld_offset | |
2855 = offset & CSKY_LD16_OFFSET_MASK (mode); | |
2856 | |
2857 xop0 = force_operand (plus_constant (Pmode, xop0, | |
2858 offset - new_ld_offset), | |
2859 NULL_RTX); | |
2860 x = plus_constant (Pmode, xop0, new_ld_offset); | |
2861 } | |
2862 else if (offset < 0 && offset >= (-CSKY_SUBI16_MAX_IMM)) | |
2863 x = force_operand (x, NULL_RTX); | |
2864 else if (offset > CSKY_LD16_MAX_OFFSET (mode) | |
2865 || offset < 0) | |
2866 { | |
2867 /* For the remaining cases, force the constant into a | |
2868 register. */ | |
2869 xop1 = force_reg (SImode, xop1); | |
2870 x = gen_rtx_PLUS (SImode, xop0, xop1); | |
2871 } | |
2872 } | |
2873 | |
2874 /* If the index is store in register, force the | |
2875 base to register. */ | |
2876 if (is_csky_address_register_rtx_p (xop1, 0) | |
2877 && !is_csky_address_register_rtx_p (xop0, 0)) | |
2878 { | |
2879 xop0 = force_operand (xop0, NULL_RTX); | |
2880 x = gen_rtx_PLUS (SImode, xop0, xop1); | |
2881 } | |
2882 } | |
2883 /* Make sure to take full advantage of the pre-indexed addressing mode | |
2884 with absolute addresses which often allows for the base register to | |
2885 be factorized for multiple adjacent memory references, and it might | |
2886 even allows for the mini pool to be avoided entirely. */ | |
2887 else if (CONST_INT_P (x) && optimize > 0) | |
2888 { | |
2889 HOST_WIDE_INT mask, base, index; | |
2890 rtx base_reg; | |
2891 | |
2892 mask = CSKY_LD16_OFFSET_MASK (mode); | |
2893 base = INTVAL (x) & ~mask; | |
2894 index = INTVAL (x) & mask; | |
2895 base_reg = force_reg (SImode, GEN_INT (base)); | |
2896 x = plus_constant (Pmode, base_reg, index); | |
2897 } | |
2898 | |
2899 return x; | |
2900 } | |
2901 | |
2902 | |
2903 /* Return nonzero if INDEX is valid for an address index operand. | |
2904 ck801 use 16 bits ld | |
2905 ck802 use 16 and 32 bits ld | |
2906 others use ld and ldr. */ | |
2907 | |
2908 static int | |
2909 ck801_legitimate_index_p (machine_mode mode, rtx index, | |
2910 int strict_p ATTRIBUTE_UNUSED) | |
2911 { | |
2912 enum rtx_code code = GET_CODE (index); | |
2913 | |
2914 /* When the mode size is larger than 4, we may use two ld instruction | |
2915 to get data, the index and (index+1) should be valid. */ | |
2916 if (GET_MODE_SIZE (mode) >= 8) | |
2917 return (code == CONST_INT | |
2918 && INTVAL (index) < CSKY_LD16_MAX_OFFSET (SImode) | |
2919 && INTVAL (index) >= 0 && (INTVAL (index) & 3) == 0); | |
2920 | |
2921 if (code == CONST_INT && GET_MODE_SIZE (mode) > 0 | |
2922 && INTVAL (index) <= CSKY_LD16_MAX_OFFSET (mode) | |
2923 && INTVAL (index) >= 0) | |
2924 return ((INTVAL (index) % GET_MODE_SIZE (mode)) == 0); | |
2925 | |
2926 return 0; | |
2927 } | |
2928 | |
2929 | |
2930 static int | |
2931 ck802_legitimate_index_p (machine_mode mode, rtx index, | |
2932 int strict_p ATTRIBUTE_UNUSED) | |
2933 { | |
2934 enum rtx_code code = GET_CODE (index); | |
2935 | |
2936 /* When the mode size is larger than 4, we may use two ld instruction | |
2937 to get data, the index and (index+1) should be valid. */ | |
2938 if (GET_MODE_SIZE (mode) >= 8) | |
2939 return (code == CONST_INT | |
2940 && INTVAL (index) < CSKY_LD32_MAX_OFFSET (SImode) | |
2941 && INTVAL (index) >= 0 && (INTVAL (index) & 3) == 0); | |
2942 | |
2943 if (code == CONST_INT && GET_MODE_SIZE (mode) > 0 | |
2944 && INTVAL (index) <= CSKY_LD32_MAX_OFFSET (mode) | |
2945 && INTVAL (index) >= 0) | |
2946 return ((INTVAL (index) % GET_MODE_SIZE (mode)) == 0); | |
2947 | |
2948 return 0; | |
2949 } | |
2950 | |
2951 | |
2952 /* The instruction ldr rz, (rx, ry << i), i can be 0,1,2,3. | |
2953 Check that SHIFT is valid, that the code is MULT, and that | |
2954 the shift is a power of 2. */ | |
2955 | |
2956 static bool | |
2957 is_ldr_shift_p (HOST_WIDE_INT shift, enum rtx_code code) | |
2958 { | |
2959 if (code == ASHIFT) | |
2960 return (shift >= 0 && shift <= 3); | |
2961 else if (code == MULT) | |
2962 return (shift == 1 | |
2963 || shift == 2 | |
2964 || shift == 4 | |
2965 || shift == 8); | |
2966 else | |
2967 return false; | |
2968 } | |
2969 | |
2970 | |
2971 static int | |
2972 ck810_legitimate_index_p (machine_mode mode, rtx index, int strict_p) | |
2973 { | |
2974 enum rtx_code code = GET_CODE (index); | |
2975 | |
2976 if (TARGET_HARD_FLOAT | |
2977 && (mode == SFmode || mode == DFmode)) | |
2978 return (code == CONST_INT && INTVAL (index) < 1024 | |
2979 && INTVAL (index) >= 0 | |
2980 && (INTVAL (index) & 3) == 0); | |
2981 | |
2982 if (code == CONST_INT) | |
2983 { | |
2984 /* When the mode size is larger than 4, we may use two ld instruction | |
2985 to get data, the index and (index+1) should be valid. */ | |
2986 if (GET_MODE_SIZE (mode) >= 8) | |
2987 return (INTVAL (index) < CSKY_LD32_MAX_OFFSET (SImode) | |
2988 && INTVAL (index) >= 0 && (INTVAL (index) & 3) == 0); | |
2989 | |
2990 if (GET_MODE_SIZE (mode) > 0 | |
2991 && INTVAL (index) <= CSKY_LD32_MAX_OFFSET (mode) | |
2992 && INTVAL (index) >= 0) | |
2993 return ((INTVAL (index) % GET_MODE_SIZE (mode)) == 0); | |
2994 } | |
2995 /* Allow ld.w rx, (gb, sym@got) when -fpic specially. */ | |
2996 else if (code == UNSPEC) | |
2997 return (flag_pic == 1 | |
2998 && (XINT (index, 1) == UNSPEC_PIC_SYMBOL_PLT | |
2999 || XINT (index, 1) == UNSPEC_PIC_SYMBOL_GOT)); | |
3000 /* The follow index is for ldr instruction, the ldr cannot | |
3001 load dword data, so the mode size should not be larger than | |
3002 4. */ | |
3003 else if (GET_MODE_SIZE (mode) <= 4) | |
3004 { | |
3005 if (is_csky_address_register_rtx_p (index, strict_p)) | |
3006 return 1; | |
3007 else if (code == MULT || code == ASHIFT) | |
3008 { | |
3009 rtx xiop0 = XEXP (index, 0); | |
3010 rtx xiop1 = XEXP (index, 1); | |
3011 | |
3012 /* FIXME can the xiop1 be the reg and xiop0 be the int when mult? */ | |
3013 return (is_csky_address_register_rtx_p (xiop0, strict_p) | |
3014 && CONST_INT_P (xiop1) | |
3015 && is_ldr_shift_p (INTVAL (xiop1), code)); | |
3016 } | |
3017 } | |
3018 | |
3019 return 0; | |
3020 } | |
3021 | |
3022 | |
3023 static int | |
3024 csky_legitimate_index_p (machine_mode mode, rtx index, int strict_p) | |
3025 { | |
3026 if (CSKY_TARGET_ARCH (CK801)) | |
3027 return ck801_legitimate_index_p (mode, index, strict_p); | |
3028 else if (CSKY_TARGET_ARCH (CK802)) | |
3029 return ck802_legitimate_index_p (mode, index, strict_p); | |
3030 else | |
3031 return ck810_legitimate_index_p (mode, index, strict_p); | |
3032 } | |
3033 | |
3034 | |
3035 /* Implement TARGET_LEGITIMATE_ADDRESS_P. | |
3036 Recognizes RTL expressions that are valid memory addresses for an | |
3037 instruction. The MODE argument is the machine mode for the MEM | |
3038 expression that wants to use this address. | |
3039 | |
3040 It only recognizes address in canonical form. LEGITIMIZE_ADDRESS should | |
3041 convert common non-canonical forms to canonical form so that they will | |
3042 be recognized. */ | |
3043 | |
3044 static bool | |
3045 csky_legitimate_address_p (machine_mode mode, rtx addr, bool strict_p) | |
3046 { | |
3047 enum rtx_code code = GET_CODE (addr); | |
3048 | |
3049 /* Match the RTX form emitted for constant pool references. | |
3050 After reload constants split into minipools will have addresses | |
3051 from a LABEL_REF. */ | |
3052 if (reload_completed | |
3053 && ((code == LABEL_REF) | |
3054 || (code == CONST | |
3055 && GET_CODE (XEXP (addr, 0)) == PLUS | |
3056 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF | |
3057 && CONST_INT_P (XEXP (XEXP (addr, 0), 1))))) | |
3058 return 1; | |
3059 | |
3060 if (is_csky_address_register_rtx_p (addr, strict_p)) | |
3061 return 1; | |
3062 /* It is a pc-relative load, may be generated for constpool. */ | |
3063 else if (GET_CODE (addr) == LABEL_REF) | |
3064 return 1; | |
3065 | |
3066 if (code == PLUS) | |
3067 { | |
3068 rtx xop0 = XEXP (addr, 0); | |
3069 rtx xop1 = XEXP (addr, 1); | |
3070 | |
3071 return ((is_csky_address_register_rtx_p (xop0, strict_p) | |
3072 && csky_legitimate_index_p (mode, xop1, strict_p)) | |
3073 || (is_csky_address_register_rtx_p (xop1, strict_p) | |
3074 && csky_legitimate_index_p (mode, xop0, strict_p))); | |
3075 } | |
3076 | |
3077 return 0; | |
3078 } | |
3079 | |
3080 | |
3081 /* Functions to save and restore machine-specific function data. */ | |
3082 | |
3083 static struct machine_function * | |
3084 csky_init_machine_status (void) | |
3085 { | |
3086 struct machine_function *machine; | |
3087 | |
3088 machine = ggc_cleared_alloc<machine_function> (); | |
3089 | |
3090 #if CSKY_FT_UNKNOWN != 0 | |
3091 machine->func_type = CSKY_FT_UNKNOWN; | |
3092 #endif | |
3093 return machine; | |
3094 } | |
3095 | |
3096 | |
3097 /* Implement INIT_EXPANDERS. */ | |
3098 | |
3099 void | |
3100 csky_init_expanders (void) | |
3101 { | |
3102 /* Arrange to initialize and mark the machine per-function status. */ | |
3103 init_machine_status = csky_init_machine_status; | |
3104 } | |
3105 | |
3106 | |
3107 /* Implement TARGET_CANNOT_COPY_INSN_P. | |
3108 We must not copy any rtx that uses a pc-relative address. */ | |
3109 | |
3110 static bool | |
3111 csky_cannot_copy_insn_p (rtx_insn *insn) | |
3112 { | |
3113 subrtx_iterator::array_type array; | |
3114 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL) | |
3115 { | |
3116 const_rtx x = *iter; | |
3117 if (GET_CODE (x) == UNSPEC | |
3118 && (XINT (x, 1) == UNSPEC_TLS_LABEL | |
3119 || XINT (x, 1) == UNSPEC_PIC_SYMBOL_GOTPC_GRS)) | |
3120 return true; | |
3121 } | |
3122 return false; | |
3123 } | |
3124 | |
3125 | |
3126 /* Extract the parts of an RTL expression that is a valid memory address | |
3127 for an instruction. Return FALSE if it is a invalid memory address. */ | |
3128 | |
3129 struct csky_address | |
3130 { | |
3131 rtx base, index, symbol, label, disp; | |
3132 HOST_WIDE_INT scale; | |
3133 }; | |
3134 | |
3135 static bool | |
3136 decompose_csky_address (rtx addr, struct csky_address *out) | |
3137 { | |
3138 rtx base = NULL_RTX, index = NULL_RTX, disp = NULL_RTX; | |
3139 HOST_WIDE_INT scale = 1; | |
3140 rtx scale_rtx = NULL_RTX; | |
3141 int i; | |
3142 | |
3143 out->base = out->index = out->symbol = out->label = out->disp = NULL_RTX; | |
3144 out->scale = 0; | |
3145 | |
3146 if (REG_P (addr)) | |
3147 { | |
3148 out->base = addr; | |
3149 return true; | |
3150 } | |
3151 | |
3152 if (GET_CODE (addr) == LABEL_REF) | |
3153 { | |
3154 out->label = addr; | |
3155 return true; | |
3156 } | |
3157 | |
3158 if (GET_CODE (addr) == CONST) | |
3159 addr = XEXP (addr, 0); | |
3160 | |
3161 if (GET_CODE (addr) == PLUS) | |
3162 { | |
3163 rtx addends[2], op; | |
3164 | |
3165 addends[0] = XEXP (addr, 0); | |
3166 addends[1] = XEXP (addr, 1); | |
3167 | |
3168 if (GET_CODE (addends[0]) == LABEL_REF && CONST_INT_P (addends[1])) | |
3169 { | |
3170 out->label = addends[0]; | |
3171 out->disp = addends[1]; | |
3172 return true; | |
3173 } | |
3174 | |
3175 if (!REG_P (addends[0])) | |
3176 std::swap (addends[0], addends[1]); | |
3177 | |
3178 for (i = 0; i < 2; ++i) | |
3179 { | |
3180 op = addends[i]; | |
3181 switch (GET_CODE (op)) | |
3182 { | |
3183 case REG: | |
3184 if (!base) | |
3185 base = op; | |
3186 else if (!index) | |
3187 index = op; | |
3188 else | |
3189 return false; | |
3190 break; | |
3191 case CONST_INT: | |
3192 case UNSPEC: | |
3193 if (disp) | |
3194 return false; | |
3195 disp = op; | |
3196 break; | |
3197 case MULT: | |
3198 if (index) | |
3199 return false; | |
3200 index = XEXP (op, 0); | |
3201 scale_rtx = XEXP (op, 1); | |
3202 if (!CONST_INT_P (index) && !CONST_INT_P (scale_rtx)) | |
3203 return false; | |
3204 else if (CONST_INT_P (index)) | |
3205 std::swap (index, scale_rtx); | |
3206 scale = INTVAL (scale_rtx); | |
3207 break; | |
3208 case ASHIFT: | |
3209 if (index) | |
3210 return false; | |
3211 index = XEXP (op, 0); | |
3212 scale_rtx = XEXP (op, 1); | |
3213 if (!CONST_INT_P (scale_rtx)) | |
3214 return false; | |
3215 scale = scale << INTVAL (scale_rtx); | |
3216 break; | |
3217 default: | |
3218 return false; | |
3219 } | |
3220 } | |
3221 } | |
3222 | |
3223 if (!base) | |
3224 return false; | |
3225 | |
3226 out->base = base; | |
3227 out->index = index; | |
3228 out->disp = disp; | |
3229 out->scale = scale; | |
3230 | |
3231 return true; | |
3232 } | |
3233 | |
3234 /* Helper function for the csky_simple_mem_operand predicate. Returns | |
3235 true if OP is an address of the form reg + displacement. */ | |
3236 | |
3237 bool | |
3238 csky_simple_addr_operand_p (rtx op) | |
3239 { | |
3240 struct csky_address addr; | |
3241 | |
3242 if (!decompose_csky_address (op, &addr)) | |
3243 return false; | |
3244 | |
3245 /* FIXME The PIC related code. | |
3246 Check if load the symbol address from got table. */ | |
3247 if (addr.disp && GET_CODE (addr.disp) == UNSPEC) | |
3248 return false; | |
3249 if (!addr.index && !addr.symbol) | |
3250 return true; | |
3251 return false; | |
3252 } | |
3253 | |
3254 | |
3255 /* Print the UNSPEC operand in X to the STREAM. */ | |
3256 | |
3257 static void | |
3258 csky_output_pic_addr_const (FILE *stream, rtx x, int code) | |
3259 { | |
3260 | |
3261 if (GET_CODE (x) != UNSPEC) | |
3262 return; | |
3263 | |
3264 if (UNSPEC_TLS == XINT (x, 1)) | |
3265 { | |
3266 /* FIXME It is not reached */ | |
3267 return; | |
3268 } | |
3269 | |
3270 csky_print_operand (stream, XVECEXP (x, 0, 0), code); | |
3271 | |
3272 switch (XINT (x, 1)) | |
3273 { | |
3274 case UNSPEC_PIC_SYMBOL_GOTOFF: | |
3275 fputs ("@GOTOFF", stream); | |
3276 break; | |
3277 case UNSPEC_PIC_SYMBOL_PLT: | |
3278 fputs ("@PLT", stream); | |
3279 break; | |
3280 case UNSPEC_PIC_SYMBOL_GOT: | |
3281 fputs ("@GOT", stream); | |
3282 break; | |
3283 case UNSPEC_PIC_SYMBOL_GOTPC: | |
3284 fputs ("@GOTPC", stream); | |
3285 break; | |
3286 case UNSPEC_PIC_SYMBOL_BSR: | |
3287 break; | |
3288 default: | |
3289 break; | |
3290 } | |
3291 } | |
3292 | |
3293 | |
3294 /* Output the constpool label according to the rtx expression X. */ | |
3295 | |
3296 static void | |
3297 csky_output_constpool_label (FILE *stream, rtx x) | |
3298 { | |
3299 char buf[15]; | |
3300 | |
3301 gcc_assert (GET_CODE (x) == LABEL_REF); | |
3302 x = XEXP (x, 0); | |
3303 | |
3304 if (GET_CODE (x) == UNSPEC_VOLATILE && XINT (x, 1) == VUNSPEC_POOL_LABEL) | |
3305 { | |
3306 ASM_GENERATE_INTERNAL_LABEL (buf, CSKY_CONSTPOOL_LABEL_PREFIX, | |
3307 INTVAL (XVECEXP (x, 0, 0))); | |
3308 assemble_name (stream, buf); | |
3309 } | |
3310 } | |
3311 | |
3312 | |
3313 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */ | |
3314 | |
3315 static void | |
3316 csky_print_operand_address (FILE *stream, | |
3317 machine_mode mode ATTRIBUTE_UNUSED, | |
3318 rtx x) | |
3319 { | |
3320 | |
3321 struct csky_address addr; | |
3322 | |
3323 decompose_csky_address (x, &addr); | |
3324 | |
3325 if (addr.label && addr.disp && GET_CODE (addr.disp) == CONST_INT) | |
3326 { | |
3327 fprintf (stream, "["); | |
3328 csky_output_constpool_label (stream, addr.label); | |
3329 fprintf (stream, "+%d]", (int) INTVAL (addr.disp)); | |
3330 } | |
3331 else if (addr.label) | |
3332 { | |
3333 fprintf (stream, "["); | |
3334 csky_output_constpool_label (stream, addr.label); | |
3335 fprintf (stream, "]"); | |
3336 } | |
3337 else if (addr.symbol && addr.disp && GET_CODE (addr.disp) == CONST_INT) | |
3338 { | |
3339 fprintf (stream, "["); | |
3340 output_addr_const (stream, addr.symbol); | |
3341 fprintf (stream, "+%d]", (int) INTVAL (addr.disp)); | |
3342 } | |
3343 else if (addr.symbol) | |
3344 { | |
3345 fprintf (stream, "["); | |
3346 output_addr_const (stream, addr.symbol); | |
3347 fprintf (stream, "]"); | |
3348 } | |
3349 else if (addr.disp && GET_CODE (addr.disp) == CONST_INT) | |
3350 fprintf (stream, "(%s, %d)", | |
3351 reg_names[REGNO (addr.base)], (int) INTVAL (addr.disp)); | |
3352 else if (addr.disp && GET_CODE (addr.disp) == UNSPEC) | |
3353 { | |
3354 if (REGNO (addr.base) != CSKY_GB_REGNUM) | |
3355 fprintf (stream, "(%s, ", reg_names[REGNO (addr.base)]); | |
3356 else | |
3357 fprintf (stream, "["); | |
3358 csky_output_pic_addr_const (stream, addr.disp, 0); | |
3359 fprintf (stream, "%s", (REGNO (addr.base) != CSKY_GB_REGNUM) | |
3360 ? ")" : "]"); | |
3361 } | |
3362 else if (addr.index) | |
3363 fprintf (stream, "(%s, %s << %d)", | |
3364 reg_names[REGNO (addr.base)], reg_names[REGNO (addr.index)], | |
3365 exact_log2 ((int) (addr.scale))); | |
3366 else | |
3367 fprintf (stream, "(%s, 0)", reg_names[REGNO (addr.base)]); | |
3368 } | |
3369 | |
3370 | |
3371 /* Implement TARGET_PRINT_OPERAND. | |
3372 Print operand X (an rtx) in assembler syntax to file STREAM | |
3373 according to modifier CODE. | |
3374 | |
3375 'N' print the log2(X+1), mainly used for bmaski | |
3376 'P' print the log2(X) | |
3377 'Q' print the log2(~X) | |
3378 'O' print a decimal number | |
3379 'M' print a decimal number as its negative | |
3380 'R' print the next register or memory location along, i.e. the lsw in | |
3381 a double word value | |
3382 'H' print the high 16 bits of a constant. */ | |
3383 | |
3384 static void | |
3385 csky_print_operand (FILE *stream, rtx x, int code) | |
3386 { | |
3387 switch (code) | |
3388 { | |
3389 case 'N': | |
3390 if ((INTVAL (x) & 0xffffffff) == 0xffffffff) | |
3391 fprintf (stream, "0"); | |
3392 else | |
3393 fprintf (stream, "%d", | |
3394 (int) exact_log2 ((INTVAL (x) & 0xffffffff) + 1) % 32); | |
3395 break; | |
3396 case 'P': | |
3397 fprintf (stream, "%d", | |
3398 (int) exact_log2 (INTVAL (x) & 0xffffffff)); | |
3399 break; | |
3400 case 'Q': | |
3401 fprintf (stream, "%d", | |
3402 (int) exact_log2 (~INTVAL (x) & 0xffffffff)); | |
3403 break; | |
3404 case 'O': | |
3405 fprintf (stream, "%d", (int) INTVAL (x)); | |
3406 break; | |
3407 case 'M': | |
3408 fprintf (stream, "%d", (int) (-INTVAL (x))); | |
3409 break; | |
3410 case 'R': | |
3411 /* Next location along in memory or register. */ | |
3412 switch (GET_CODE (x)) | |
3413 { | |
3414 case REG: | |
3415 fputs (reg_names[REGNO (x) + 1], stream); | |
3416 break; | |
3417 case MEM: | |
3418 csky_print_operand_address | |
3419 (stream, GET_MODE (x), XEXP (adjust_address (x, SImode, 4), 0)); | |
3420 break; | |
3421 default: | |
3422 gcc_unreachable (); | |
3423 } | |
3424 break; | |
3425 case 'H': | |
3426 fprintf (stream, "%ld", (long)((INTVAL (x) & 0xFFFF0000) >> 16)); | |
3427 break; | |
3428 default: | |
3429 switch (GET_CODE (x)) | |
3430 { | |
3431 case REG: | |
3432 fputs (reg_names[REGNO (x)], stream); | |
3433 break; | |
3434 case MEM: | |
3435 output_address (GET_MODE (x), XEXP (x, 0)); | |
3436 break; | |
3437 case UNSPEC: | |
3438 csky_output_pic_addr_const (stream, x, code); | |
3439 break; | |
3440 default: | |
3441 output_addr_const (stream, x); | |
3442 break; | |
3443 } | |
3444 break; | |
3445 } | |
3446 } | |
3447 | |
3448 | |
3449 | |
3450 /* Implement TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS. */ | |
3451 | |
3452 static bool | |
3453 csky_allocate_stack_slots_for_args (void) | |
3454 { | |
3455 /* Naked functions should not allocate stack slots for arguments. */ | |
3456 return !CSKY_FUNCTION_IS_NAKED (get_csky_current_func_type ()); | |
3457 } | |
3458 | |
3459 | |
3460 /* Can we generate a constant with a single instruction, without using | |
3461 lrw? */ | |
3462 | |
3463 static int | |
3464 const_ok_for_cskyv2 (HOST_WIDE_INT value) | |
3465 { | |
3466 /* Try exact power of two. It can be generated by bgeni. */ | |
3467 if (CSKY_CONST_OK_FOR_Ub (value)) | |
3468 return 1; | |
3469 | |
3470 /* Try exact power of two - 1. It can be generated by bmaski. */ | |
3471 if (CSKY_CONST_OK_FOR_Uc (value) && value != -1) | |
3472 return 1; | |
3473 | |
3474 /* Try if it can be generated by movi. */ | |
3475 if (CSKY_CONST_OK_FOR_I (value)) | |
3476 return 1; | |
3477 | |
3478 /* The constant can be generated by movih. | |
3479 Notice that movih is a 32-bit instruction. */ | |
3480 if (CSKY_CONST_OK_FOR_MOVIH (value)) | |
3481 return 1; | |
3482 | |
3483 return 0; | |
3484 } | |
3485 | |
3486 | |
3487 /* Tricks for synthesizing constants from values that can be directly | |
3488 manipulated by machine instructions. */ | |
3489 | |
3490 enum csky_inline_const_type | |
3491 { | |
3492 IC_UNINLINABLE = 0, /* Not inlineable */ | |
3493 IC_SINGLE, /* Single instruction */ | |
3494 IC_APPEND_NOT, /* Single instruction followed by a not */ | |
3495 IC_APPEND_ADDI, /* Single insn followed by an addi */ | |
3496 IC_APPEND_SUBI, /* Single insn followed by a subi */ | |
3497 IC_BGENI_ADDI, /* Single insn(bgeni) followed by an addi */ | |
3498 IC_BGENI_SUBI, /* Single insn(bgeni) followed by a subi */ | |
3499 IC_APPEND_BSETI, /* Single insn followed by bseti */ | |
3500 IC_APPEND_MOVI, /* Single insn followed by movi */ | |
3501 IC_APPEND_BCLRI, /* Single insn followed by bclri */ | |
3502 IC_APPEND_ROTLI, /* Single insn followed by rotli */ | |
3503 IC_APPEND_LSLI, /* Single insn followed by lsli */ | |
3504 IC_APPEND_IXH, /* Single insn followed by ixh */ | |
3505 IC_APPEND_IXW /* Single insn followed by ixw */ | |
3506 }; | |
3507 | |
3508 | |
3509 /* Try tricks to load a constant inline and return the trick number if | |
3510 success, or IC_UNINLINABLE. */ | |
3511 | |
3512 static enum csky_inline_const_type | |
3513 try_csky_constant_tricks (HOST_WIDE_INT value, HOST_WIDE_INT *x, | |
3514 HOST_WIDE_INT *y) | |
3515 { | |
3516 HOST_WIDE_INT i, value_invert; | |
3517 unsigned HOST_WIDE_INT bit, shf, rot, lobits, hibits; | |
3518 | |
3519 value &= 0xffffffff; | |
3520 value_invert = ~value & 0xffffffff; | |
3521 | |
3522 if (const_ok_for_cskyv2 (value)) | |
3523 { | |
3524 *x = value; | |
3525 return IC_SINGLE; | |
3526 } | |
3527 | |
3528 /* Since movih is 32 bits, do not use it here, better code may | |
3529 be generated later. */ | |
3530 if (const_ok_for_cskyv2 (value_invert) | |
3531 && !CSKY_CONST_OK_FOR_MOVIH (value_invert)) | |
3532 { | |
3533 *x = value_invert; | |
3534 return IC_APPEND_NOT; | |
3535 } | |
3536 | |
3537 /* One immediate generate instruction, and one 16-bit subi or addi. */ | |
3538 for (i = 1; i <= 32; i++) | |
3539 { | |
3540 if (const_ok_for_cskyv2 (value - i) | |
3541 && !CSKY_CONST_OK_FOR_MOVIH (value - i)) | |
3542 { | |
3543 *x = value - i; | |
3544 *y = i; | |
3545 return IC_APPEND_ADDI; | |
3546 } | |
3547 | |
3548 if (const_ok_for_cskyv2 (value + i) | |
3549 && !CSKY_CONST_OK_FOR_MOVIH (value - i)) | |
3550 { | |
3551 *x = value + i; | |
3552 *y = i; | |
3553 return IC_APPEND_SUBI; | |
3554 } | |
3555 } | |
3556 | |
3557 /* Generate bgeni + addi. */ | |
3558 if (CSKY_CONST_OK_FOR_Ub (value & 0xfffff000)) | |
3559 { | |
3560 *x = (value & 0xfffff000); | |
3561 *y = (value & 0xfff); | |
3562 return IC_BGENI_ADDI; | |
3563 } | |
3564 | |
3565 /* Generate bgeni + subi. */ | |
3566 lobits = value & 0xfff; | |
3567 hibits = (unsigned HOST_WIDE_INT)(value & 0xfffff000) + (1 << 12); | |
3568 if (exact_log2 (hibits) >= 1 | |
3569 && exact_log2 (hibits) <= 30 | |
3570 && lobits != 0) | |
3571 { | |
3572 *x = hibits; | |
3573 *y = (0x1000 - lobits); | |
3574 return IC_BGENI_SUBI; | |
3575 } | |
3576 | |
3577 /* One immediate generate instruction, and one bseti or bclri. */ | |
3578 bit = 0x80000000ULL; | |
3579 for (i = 0; i <= 31; i++) | |
3580 { | |
3581 if (const_ok_for_cskyv2 (value & ~bit) | |
3582 && !CSKY_CONST_OK_FOR_MOVIH (value & ~bit)) | |
3583 { | |
3584 *y = bit; | |
3585 *x = (value & ~bit); | |
3586 return IC_APPEND_BSETI; | |
3587 } | |
3588 | |
3589 if (const_ok_for_cskyv2 (value | bit) | |
3590 && !CSKY_CONST_OK_FOR_MOVIH (value | bit)) | |
3591 { | |
3592 *y = ~bit & 0xffffffff; | |
3593 *x = value | bit; | |
3594 return IC_APPEND_BCLRI; | |
3595 } | |
3596 | |
3597 bit >>= 1; | |
3598 } | |
3599 | |
3600 /* One immediate generate instruction, and one rotli or lsli. */ | |
3601 shf = value; | |
3602 rot = value; | |
3603 for (i = 1; i < 31; i++) | |
3604 { | |
3605 int c; | |
3606 | |
3607 /* Rotate left. */ | |
3608 c = rot << 31; | |
3609 rot >>= 1; | |
3610 rot &= 0x7FFFFFFF; | |
3611 rot |= c; | |
3612 | |
3613 if (const_ok_for_cskyv2 (rot) && !CSKY_CONST_OK_FOR_MOVIH (rot)) | |
3614 { | |
3615 *y = i; | |
3616 *x = rot; | |
3617 return IC_APPEND_ROTLI; | |
3618 } | |
3619 | |
3620 /* Can't use logical shift when low order bit is one. */ | |
3621 if (shf & 1) | |
3622 shf = 0; | |
3623 else | |
3624 shf >>= 1; | |
3625 | |
3626 if (shf != 0 && const_ok_for_cskyv2 (shf) | |
3627 && !CSKY_CONST_OK_FOR_MOVIH (shf)) | |
3628 { | |
3629 *y = i; | |
3630 *x = shf; | |
3631 return IC_APPEND_LSLI; | |
3632 } | |
3633 } | |
3634 | |
3635 /* One immediate generate instruction, and one ixh. */ | |
3636 if (CSKY_ISA_FEATURE (E2) | |
3637 && (value % 3) == 0 | |
3638 && const_ok_for_cskyv2 (value / 3) | |
3639 && !CSKY_CONST_OK_FOR_MOVIH (value / 3)) | |
3640 { | |
3641 *x = value / 3; | |
3642 return IC_APPEND_IXH; | |
3643 } | |
3644 | |
3645 /* One immediate generate instruction, and one ixw. */ | |
3646 if (CSKY_ISA_FEATURE (E2) | |
3647 && (value % 5) == 0 | |
3648 && const_ok_for_cskyv2 (value / 5) | |
3649 && !CSKY_CONST_OK_FOR_MOVIH (value / 5)) | |
3650 { | |
3651 *x = value / 5; | |
3652 return IC_APPEND_IXW; | |
3653 } | |
3654 | |
3655 /* Generate movih + bseti. */ | |
3656 if (CSKY_CONST_OK_FOR_Ub (value & 0xffff)) | |
3657 { | |
3658 *x = value & 0xffff0000; | |
3659 *y = value & 0xffff; | |
3660 return IC_APPEND_BSETI; | |
3661 } | |
3662 | |
3663 /* Generate movih + not. */ | |
3664 if (CSKY_CONST_OK_FOR_MOVIH (value_invert)) | |
3665 { | |
3666 *x = value_invert; | |
3667 return IC_APPEND_NOT; | |
3668 } | |
3669 | |
3670 /* One movih, and one 16bits addi or subi. */ | |
3671 for (i = 1; i <= 32; i++) | |
3672 { | |
3673 if (CSKY_CONST_OK_FOR_MOVIH (value - i)) | |
3674 { | |
3675 *x = value - i; | |
3676 *y = i; | |
3677 return IC_APPEND_ADDI; | |
3678 } | |
3679 | |
3680 if (CSKY_CONST_OK_FOR_MOVIH (value + i)) | |
3681 { | |
3682 *x = value + i; | |
3683 *y = i; | |
3684 return IC_APPEND_SUBI; | |
3685 } | |
3686 } | |
3687 | |
3688 /* One movih, and one bseti or bclri. */ | |
3689 bit = 0x80000000ULL; | |
3690 for (i = 0; i <= 31; i++) | |
3691 { | |
3692 if (CSKY_CONST_OK_FOR_MOVIH (value & ~bit)) | |
3693 { | |
3694 *y = bit; | |
3695 *x = value & ~bit; | |
3696 return IC_APPEND_BSETI; | |
3697 } | |
3698 | |
3699 if (CSKY_CONST_OK_FOR_MOVIH (value | bit)) | |
3700 { | |
3701 *y = ~bit & 0xffffffff; | |
3702 *x = value | bit; | |
3703 return IC_APPEND_BCLRI; | |
3704 } | |
3705 | |
3706 bit >>= 1; | |
3707 } | |
3708 | |
3709 /* One movih, and one rotli or lsli. */ | |
3710 shf = value; | |
3711 rot = value; | |
3712 for (i = 1; i < 31; i++) | |
3713 { | |
3714 int c; | |
3715 | |
3716 /* Rotate left. */ | |
3717 c = rot << 31; | |
3718 rot >>= 1; | |
3719 rot &= 0x7FFFFFFF; | |
3720 rot |= c; | |
3721 | |
3722 if (CSKY_CONST_OK_FOR_MOVIH (rot)) | |
3723 { | |
3724 *y = i; | |
3725 *x = rot; | |
3726 return IC_APPEND_ROTLI; | |
3727 } | |
3728 | |
3729 /* Can't use logical shift when low order bit is one. */ | |
3730 if (shf & 1) | |
3731 shf = 0; | |
3732 else | |
3733 shf >>= 1; | |
3734 | |
3735 if (shf != 0 && CSKY_CONST_OK_FOR_MOVIH (shf)) | |
3736 { | |
3737 *y = i; | |
3738 *x = shf; | |
3739 return IC_APPEND_LSLI; | |
3740 } | |
3741 } | |
3742 | |
3743 return IC_UNINLINABLE; | |
3744 } | |
3745 | |
3746 | |
3747 /* Actually output a constant using a trick. | |
3748 FIXME: I think this would be better handled by a splitter than at the | |
3749 asm output level. */ | |
3750 | |
3751 static const char * | |
3752 csky_output_inline_const (machine_mode mode, rtx operands[]) | |
3753 { | |
3754 HOST_WIDE_INT x = 0, y = 0; | |
3755 enum csky_inline_const_type trick_type; | |
3756 rtx out_operands[3]; | |
3757 char buf[256]; | |
3758 char load_op[128]; | |
3759 const char *dst_fmt; | |
3760 HOST_WIDE_INT value = INTVAL (operands[1]); | |
3761 int ivalue = (int) value; | |
3762 unsigned int uvalue = (unsigned int) value; | |
3763 | |
3764 trick_type = try_csky_constant_tricks (value, &x, &y); | |
3765 /* lrw's are handled separately: Large inlinable constants never get | |
3766 turned into lrw's. Our caller uses try_csky_constant_tricks to back | |
3767 off to an lrw rather than calling this routine. */ | |
3768 gcc_assert (trick_type != IC_UNINLINABLE); | |
3769 | |
3770 /* Operands: 0 = dst, 1 = load immedate., 2 = adjust immedate. */ | |
3771 out_operands[0] = operands[0]; | |
3772 out_operands[1] = GEN_INT (x); | |
3773 if (trick_type != IC_SINGLE && trick_type != IC_APPEND_NOT) | |
3774 out_operands[2] = GEN_INT (y); | |
3775 | |
3776 /* Select dst format based on mode. */ | |
3777 if (mode == DImode && TARGET_BIG_ENDIAN) | |
3778 dst_fmt = "%R0"; | |
3779 else | |
3780 dst_fmt = "%0"; | |
3781 | |
3782 /* Try movi16: 0~31,movi32: 0~65535. */ | |
3783 if (CSKY_CONST_OK_FOR_I (x)) | |
3784 sprintf (load_op, "movi\t%s, %%1", dst_fmt); | |
3785 /* Try exact power of two - 1. */ | |
3786 else if (CSKY_CONST_OK_FOR_Uc (x)) | |
3787 sprintf (load_op, "bmaski\t%s, %%N1", dst_fmt); | |
3788 /* Try movih. */ | |
3789 else if (CSKY_CONST_OK_FOR_MOVIH (x)) | |
3790 sprintf (load_op, "movih\t%s, %%H1", dst_fmt); | |
3791 else | |
3792 { | |
3793 sprintf (load_op, "BADMOVI-inline_const %s, %%1", dst_fmt); | |
3794 gcc_unreachable (); | |
3795 } | |
3796 | |
3797 switch (trick_type) | |
3798 { | |
3799 case IC_SINGLE: | |
3800 strcpy (buf, load_op); | |
3801 break; | |
3802 /* Add instruction 'not'. */ | |
3803 case IC_APPEND_NOT: | |
3804 sprintf (buf, "%s\n\tnot\t%s, %s\t// %d 0x%x", load_op, dst_fmt, | |
3805 dst_fmt, ivalue, uvalue); | |
3806 break; | |
3807 /* Add instruction 'addi'. */ | |
3808 case IC_APPEND_ADDI: | |
3809 sprintf (buf, "%s\n\taddi\t%s, %s, %%2\t// %d 0x%x", load_op, | |
3810 dst_fmt, dst_fmt, ivalue, uvalue); | |
3811 break; | |
3812 /* Add instruction 'subi'. */ | |
3813 case IC_APPEND_SUBI: | |
3814 sprintf (buf, "%s\n\tsubi\t%s, %s, %%2\t// %d 0x%x", load_op, | |
3815 dst_fmt, dst_fmt, ivalue, uvalue); | |
3816 break; | |
3817 /* Add instruction 'addi', the last instruction is bgeni. */ | |
3818 case IC_BGENI_ADDI: | |
3819 sprintf (buf, "%s\n\taddi\t%s, %s, %%2\t// %d 0x%x", load_op, | |
3820 dst_fmt, dst_fmt, ivalue, uvalue); | |
3821 break; | |
3822 /* Add instruction 'subi', the last instruction is bgeni. */ | |
3823 case IC_BGENI_SUBI: | |
3824 sprintf (buf, "%s\n\tsubi\t%s, %s, %%2\t// %d 0x%x", load_op, | |
3825 dst_fmt, dst_fmt, ivalue, uvalue); | |
3826 break; | |
3827 /* Add instruction 'bseti'. */ | |
3828 case IC_APPEND_BSETI: | |
3829 sprintf (buf, "%s\n\tbseti\t%s, %s, %%P2\t// %d 0x%x", load_op, | |
3830 dst_fmt, dst_fmt, ivalue, uvalue); | |
3831 break; | |
3832 /* Add instruction 'movi'. */ | |
3833 case IC_APPEND_MOVI: | |
3834 sprintf (buf, "%s\n\tmovi\t%s, %%2\t// %d 0x%x", load_op, dst_fmt, | |
3835 ivalue, uvalue); | |
3836 break; | |
3837 /* Add instruction 'bclri'. */ | |
3838 case IC_APPEND_BCLRI: | |
3839 sprintf (buf, "%s\n\tbclri\t%s, %s, %%Q2\t// %d 0x%x", load_op, | |
3840 dst_fmt, dst_fmt, ivalue, uvalue); | |
3841 break; | |
3842 /* Add instruction 'rotli'. */ | |
3843 case IC_APPEND_ROTLI: | |
3844 sprintf (buf, "%s\n\trotli\t%s, %s, %%2\t// %d 0x%x", load_op, | |
3845 dst_fmt, dst_fmt, ivalue, uvalue); | |
3846 break; | |
3847 /* Add instruction 'lsli'. */ | |
3848 case IC_APPEND_LSLI: | |
3849 sprintf (buf, "%s\n\tlsli\t%s, %s, %%2\t// %d 0x%x", load_op, | |
3850 dst_fmt, dst_fmt, ivalue, uvalue); | |
3851 break; | |
3852 /* Add instruction 'ixh'. */ | |
3853 case IC_APPEND_IXH: | |
3854 sprintf (buf, "%s\n\tixh\t%s, %s, %s\t// %d 0x%x", load_op, | |
3855 dst_fmt, dst_fmt, dst_fmt, ivalue, uvalue); | |
3856 break; | |
3857 /* Add instruction 'ixw'. */ | |
3858 case IC_APPEND_IXW: | |
3859 sprintf (buf, "%s\n\tixw\t%s, %s, %s\t// %d 0x%x", load_op, | |
3860 dst_fmt, dst_fmt, dst_fmt, ivalue, uvalue); | |
3861 break; | |
3862 default: | |
3863 return ""; | |
3864 } | |
3865 | |
3866 output_asm_insn (buf, out_operands); | |
3867 | |
3868 return ""; | |
3869 } | |
3870 | |
3871 /* This is a helper function for the Uo constraint for movsi patterns. */ | |
3872 | |
3873 bool | |
3874 csky_inlinable_constant (HOST_WIDE_INT value) | |
3875 { | |
3876 HOST_WIDE_INT x, y; | |
3877 return (!(CSKY_TARGET_ARCH (CK802) || CSKY_TARGET_ARCH (CK801)) | |
3878 && try_csky_constant_tricks (value, &x, &y)); | |
3879 } | |
3880 | |
3881 | |
3882 /* Return true if the constant VAL can be expressed by an 8-bit constant | |
3883 with a shift value, filling in *BASE and *SHIFT. */ | |
3884 | |
3885 bool | |
3886 csky_shifted_imm8_constant (unsigned HOST_WIDE_INT val, | |
3887 unsigned int *base, unsigned int *shift) | |
3888 { | |
3889 unsigned HOST_WIDE_INT mask = 0xff; | |
3890 int i; | |
3891 val = val & (unsigned HOST_WIDE_INT) 0xffffffffu; | |
3892 if (val == 0) | |
3893 return 0; | |
3894 | |
3895 for (i = 0; i < 25; i++) | |
3896 if ((val & (mask << i)) == val) | |
3897 { | |
3898 if (base) | |
3899 *base = (unsigned int) (val >> i); | |
3900 if (shift) | |
3901 *shift = (unsigned int) i; | |
3902 return true; | |
3903 } | |
3904 | |
3905 return false; | |
3906 } | |
3907 | |
3908 | |
3909 /* Output a move of a word or less value. */ | |
3910 | |
3911 const char * | |
3912 csky_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[], | |
3913 machine_mode mode ATTRIBUTE_UNUSED) | |
3914 { | |
3915 rtx dst = operands[0]; | |
3916 rtx src = operands[1]; | |
3917 struct csky_address op0, op1; | |
3918 | |
3919 if (REG_P (dst)) | |
3920 { | |
3921 /* The situation mov reg to reg. */ | |
3922 if (REG_P (src)) | |
3923 { | |
3924 int dstreg = REGNO (dst); | |
3925 int srcreg = REGNO (src); | |
3926 | |
3927 /* hilo registers exchange their places, | |
3928 and their order of Dimode as same as other | |
3929 general registers in LITTLE_ENDIAN mode. */ | |
3930 if (TARGET_BIG_ENDIAN) | |
3931 { | |
3932 if (dstreg == CSKY_HI_REGNUM) | |
3933 return "mthi\t%1"; | |
3934 else if (dstreg == CSKY_LO_REGNUM) | |
3935 return "mtlo\t%1"; | |
3936 else if (srcreg == CSKY_HI_REGNUM) | |
3937 return "mfhi\t%0"; | |
3938 else if (srcreg == CSKY_LO_REGNUM) | |
3939 return "mflo\t%0"; | |
3940 } | |
3941 else | |
3942 { | |
3943 if (dstreg == CSKY_HI_REGNUM) | |
3944 return "mtlo\t%1"; | |
3945 else if (dstreg == CSKY_LO_REGNUM) | |
3946 return "mthi\t%1"; | |
3947 else if (srcreg == CSKY_HI_REGNUM) | |
3948 return "mflo\t%0"; | |
3949 else if (srcreg == CSKY_LO_REGNUM) | |
3950 return "mfhi\t%0"; | |
3951 } | |
3952 | |
3953 if (CSKY_VREG_P (dstreg) && CSKY_VREG_P (srcreg)) | |
3954 return "fmovs\t%0, %1"; | |
3955 if (CSKY_VREG_P (dstreg)) | |
3956 return "fmtvrl\t%0, %1"; | |
3957 if (CSKY_VREG_P (srcreg)) | |
3958 return "fmfvrl\t%0, %1"; | |
3959 | |
3960 if (REGNO (src) == CSKY_CC_REGNUM) | |
3961 return "mvc\t%0"; | |
3962 else | |
3963 return "mov\t%0, %1"; | |
3964 } | |
3965 /* The situation mov memory to reg. */ | |
3966 else if (GET_CODE (src) == MEM) | |
3967 { | |
3968 decompose_csky_address (XEXP (src, 0), &op1); | |
3969 | |
3970 if (op1.index) | |
3971 switch (GET_MODE (src)) | |
3972 { | |
3973 case E_HImode: | |
3974 return "ldr.h\t%0, %1"; | |
3975 case E_QImode: | |
3976 return "ldr.b\t%0, %1"; | |
3977 case E_SImode: | |
3978 case E_SFmode: | |
3979 if (CSKY_VREG_P (REGNO (dst))) | |
3980 return "fldrs\t%0, %1"; | |
3981 else | |
3982 return "ldr.w\t%0, %1"; | |
3983 default: | |
3984 gcc_unreachable (); | |
3985 } | |
3986 /* Generate lrw rx, [LABEL]. This happens when the compiler | |
3987 generates constant pool references and uses lrw to get the | |
3988 constant into memory. */ | |
3989 else if (op1.label) | |
3990 return "lrw\t%0, %1"; | |
3991 /* Generate lrs.w rx, [symbol@GOT/PLT]. */ | |
3992 else if (flag_pic == 1 && op1.disp && GET_CODE (op1.disp) == UNSPEC) | |
3993 return "lrs.w\t%0, %1"; | |
3994 else | |
3995 switch (GET_MODE (src)) | |
3996 { | |
3997 case E_HImode: | |
3998 return "ld.h\t%0, %1"; | |
3999 case E_QImode: | |
4000 return "ld.b\t%0, %1"; | |
4001 case E_SFmode: | |
4002 case E_SImode: | |
4003 if (CSKY_VREG_P (REGNO (dst))) | |
4004 return "flds\t%0, %1"; | |
4005 else | |
4006 return "ld.w\t%0, %1"; | |
4007 default: | |
4008 gcc_unreachable (); | |
4009 } | |
4010 } | |
4011 /* The situation mov integer to reg. */ | |
4012 else if (GET_CODE (src) == CONST_INT || | |
4013 (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode)) | |
4014 { | |
4015 HOST_WIDE_INT x, y; | |
4016 const REAL_VALUE_TYPE *d; | |
4017 long l; | |
4018 | |
4019 if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode) | |
4020 { | |
4021 d = CONST_DOUBLE_REAL_VALUE (src); | |
4022 REAL_VALUE_TO_TARGET_SINGLE (*d, l); | |
4023 operands[1] = GEN_INT (l); | |
4024 src = operands[1]; | |
4025 } | |
4026 | |
4027 if (try_csky_constant_tricks (INTVAL (src), &x, &y)) | |
4028 return csky_output_inline_const (SImode, operands); | |
4029 /* Return '#' to split it. */ | |
4030 else if (CSKY_CONST_OK_FOR_T (INTVAL (src))) | |
4031 return "#"; | |
4032 else | |
4033 return "lrw\t%0, %x1\t"; | |
4034 } | |
4035 else if (TARGET_ANCHOR && GET_CODE (src) == SYMBOL_REF) | |
4036 { | |
4037 if (SYMBOL_REF_FUNCTION_P (src)) | |
4038 return "lrw\t%0, %1@BTEXT"; | |
4039 else | |
4040 return "lrw\t%0, %1@BDATA"; | |
4041 } | |
4042 else if (GET_CODE (src) == UNSPEC | |
4043 && XINT (src, 1) == UNSPEC_PIC_SYMBOL_GRS) | |
4044 return "grs\t%0, %1"; | |
4045 else | |
4046 return "lrw\t%0, %1"; | |
4047 } | |
4048 else if (GET_CODE (dst) == MEM) | |
4049 { | |
4050 decompose_csky_address (XEXP (dst, 0), &op0); | |
4051 | |
4052 if (op0.index) | |
4053 switch (GET_MODE (src)) | |
4054 { | |
4055 case E_HImode: | |
4056 return "str.h\t%1, %0"; | |
4057 case E_QImode: | |
4058 return "str.b\t%1, %0"; | |
4059 case E_SFmode: | |
4060 case E_SImode: | |
4061 if (CSKY_VREG_P (REGNO (src))) | |
4062 return "fstrs\t%1, %0"; | |
4063 else | |
4064 return "str.w\t%1, %0"; | |
4065 default: | |
4066 gcc_unreachable (); | |
4067 } | |
4068 else | |
4069 switch (GET_MODE (dst)) | |
4070 { | |
4071 case E_HImode: | |
4072 return "st.h\t%1, %0"; | |
4073 case E_QImode: | |
4074 return "st.b\t%1, %0"; | |
4075 case E_SImode: | |
4076 case E_SFmode: | |
4077 if (CSKY_VREG_P (REGNO (src))) | |
4078 return "fsts\t%1, %0"; | |
4079 else | |
4080 return "st.w\t%1, %0"; | |
4081 default: | |
4082 gcc_unreachable (); | |
4083 } | |
4084 } | |
4085 | |
4086 gcc_unreachable (); | |
4087 } | |
4088 | |
4089 | |
4090 /* Output a move of a word or less value. Specific for ck801. */ | |
4091 | |
4092 const char * | |
4093 csky_output_ck801_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[], | |
4094 machine_mode mode ATTRIBUTE_UNUSED) | |
4095 { | |
4096 rtx dst = operands[0]; | |
4097 rtx src = operands[1]; | |
4098 struct csky_address op1; | |
4099 | |
4100 if (REG_P (dst)) | |
4101 { | |
4102 if (REG_P (src)) | |
4103 return "mov\t%0, %1"; | |
4104 else if (GET_CODE (src) == MEM) | |
4105 { | |
4106 decompose_csky_address (XEXP (src, 0), &op1); | |
4107 | |
4108 /* Generate lrw rx, [LABEL]. This happens when the compiler | |
4109 generates constant pool references and uses lrw to get the | |
4110 constant in memory. */ | |
4111 if (op1.label) | |
4112 return "lrw\t%0, %1"; | |
4113 else | |
4114 switch (GET_MODE (src)) | |
4115 { | |
4116 case E_HImode: | |
4117 return "ld.h\t%0, %1"; | |
4118 case E_QImode: | |
4119 return "ld.b\t%0, %1"; | |
4120 case E_SFmode: | |
4121 case E_SImode: | |
4122 return "ld.w\t%0, %1"; | |
4123 default: | |
4124 gcc_unreachable (); | |
4125 } | |
4126 } | |
4127 else if (GET_CODE (src) == CONST_INT) | |
4128 { | |
4129 if (REGNO (dst) > 7) | |
4130 return "lrw\t%0, %x1\t"; | |
4131 else if (CSKY_CONST_OK_FOR_N (INTVAL (src) + 1)) | |
4132 return "movi\t%0, %1"; | |
4133 /* Return '#' to split it. */ | |
4134 else if (CSKY_CONST_OK_FOR_T (INTVAL (src))) | |
4135 return "#"; | |
4136 else if (csky_shifted_imm8_constant (INTVAL (src), NULL, NULL)) | |
4137 return "#"; | |
4138 else | |
4139 return "lrw\t%0, %x1\t"; | |
4140 } | |
4141 else if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode) | |
4142 { | |
4143 const REAL_VALUE_TYPE *d; | |
4144 long l; | |
4145 | |
4146 d = CONST_DOUBLE_REAL_VALUE (src); | |
4147 REAL_VALUE_TO_TARGET_SINGLE (*d, l); | |
4148 operands[1] = GEN_INT (l); | |
4149 src = operands[1]; | |
4150 | |
4151 if (CSKY_CONST_OK_FOR_N (INTVAL (src) + 1)) | |
4152 return "movi\t%0, %1"; | |
4153 else | |
4154 return "lrw\t%0, %x1\t"; | |
4155 } | |
4156 else if (TARGET_ANCHOR && GET_CODE (src) == SYMBOL_REF) | |
4157 { | |
4158 if (SYMBOL_REF_FUNCTION_P (src)) | |
4159 return "lrw\t%0, %1@BTEXT"; | |
4160 else | |
4161 return "lrw\t%0, %1@BDATA"; | |
4162 } | |
4163 else | |
4164 return "lrw\t%0, %1"; | |
4165 } | |
4166 else if (GET_CODE (dst) == MEM) | |
4167 switch (GET_MODE (dst)) | |
4168 { | |
4169 case E_HImode: | |
4170 return "st.h\t%1, %0"; | |
4171 case E_QImode: | |
4172 return "st.b\t%1, %0"; | |
4173 case E_SImode: | |
4174 case E_SFmode: | |
4175 return "st.w\t%1, %0"; | |
4176 default: | |
4177 gcc_unreachable (); | |
4178 } | |
4179 | |
4180 gcc_unreachable (); | |
4181 } | |
4182 | |
4183 | |
4184 /* Return a sequence of instructions to perform DI or DF move. | |
4185 Since the CSKY cannot move a DI or DF in one instruction, we have | |
4186 to take care when we see overlapping source and dest registers. */ | |
4187 | |
4188 const char * | |
4189 csky_output_movedouble (rtx operands[], | |
4190 machine_mode mode ATTRIBUTE_UNUSED) | |
4191 { | |
4192 rtx dst = operands[0]; | |
4193 rtx src = operands[1]; | |
4194 | |
4195 if (REG_P (dst)) | |
4196 { | |
4197 if (REG_P (src)) | |
4198 { | |
4199 int dstreg = REGNO (dst); | |
4200 int srcreg = REGNO (src); | |
4201 | |
4202 if (CSKY_HILO_REG_P (srcreg)) | |
4203 { | |
4204 if (TARGET_BIG_ENDIAN) | |
4205 return "mfhi\t%0\n\tmflo\t%R0"; | |
4206 else | |
4207 return "mfhi\t%R0\n\tmflo\t%0"; | |
4208 } | |
4209 else if (CSKY_HILO_REG_P (dstreg)) | |
4210 { | |
4211 if (TARGET_BIG_ENDIAN) | |
4212 return "mthi\t%1\n\tmtlo\t%R1"; | |
4213 else | |
4214 return "mthi\t%R1\n\tmtlo\t%1"; | |
4215 } | |
4216 else if (CSKY_VREG_P (srcreg) && CSKY_VREG_P (dstreg)) | |
4217 return "fmovd\t%0, %1"; | |
4218 else if (CSKY_VREG_P (srcreg)) | |
4219 { | |
4220 /* Since the vector registers in fpuv2_soft processors | |
4221 like ck803f are 32 bits wide, just one insn is needed | |
4222 to complete the move operation. */ | |
4223 if (TARGET_SOFT_FPU) | |
4224 return "fmfvrl\t%0, %1"; | |
4225 else if (TARGET_BIG_ENDIAN) | |
4226 return "fmfvrh\t%0, %1\n\tfmfvrl\t%R0, %1"; | |
4227 else | |
4228 return "fmfvrh\t%R0, %1\n\tfmfvrl\t%0, %1"; | |
4229 } | |
4230 else if (CSKY_VREG_P (dstreg)) | |
4231 { | |
4232 if (TARGET_SOFT_FPU) | |
4233 return "fmtvrl\t%0, %1"; | |
4234 else if (TARGET_BIG_ENDIAN) | |
4235 return "fmtvrh\t%0, %1\n\tfmtvrl\t%0, %R1"; | |
4236 else | |
4237 return "fmtvrh\t%0, %R1\n\tfmtvrl\t%0, %1"; | |
4238 } | |
4239 | |
4240 /* Ensure the second source not overwritten. */ | |
4241 if (srcreg + 1 == dstreg) | |
4242 return "mov\t%R0, %R1\n\tmov\t%0, %1"; | |
4243 else | |
4244 return "mov\t%0, %1\n\tmov\t%R0, %R1"; | |
4245 } | |
4246 else if (GET_CODE (src) == MEM) | |
4247 { | |
4248 rtx memexp = XEXP (src, 0); | |
4249 int dstreg = REGNO (dst); | |
4250 int basereg = -1; | |
4251 struct csky_address op0; | |
4252 | |
4253 decompose_csky_address (XEXP (src, 0), &op0); | |
4254 | |
4255 if (GET_CODE (memexp) == LABEL_REF | |
4256 || (GET_CODE (memexp) == CONST | |
4257 && GET_CODE (XEXP (memexp, 0)) == PLUS | |
4258 && GET_CODE (XEXP (XEXP (memexp, 0), 0)) == LABEL_REF)) | |
4259 return "lrw\t%0, [%1]\n\tlrw\t%R0, [%R1]"; | |
4260 else if (GET_CODE (memexp) == REG) | |
4261 basereg = REGNO (memexp); | |
4262 else if (GET_CODE (memexp) == PLUS) | |
4263 { | |
4264 if (GET_CODE (XEXP (memexp, 0)) == REG) | |
4265 basereg = REGNO (XEXP (memexp, 0)); | |
4266 else if (GET_CODE (XEXP (memexp, 1)) == REG) | |
4267 basereg = REGNO (XEXP (memexp, 1)); | |
4268 else | |
4269 gcc_unreachable (); | |
4270 } | |
4271 else | |
4272 gcc_unreachable (); | |
4273 | |
4274 | |
4275 /* When FPUV2. */ | |
4276 if (CSKY_VREG_P (dstreg)) | |
4277 { | |
4278 if (op0.index) | |
4279 return "fldrd\t%0, %1"; | |
4280 else | |
4281 return "fldd\t%0, %1"; | |
4282 } | |
4283 /* FIXME length attribute is wrong here. */ | |
4284 if (dstreg == basereg) | |
4285 /* Just load them in reverse order. */ | |
4286 return "ld.w\t%R0, %R1\n\tld.w\t%0, %1"; | |
4287 else | |
4288 return "ld.w\t%0, %1\n\tld.w\t%R0, %R1"; | |
4289 } | |
4290 else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE) | |
4291 { | |
4292 split_double (src, operands + 2, operands + 3); | |
4293 | |
4294 if (CSKY_CONST_OK_FOR_I (INTVAL (operands[2]))) | |
4295 output_asm_insn ("movi\t%0, %2", operands); | |
4296 else if (CSKY_CONST_OK_FOR_Uc (INTVAL (operands[2]))) | |
4297 output_asm_insn ("bmaski\t%0, %N2", operands); | |
4298 else if (CSKY_CONST_OK_FOR_Ub (INTVAL (operands[2]))) | |
4299 output_asm_insn ("bgeni\t%0, %P2", operands); | |
4300 else | |
4301 output_asm_insn ("lrw\t%0, %2", operands); | |
4302 | |
4303 if (CSKY_CONST_OK_FOR_I (INTVAL (operands[3]))) | |
4304 output_asm_insn ("movi\t%R0, %3", operands); | |
4305 else if (CSKY_CONST_OK_FOR_Uc (INTVAL (operands[3]))) | |
4306 output_asm_insn ("bmaski\t%R0, %N3", operands); | |
4307 | |
4308 else if (CSKY_CONST_OK_FOR_Ub (INTVAL (operands[3]))) | |
4309 output_asm_insn ("bgeni\t%R0, %P3", operands); | |
4310 else | |
4311 output_asm_insn ("lrw\t%R0, %3", operands); | |
4312 | |
4313 return ""; | |
4314 } | |
4315 else | |
4316 gcc_unreachable (); | |
4317 } | |
4318 else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG) | |
4319 { | |
4320 rtx memexp = XEXP (dst, 0); | |
4321 int srcreg = REGNO (src); | |
4322 int basereg = -1; | |
4323 struct csky_address op0; | |
4324 | |
4325 decompose_csky_address (XEXP (dst, 0), &op0); | |
4326 | |
4327 if (GET_CODE (memexp) == REG) | |
4328 basereg = REGNO (memexp); | |
4329 else if (GET_CODE (memexp) == PLUS) | |
4330 { | |
4331 if (GET_CODE (XEXP (memexp, 0)) == REG) | |
4332 basereg = REGNO (XEXP (memexp, 0)); | |
4333 else if (GET_CODE (XEXP (memexp, 1)) == REG) | |
4334 basereg = REGNO (XEXP (memexp, 1)); | |
4335 else | |
4336 gcc_unreachable (); | |
4337 } | |
4338 else | |
4339 gcc_unreachable (); | |
4340 | |
4341 /* When FPUV2. */ | |
4342 if (CSKY_VREG_P (srcreg)) | |
4343 { | |
4344 if (op0.index) | |
4345 return "fstrd\t%1, %0"; | |
4346 else | |
4347 return "fstd\t%1, %0"; | |
4348 } | |
4349 /* FIXME length attribute is wrong here. */ | |
4350 if (srcreg == basereg) | |
4351 /* Just load them in reverse order. */ | |
4352 return "st.w\t%R1, %R0\n\tst.w\t%1, %0"; | |
4353 else | |
4354 return "st.w\t%1, %0\n\tst.w\t%R1, %R0"; | |
4355 } | |
4356 else | |
4357 gcc_unreachable (); | |
4358 } | |
4359 | |
4360 | |
4361 const char * | |
4362 csky_output_ck801_movedouble (rtx operands[], | |
4363 machine_mode mode ATTRIBUTE_UNUSED) | |
4364 { | |
4365 rtx dst = operands[0]; | |
4366 rtx src = operands[1]; | |
4367 | |
4368 if (REG_P (dst)) | |
4369 { | |
4370 if (REG_P (src)) | |
4371 { | |
4372 int dstreg = REGNO (dst); | |
4373 int srcreg = REGNO (src); | |
4374 | |
4375 /* Ensure the second source not overwritten. */ | |
4376 if (srcreg + 1 == dstreg) | |
4377 return "mov\t%R0, %R1\n\tmov\t%0, %1"; | |
4378 else | |
4379 return "mov\t%0, %1\n\tmov\t%R0, %R1"; | |
4380 } | |
4381 else if (GET_CODE (src) == MEM) | |
4382 { | |
4383 rtx memexp = XEXP (src, 0); | |
4384 int dstreg = REGNO (dst); | |
4385 int basereg = -1; | |
4386 struct csky_address op0; | |
4387 | |
4388 decompose_csky_address (XEXP (src, 0), &op0); | |
4389 | |
4390 if (GET_CODE (memexp) == LABEL_REF | |
4391 || (GET_CODE (memexp) == CONST | |
4392 && GET_CODE (XEXP (memexp, 0)) == PLUS | |
4393 && GET_CODE (XEXP (XEXP (memexp, 0), 0)) == LABEL_REF)) | |
4394 return "lrw\t%0, [%1]\n\tlrw\t%R0, [%R1]"; | |
4395 else if (GET_CODE (memexp) == REG) | |
4396 basereg = REGNO (memexp); | |
4397 else if (GET_CODE (memexp) == PLUS) | |
4398 { | |
4399 if (GET_CODE (XEXP (memexp, 0)) == REG) | |
4400 basereg = REGNO (XEXP (memexp, 0)); | |
4401 else if (GET_CODE (XEXP (memexp, 1)) == REG) | |
4402 basereg = REGNO (XEXP (memexp, 1)); | |
4403 else | |
4404 gcc_unreachable (); | |
4405 } | |
4406 else | |
4407 gcc_unreachable (); | |
4408 | |
4409 /* FIXME length attribute is wrong here. */ | |
4410 if (dstreg == basereg) | |
4411 /* Just load them in reverse order. */ | |
4412 return "ld.w\t%R0, %R1\n\tld.w\t%0, %1"; | |
4413 else | |
4414 return "ld.w\t%0, %1\n\tld.w\t%R0, %R1"; | |
4415 } | |
4416 else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE) | |
4417 { | |
4418 split_double (src, operands + 2, operands + 3); | |
4419 | |
4420 if (REGNO (dst) <= 7 | |
4421 && CSKY_CONST_OK_FOR_N (INTVAL (operands[2]) + 1)) | |
4422 output_asm_insn ("movi\t%0, %2", operands); | |
4423 else | |
4424 output_asm_insn ("lrw\t%0, %2", operands); | |
4425 | |
4426 | |
4427 if (REGNO (dst) <= 6 | |
4428 && CSKY_CONST_OK_FOR_N (INTVAL (operands[3]) + 1)) | |
4429 output_asm_insn ("movi\t%R0, %3", operands); | |
4430 else | |
4431 output_asm_insn ("lrw\t%R0, %3", operands); | |
4432 | |
4433 return ""; | |
4434 | |
4435 | |
4436 } | |
4437 else | |
4438 gcc_unreachable (); | |
4439 } | |
4440 else if (GET_CODE (dst) == MEM && GET_CODE (src) == REG) | |
4441 { | |
4442 rtx memexp = XEXP (dst, 0); | |
4443 int srcreg = REGNO (src); | |
4444 int basereg = -1; | |
4445 struct csky_address op0; | |
4446 | |
4447 decompose_csky_address (XEXP (dst, 0), &op0); | |
4448 | |
4449 if (GET_CODE (memexp) == REG) | |
4450 basereg = REGNO (memexp); | |
4451 else if (GET_CODE (memexp) == PLUS) | |
4452 { | |
4453 if (GET_CODE (XEXP (memexp, 0)) == REG) | |
4454 basereg = REGNO (XEXP (memexp, 0)); | |
4455 else if (GET_CODE (XEXP (memexp, 1)) == REG) | |
4456 basereg = REGNO (XEXP (memexp, 1)); | |
4457 else | |
4458 gcc_unreachable (); | |
4459 } | |
4460 else | |
4461 gcc_unreachable (); | |
4462 | |
4463 /* FIXME length attribute is wrong here. */ | |
4464 if (srcreg == basereg) | |
4465 /* Just load them in reverse order. */ | |
4466 return "st.w\t%R1, %R0\n\tst.w\t%1, %0"; | |
4467 else | |
4468 return "st.w\t%1, %0\n\tst.w\t%R1, %R0"; | |
4469 } | |
4470 else | |
4471 gcc_unreachable (); | |
4472 } | |
4473 | |
4474 /* Split operands for an AND expression when OPERANDS[2] is a constant. | |
4475 Note operands[0] is marked earlyclobber in this case and can be | |
4476 overwritten. Return true if "DONE", false otherwise. */ | |
4477 bool | |
4478 csky_split_and (rtx *operands) | |
4479 { | |
4480 HOST_WIDE_INT mask = INTVAL (operands[2]); | |
4481 rtx not_value = GEN_INT (~mask); | |
4482 int i; | |
4483 | |
4484 /* All zeros or all ones can be handled by a move instruction. */ | |
4485 if (mask == 0) | |
4486 { | |
4487 emit_move_insn (operands[0], const0_rtx); | |
4488 return true; | |
4489 } | |
4490 if (mask == -1) | |
4491 { | |
4492 emit_move_insn (operands[0], operands[1]); | |
4493 return true; | |
4494 } | |
4495 | |
4496 /* Check for constants that can be handled directly by the 32-bit andi | |
4497 instruction. */ | |
4498 if (CSKY_ISA_FEATURE (E2) && csky_arith_O_operand (operands[2], SImode)) | |
4499 return false; | |
4500 | |
4501 /* Try to transform to andni instruction. */ | |
4502 if (CSKY_ISA_FEATURE (E2) && csky_arith_O_operand (not_value, SImode)) | |
4503 { | |
4504 emit_insn (gen_cskyv2_andnsi3 (operands[0], not_value, operands[1])); | |
4505 return true; | |
4506 } | |
4507 | |
4508 /* If there are only one or two 0 bits in the constant, we can | |
4509 replace the operation with bclri instructions on those bits. | |
4510 Note CK801 has only the 16-bit bclri that operates on a single | |
4511 register, so we must count a move if we are post-reload. */ | |
4512 if (popcount_hwi (~mask & 0xffffffff) | |
4513 <= (reload_completed && !CSKY_ISA_FEATURE (E2) ? 1 : 2)) | |
4514 { | |
4515 rtx input = operands[1]; | |
4516 | |
4517 if (!CSKY_ISA_FEATURE (E2)) | |
4518 { | |
4519 emit_move_insn (operands[0], input); | |
4520 input = operands[0]; | |
4521 } | |
4522 | |
4523 for (i = 0; i < 32; i++) | |
4524 if ((mask & (1 << i)) == 0x0) | |
4525 { | |
4526 emit_insn (gen_bclri (operands[0], input, GEN_INT (i))); | |
4527 input = operands[0]; | |
4528 } | |
4529 return true; | |
4530 } | |
4531 | |
4532 /* If the constant mask is outside the [0, 4095] range for | |
4533 constraint O, or if constraint O is not allowed (ck801), | |
4534 maybe the constant is a contiguous bit range that we can | |
4535 handle by bit extract (low bits) or shifts (high bits). */ | |
4536 for (i = (CSKY_ISA_FEATURE (E2) ? 13 : 1); i < 32; i++) | |
4537 { | |
4538 if ((((HOST_WIDE_INT) 1) << i) - 1 == mask) | |
4539 { | |
4540 if (CSKY_ISA_FEATURE (2E3)) | |
4541 emit_insn (gen_cskyv2_extzv (operands[0], operands[1], | |
4542 GEN_INT (i), const0_rtx)); | |
4543 else | |
4544 { | |
4545 rtx shift = GEN_INT (32 - i); | |
4546 rtx reg = (reload_completed | |
4547 ? operands[0] : gen_reg_rtx (SImode)); | |
4548 | |
4549 emit_insn (gen_ashlsi3 (reg, operands[1], shift)); | |
4550 emit_insn (gen_lshrsi3 (operands[0], reg, shift)); | |
4551 } | |
4552 return true; | |
4553 } | |
4554 else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~mask) | |
4555 { | |
4556 rtx shift = GEN_INT (i); | |
4557 rtx reg = (reload_completed | |
4558 ? operands[0] : gen_reg_rtx (SImode)); | |
4559 | |
4560 emit_insn (gen_lshrsi3 (reg, operands[1], shift)); | |
4561 emit_insn (gen_ashlsi3 (operands[0], reg, shift)); | |
4562 return true; | |
4563 } | |
4564 } | |
4565 | |
4566 /* If the constant is a negative number, it seems better to use | |
4567 andn and copy the NOT_VALUE to a register instead of the | |
4568 original value, since the NOT_VALUE is always smaller and thus | |
4569 more likely to be representable as a small constant. | |
4570 This transformation can only be done before reload because | |
4571 it requires a temporary. Hopefully register allocation can get | |
4572 rid of the extra move required for CK801. */ | |
4573 if (!reload_completed && INTVAL (operands[2]) < 0) | |
4574 { | |
4575 rtx reg = copy_to_mode_reg (SImode, not_value); | |
4576 | |
4577 if (CSKY_ISA_FEATURE (E2)) | |
4578 emit_insn (gen_cskyv2_andnsi3 (operands[0], reg, operands[1])); | |
4579 else | |
4580 { | |
4581 emit_move_insn (operands[0], operands[1]); | |
4582 emit_insn (gen_ck801_andnsi3 (operands[0], reg, operands[0])); | |
4583 } | |
4584 return true; | |
4585 } | |
4586 | |
4587 /* If the above ways are all not working, move the constant | |
4588 to a register. We can clobber operands[0] as it is | |
4589 marked earlyclobber in the insn constraints, but then we have to | |
4590 swap operands 1 and 2 to match the constraints on the 2-operand | |
4591 16-bit and instruction. */ | |
4592 if (reload_completed) | |
4593 { | |
4594 emit_move_insn (operands[0], operands[2]); | |
4595 operands[2] = operands[1]; | |
4596 operands[1] = operands[0]; | |
4597 } | |
4598 else | |
4599 operands[2] = copy_to_mode_reg (SImode, operands[2]); | |
4600 return false; | |
4601 } | |
4602 | |
4603 /* Split operands for an IOR expression when OPERANDS[2] is a constant. | |
4604 Note operands[0] is marked earlyclobber in this case and can be | |
4605 overwritten. Return true if "DONE", false otherwise. */ | |
4606 bool | |
4607 csky_split_ior (rtx *operands) | |
4608 { | |
4609 HOST_WIDE_INT mask = INTVAL (operands[2]); | |
4610 int i; | |
4611 | |
4612 /* All zeros or all ones can be handled by a move instruction. */ | |
4613 if (mask == 0) | |
4614 { | |
4615 emit_move_insn (operands[0], operands[1]); | |
4616 return true; | |
4617 } | |
4618 if (mask == -1) | |
4619 { | |
4620 emit_move_insn (operands[0], gen_int_mode (-1, SImode)); | |
4621 return true; | |
4622 } | |
4623 | |
4624 /* Check for constants that can be handled directly by the 32-bit ori | |
4625 instruction. */ | |
4626 if (CSKY_ISA_FEATURE (E2) && csky_literal_I_operand (operands[2], SImode)) | |
4627 return false; | |
4628 | |
4629 /* If there are only one or two 1 bits in the value, we can replace | |
4630 the operation with bseti instructions to set those bits. | |
4631 Note CK801 has only the 16-bit bclri that operates on a single | |
4632 register, so we must count a move if we are post-reload. */ | |
4633 if (popcount_hwi (mask & 0xffffffff) | |
4634 <= (reload_completed && !CSKY_ISA_FEATURE (E2) ? 1 : 2)) | |
4635 { | |
4636 rtx input = operands[1]; | |
4637 | |
4638 if (!CSKY_ISA_FEATURE (E2)) | |
4639 { | |
4640 emit_move_insn (operands[0], input); | |
4641 input = operands[0]; | |
4642 } | |
4643 | |
4644 for (i = 0; i < 32; i++) | |
4645 if (mask & (1 << i)) | |
4646 { | |
4647 emit_insn (gen_bseti (operands[0], input, GEN_INT (i))); | |
4648 input = operands[0]; | |
4649 } | |
4650 return true; | |
4651 } | |
4652 | |
4653 /* If the above ways are all not working, move the constant | |
4654 to a register. We can clobber operands[0] as it is | |
4655 marked earlyclobber in the insn constraints, but then we have to | |
4656 swap operands 1 and 2 to match the constraints on the 2-operand | |
4657 16-bit ior instruction. */ | |
4658 if (reload_completed) | |
4659 { | |
4660 emit_move_insn (operands[0], operands[2]); | |
4661 operands[2] = operands[1]; | |
4662 operands[1] = operands[0]; | |
4663 } | |
4664 else | |
4665 operands[2] = copy_to_mode_reg (SImode, operands[2]); | |
4666 return false; | |
4667 } | |
4668 | |
4669 | |
4670 /* Split operands for an XOR expression when OPERANDS[2] is a constant. | |
4671 Note operands[0] is marked earlyclobber in this case and can be | |
4672 overwritten. Return true if "DONE", false otherwise. */ | |
4673 bool | |
4674 csky_split_xor (rtx *operands) | |
4675 { | |
4676 HOST_WIDE_INT mask = INTVAL (operands[2]); | |
4677 | |
4678 /* All zeros can be turned into move instruction. */ | |
4679 if (mask == 0) | |
4680 { | |
4681 emit_move_insn (operands[0], operands[1]); | |
4682 return true; | |
4683 } | |
4684 | |
4685 /* All ones can be turned into a bitwise not. */ | |
4686 if (mask == -1) | |
4687 { | |
4688 if (CSKY_ISA_FEATURE (E2)) | |
4689 emit_insn (gen_cskyv2_one_cmplsi2 (operands[0], operands[1])); | |
4690 else | |
4691 { | |
4692 emit_move_insn (operands[0], operands[1]); | |
4693 emit_insn (gen_ck801_one_cmplsi2 (operands[0], operands[0])); | |
4694 } | |
4695 return true; | |
4696 } | |
4697 | |
4698 /* Check for constants that can be handled directly by the 32-bit xori | |
4699 instruction. */ | |
4700 if (CSKY_ISA_FEATURE (E2) && csky_arith_O_operand (operands[2], SImode)) | |
4701 return false; | |
4702 | |
4703 /* If the above ways are all not working, move the constant | |
4704 to a register. We can clobber operands[0] as it is | |
4705 marked earlyclobber in the insn constraints, but then we have to | |
4706 swap operands 1 and 2 to match the constraints on the 2-operand | |
4707 16-bit ior instruction. */ | |
4708 if (reload_completed) | |
4709 { | |
4710 emit_move_insn (operands[0], operands[2]); | |
4711 operands[2] = operands[1]; | |
4712 operands[1] = operands[0]; | |
4713 } | |
4714 else | |
4715 operands[2] = copy_to_mode_reg (SImode, operands[2]); | |
4716 return false; | |
4717 } | |
4718 | |
4719 | |
4720 /* Return true if X is an address form involving a symbol or label ref. */ | |
4721 bool | |
4722 csky_symbolic_address_p (rtx x) | |
4723 { | |
4724 switch (GET_CODE (x)) | |
4725 { | |
4726 case SYMBOL_REF: | |
4727 case LABEL_REF: | |
4728 return 1; | |
4729 case CONST: | |
4730 x = XEXP (x, 0); | |
4731 return ((GET_CODE (XEXP (x, 0)) == SYMBOL_REF | |
4732 || GET_CODE (XEXP (x, 0)) == LABEL_REF) | |
4733 && GET_CODE (XEXP (x, 1)) == CONST_INT); | |
4734 default: | |
4735 return 0; | |
4736 } | |
4737 } | |
4738 | |
4739 | |
4740 /* Emit a comparison instruction. | |
4741 Return true if an inverted comparison is generated. */ | |
4742 | |
4743 bool | |
4744 csky_emit_compare (enum rtx_code code, rtx op0, rtx op1) | |
4745 { | |
4746 bool invert; | |
4747 rtx cc_reg = gen_rtx_REG (CCmode, CSKY_CC_REGNUM); | |
4748 | |
4749 if (GET_CODE (op1) == CONST_INT) | |
4750 { | |
4751 HOST_WIDE_INT val = INTVAL (op1); | |
4752 | |
4753 switch (code) | |
4754 { | |
4755 case GTU: | |
4756 /* Unsigned (GTU 0) is the same as (NE 0); everything else is | |
4757 converted below to LEU (reversed cmphs). */ | |
4758 if (val == 0) | |
4759 code = NE; | |
4760 /* Check whether (GTU A imm) can become (GEU A imm + 1). */ | |
4761 else if (TARGET_MINI_REGISTERS | |
4762 ? CSKY_CONST_OK_FOR_J (val + 1) | |
4763 : CSKY_CONST_OK_FOR_Uk (val + 1)) | |
4764 { | |
4765 op1 = GEN_INT (val + 1); | |
4766 code = GEU; | |
4767 } | |
4768 break; | |
4769 /* Check whether (LE A imm) can become (LT A imm + 1), | |
4770 or (GT A imm) can become (GE A imm + 1). */ | |
4771 case GT: | |
4772 case LE: | |
4773 if (TARGET_MINI_REGISTERS | |
4774 ? CSKY_CONST_OK_FOR_J (val + 1) | |
4775 : CSKY_CONST_OK_FOR_Uk (val + 1)) | |
4776 { | |
4777 op1 = GEN_INT (val + 1); | |
4778 code = code == LE ? LT : GE; | |
4779 } | |
4780 break; | |
4781 | |
4782 default: | |
4783 break; | |
4784 } | |
4785 } | |
4786 | |
4787 if (CONSTANT_P (op1) && GET_CODE (op1) != CONST_INT) | |
4788 op1 = force_reg (GET_MODE (op1), op1); | |
4789 | |
4790 /* cmpnei: 0-31 (K immediate) | |
4791 ti: 1-32 (J immediate, 0 using btsti x,31). */ | |
4792 invert = false; | |
4793 switch (code) | |
4794 { | |
4795 /* Use inverted condition, cmpne. */ | |
4796 case EQ: | |
4797 code = NE; | |
4798 invert = true; | |
4799 /* Fall through. */ | |
4800 /* Use normal condition, cmpne. */ | |
4801 case NE: | |
4802 if (GET_CODE (op1) == CONST_INT | |
4803 && (TARGET_MINI_REGISTERS | |
4804 ? !csky_literal_K_operand (op1, SImode) | |
4805 : !csky_literal_I_operand (op1, SImode))) | |
4806 op1 = force_reg (SImode, op1); | |
4807 break; | |
4808 | |
4809 /* Use inverted condition, reversed cmplt. */ | |
4810 case LE: | |
4811 code = GT; | |
4812 invert = true; | |
4813 /* Fall through. */ | |
4814 /* Use normal condition, reversed cmplt. */ | |
4815 case GT: | |
4816 if (GET_CODE (op1) == CONST_INT) | |
4817 op1 = force_reg (SImode, op1); | |
4818 break; | |
4819 | |
4820 /* Use inverted condition, cmplt. */ | |
4821 case GE: | |
4822 code = LT; | |
4823 invert = true; | |
4824 /* Fall through. */ | |
4825 /* Use normal condition, cmplt. */ | |
4826 case LT: | |
4827 /* covered by btsti x,31. */ | |
4828 if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0 | |
4829 && (TARGET_MINI_REGISTERS | |
4830 ? !csky_literal_J_operand (op1, SImode) | |
4831 : !csky_literal_Uk_operand (op1, SImode))) | |
4832 op1 = force_reg (SImode, op1); | |
4833 break; | |
4834 | |
4835 /* Use inverted condition, cmple. */ | |
4836 case GTU: | |
4837 /* We coped with unsigned > 0 above. */ | |
4838 gcc_assert (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0); | |
4839 code = LEU; | |
4840 invert = true; | |
4841 /* Fall through. */ | |
4842 /* Use normal condition, reversed cmphs. */ | |
4843 case LEU: | |
4844 if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0) | |
4845 op1 = force_reg (SImode, op1); | |
4846 break; | |
4847 | |
4848 /* Use inverted condition, cmphs. */ | |
4849 case LTU: | |
4850 code = GEU; | |
4851 invert = true; | |
4852 /* Fall through. */ | |
4853 /* Use normal condition, cmphs. */ | |
4854 case GEU: | |
4855 if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0 | |
4856 && (TARGET_MINI_REGISTERS | |
4857 ? !csky_literal_J_operand (op1, SImode) | |
4858 : !csky_literal_Uk_operand (op1, SImode))) | |
4859 op1 = force_reg (SImode, op1); | |
4860 break; | |
4861 | |
4862 default: | |
4863 break; | |
4864 } | |
4865 | |
4866 emit_insn (gen_rtx_SET (cc_reg, | |
4867 gen_rtx_fmt_ee (code, CCmode, op0, op1))); | |
4868 return invert; | |
4869 } | |
4870 | |
4871 /* Return true if push/pop can be used to save/restore all the registers | |
4872 indicated by MASK. We currently don't attempt to handle situations where | |
4873 some of the registers could be handled by push/pop and others saved and | |
4874 restored individually. */ | |
4875 | |
4876 static bool | |
4877 csky_can_use_pushpop (unsigned int mask) | |
4878 { | |
4879 int i; | |
4880 int end_reg; | |
4881 | |
4882 if (!TARGET_PUSHPOP) | |
4883 return false; | |
4884 | |
4885 if (mask == 0) | |
4886 return false; | |
4887 | |
4888 /* Regs 0-3, 12-14, 18-27, 29-31 cannot be in the mask. */ | |
4889 if (mask & 0xeffc700f) | |
4890 return false; | |
4891 | |
4892 /* Regs in the range r4-r11 must be contiguous. */ | |
4893 for (end_reg = 0, i = 11; i >= 4; i--) | |
4894 { | |
4895 if (!end_reg && (mask & (1 << i))) | |
4896 end_reg = i; | |
4897 if (end_reg && !(mask & (1 << i))) | |
4898 return false; | |
4899 } | |
4900 | |
4901 /* Likewise for regs in the range r16-r17. */ | |
4902 for (end_reg = 0, i = 17; i >= 16; i--) | |
4903 { | |
4904 if (!end_reg && (mask & (1 << i))) | |
4905 end_reg = i; | |
4906 if (end_reg && !(mask & (1 << i))) | |
4907 return false; | |
4908 } | |
4909 | |
4910 return true; | |
4911 } | |
4912 | |
4913 | |
4914 /* Return true if store/load multiple instructions can be used to | |
4915 save/restore at least some of the registers indicated by MASK. | |
4916 Unlike the push/pop case, this does handle partial ranges. | |
4917 Set *BR and *ER to the beginning and end (respectively) of the | |
4918 register range that can be handled. */ | |
4919 | |
4920 static bool | |
4921 csky_can_use_ldstm (int mask, int *br, int *er) | |
4922 { | |
4923 int regno; | |
4924 int begin_reg = 0, end_reg = 0; | |
4925 int count = 0; | |
4926 | |
4927 if (!TARGET_MULTIPLE_STLD) | |
4928 return false; | |
4929 | |
4930 /* We'll only handle registers in the range 4-11, the contiguous range | |
4931 of caller-saved registers. Higher-numbered registers are handled | |
4932 individually in addition to this, but we'll give up on doing ldstm | |
4933 entirely if we need to save/restore the low-numbered EH registers. */ | |
4934 if (mask & 0xf) | |
4935 return false; | |
4936 | |
4937 for (regno = 4; regno <= 11; regno++) | |
4938 { | |
4939 if (mask & 1 << regno) | |
4940 { | |
4941 if (!begin_reg) | |
4942 begin_reg = regno; | |
4943 end_reg = regno; | |
4944 count++; | |
4945 } | |
4946 else if (begin_reg) | |
4947 break; | |
4948 } | |
4949 | |
4950 if (count >= CSKY_MIN_MULTIPLE_STLD && count <= CSKY_MAX_MULTIPLE_STLD) | |
4951 { | |
4952 if (br) | |
4953 *br = begin_reg; | |
4954 if (er) | |
4955 *er = end_reg; | |
4956 return true; | |
4957 } | |
4958 return false; | |
4959 } | |
4960 | |
4961 | |
4962 const char * | |
4963 csky_output_return_instruction (void) | |
4964 { | |
4965 unsigned long func_type = get_csky_current_func_type (); | |
4966 | |
4967 if (CSKY_FUNCTION_IS_NAKED (func_type)) | |
4968 return ""; | |
4969 if (CSKY_FUNCTION_IS_INTERRUPT (func_type)) | |
4970 return "ipop\n\tnir\n"; | |
4971 else | |
4972 return "rts\n"; | |
4973 } | |
4974 | |
4975 | |
4976 /* Adjust the stack pointer by OFFSET bytes. OFFSET is negative if this | |
4977 is in the prologue, positive if in the epilogue. This may require | |
4978 multiple instructions and/or use of CSKY_STACKADJUST_REGNUM as | |
4979 a scratch register. Emit CFA notes as appropriate. */ | |
4980 static void | |
4981 expand_csky_stack_adjust (int offset) | |
4982 { | |
4983 rtx set; | |
4984 rtx_insn *insn; | |
4985 int size = (offset > 0 ? offset : -offset); | |
4986 | |
4987 if (offset == 0) | |
4988 return; | |
4989 | |
4990 /* If OFFSET is too large for addi/subi, load it into | |
4991 CSKY_STACKADJUST_REGNUM and use a register add/sub instead. | |
4992 This case is not mentioned in the ABI documentation, but it is | |
4993 supported by GDB prologue analysis provided that the instruction(s) | |
4994 to initialize CSKY_STACKADJUST_REGNUM appear directly before | |
4995 the sub. Depending on the value of OFFSET, this might be a | |
4996 lrw instruction or the "tricks" used by csky_output_inline_const to | |
4997 encode special-case integer constants. */ | |
4998 if (size > CSKY_MAX_SP_ADJUST * 2) | |
4999 { | |
5000 rtx tmp, dwarf; | |
5001 | |
5002 /* We should have reserved the scratch register already in | |
5003 csky_layout_stack_frame. */ | |
5004 gcc_assert (cfun->machine->reg_size != 0 | |
5005 && (cfun->machine->reg_mask | |
5006 & (1 << CSKY_STACKADJUST_REGNUM))); | |
5007 | |
5008 /* Prevent the optimizer from reordering these instructions to | |
5009 keep GDB happy. */ | |
5010 if (!flag_sched_prolog) | |
5011 emit_insn (gen_blockage ()); | |
5012 | |
5013 tmp = gen_rtx_REG (SImode, CSKY_STACKADJUST_REGNUM); | |
5014 emit_move_insn (tmp, GEN_INT (size)); | |
5015 | |
5016 if (offset > 0) | |
5017 set = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp); | |
5018 else | |
5019 set = gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp); | |
5020 insn = emit_insn (set); | |
5021 RTX_FRAME_RELATED_P (insn) = 1; | |
5022 dwarf = gen_rtx_SET (stack_pointer_rtx, | |
5023 plus_constant (Pmode, stack_pointer_rtx, offset)); | |
5024 add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf); | |
5025 | |
5026 /* More make GDB happy. */ | |
5027 if (!flag_sched_prolog) | |
5028 emit_insn (gen_blockage ()); | |
5029 } | |
5030 | |
5031 /* Use one or two addi or subi insns to adjust stack. */ | |
5032 else | |
5033 while (size) | |
5034 { | |
5035 int delta = (size > CSKY_MAX_SP_ADJUST | |
5036 ? CSKY_MAX_SP_ADJUST : size); | |
5037 | |
5038 if (offset > 0) | |
5039 set = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, | |
5040 GEN_INT (delta)); | |
5041 else | |
5042 set = gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, | |
5043 GEN_INT (delta)); | |
5044 insn = emit_insn (set); | |
5045 RTX_FRAME_RELATED_P (insn) = 1; | |
5046 size -= delta; | |
5047 } | |
5048 } | |
5049 | |
5050 | |
5051 /* Generate and emit an insn that we will recognize as a push_multi. | |
5052 Unfortunately, since this insn does not reflect very well the actual | |
5053 semantics of the operation, we need to annotate the insn for the benefit | |
5054 of DWARF2 frame unwind information. DWARF_REGS_MASK is a subset of | |
5055 MASK for registers that should be annotated for DWARF2 frame unwind | |
5056 information. */ | |
5057 | |
5058 static rtx | |
5059 emit_csky_regs_push (unsigned long mask) | |
5060 { | |
5061 int num_regs = 0; | |
5062 int i, j; | |
5063 rtx par; | |
5064 rtx dwarf; | |
5065 rtx tmp; | |
5066 int dwarf_par_index; | |
5067 | |
5068 for (i = 0; i < CSKY_NGPR_REGS; i++) | |
5069 { | |
5070 if (mask & (1 << i)) | |
5071 num_regs++; | |
5072 } | |
5073 | |
5074 /* The reg range for push is:r4-r11,r15-r17,r28. */ | |
5075 gcc_assert (num_regs && num_regs <= 12); | |
5076 | |
5077 /* For the body of the insn we are going to generate an UNSPEC in | |
5078 parallel with several USEs. This allows the insn to be recognized | |
5079 by the push_multi pattern in the csky.md file. | |
5080 | |
5081 The body of the insn looks something like this: | |
5082 | |
5083 (parallel [ | |
5084 (set (mem:BLK (pre_modify:SI (reg:SI sp) | |
5085 (const_int:SI <num>))) | |
5086 (unspec:BLK [(reg:SI r4)] UNSPEC_PUSHPOP_MULT)) | |
5087 (use (reg:SI XX)) | |
5088 (use (reg:SI YY)) | |
5089 ... | |
5090 ]) | |
5091 | |
5092 For the frame note however, we try to be more explicit and actually | |
5093 show each register being stored into the stack frame, plus a (single) | |
5094 decrement of the stack pointer. We do it this way in order to be | |
5095 friendly to the stack unwinding code, which only wants to see a single | |
5096 stack decrement per instruction. The RTL we generate for the note looks | |
5097 something like this: | |
5098 | |
5099 (sequence [ | |
5100 (set (reg:SI sp) (plus:SI (reg:SI sp) (const_int -20))) | |
5101 (set (mem:SI (reg:SI sp)) (reg:SI r4)) | |
5102 (set (mem:SI (plus:SI (reg:SI sp) (const_int 4))) (reg:SI XX)) | |
5103 (set (mem:SI (plus:SI (reg:SI sp) (const_int 8))) (reg:SI YY)) | |
5104 ... | |
5105 ]) | |
5106 | |
5107 FIXME:: In an ideal world the PRE_MODIFY would not exist and | |
5108 instead we'd have a parallel expression detailing all | |
5109 the stores to the various memory addresses so that debug | |
5110 information is more up-to-date. Remember however while writing | |
5111 this to take care of the constraints with the push instruction. | |
5112 | |
5113 Note also that this has to be taken care of for the VFP registers. | |
5114 | |
5115 For more see PR43399. */ | |
5116 | |
5117 par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs)); | |
5118 dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1)); | |
5119 dwarf_par_index = 1; | |
5120 | |
5121 for (i = 0; i < CSKY_NGPR_REGS; i++) | |
5122 if (mask & (1 << i)) | |
5123 { | |
5124 rtx reg = gen_rtx_REG (SImode, i); | |
5125 rtx addr = plus_constant (Pmode, stack_pointer_rtx, -4 * num_regs); | |
5126 tmp = gen_frame_mem (BLKmode, | |
5127 gen_rtx_PRE_MODIFY (Pmode, | |
5128 stack_pointer_rtx, addr)); | |
5129 XVECEXP (par, 0, 0) | |
5130 = gen_rtx_SET (tmp, | |
5131 gen_rtx_UNSPEC (BLKmode, | |
5132 gen_rtvec (1, reg), | |
5133 UNSPEC_PUSHPOP_MULT)); | |
5134 tmp = gen_rtx_SET (gen_frame_mem (SImode, stack_pointer_rtx), | |
5135 reg); | |
5136 RTX_FRAME_RELATED_P (tmp) = 1; | |
5137 XVECEXP (dwarf, 0, dwarf_par_index++) = tmp; | |
5138 | |
5139 break; | |
5140 } | |
5141 | |
5142 for (j = 1, i++; j < num_regs; i++) | |
5143 if (mask & (1 << i)) | |
5144 { | |
5145 rtx reg = gen_rtx_REG (SImode, i); | |
5146 rtx addr = plus_constant (Pmode, stack_pointer_rtx, 4 * j); | |
5147 tmp = gen_rtx_SET (gen_frame_mem (SImode, addr), reg); | |
5148 RTX_FRAME_RELATED_P (tmp) = 1; | |
5149 XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg); | |
5150 XVECEXP (dwarf, 0, dwarf_par_index++) = tmp; | |
5151 j++; | |
5152 } | |
5153 | |
5154 par = emit_insn (par); | |
5155 | |
5156 tmp = gen_rtx_SET (stack_pointer_rtx, | |
5157 plus_constant (Pmode, stack_pointer_rtx, -4 * num_regs)); | |
5158 RTX_FRAME_RELATED_P (tmp) = 1; | |
5159 XVECEXP (dwarf, 0, 0) = tmp; | |
5160 | |
5161 add_reg_note (par, REG_FRAME_RELATED_EXPR, dwarf); | |
5162 RTX_FRAME_RELATED_P (par) = 1; | |
5163 | |
5164 return par; | |
5165 } | |
5166 | |
5167 | |
5168 /* Generate and emit an insn pattern that we will recognize as a pop_multi. | |
5169 SAVED_REGS_MASK shows which registers need to be restored. | |
5170 | |
5171 Unfortunately, since this insn does not reflect very well the actual | |
5172 semantics of the operation, we need to annotate the insn for the benefit | |
5173 of DWARF2 frame unwind information. */ | |
5174 | |
5175 static void | |
5176 emit_csky_regs_pop (unsigned long mask) | |
5177 { | |
5178 int num_regs = 0; | |
5179 int i, j; | |
5180 rtx par; | |
5181 | |
5182 for (i = 0; i < CSKY_NGPR_REGS; i++) | |
5183 if (mask & (1 << i)) | |
5184 num_regs++; | |
5185 | |
5186 /* The reg range for push is:r4-r11,r15-r17,r28. */ | |
5187 gcc_assert (num_regs && num_regs <= 12); | |
5188 | |
5189 /* The first element is (return), | |
5190 the second element is | |
5191 (set (reg:SI 'first reg number') | |
5192 (unspec:SI [(mem)] UNSPEC_PUSHPOP_MULT), | |
5193 the rest elements is (use (reg:SI 'rest reg number')), | |
5194 so the length should be number of register to be poped | |
5195 plus one. */ | |
5196 par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs + 1)); | |
5197 | |
5198 XVECEXP (par, 0, 0) = ret_rtx; | |
5199 | |
5200 for (i = 0; i < CSKY_NGPR_REGS; i++) | |
5201 if (mask & (1 << i)) | |
5202 { | |
5203 rtx reg = gen_rtx_REG (SImode, i); | |
5204 rtx addr = plus_constant (Pmode, stack_pointer_rtx, 4 * num_regs); | |
5205 rtx tmp = gen_frame_mem (SImode, | |
5206 gen_rtx_POST_MODIFY (Pmode, | |
5207 stack_pointer_rtx, addr)); | |
5208 XVECEXP (par, 0, 1) | |
5209 = gen_rtx_SET (reg, | |
5210 gen_rtx_UNSPEC (SImode, | |
5211 gen_rtvec (1, tmp), | |
5212 UNSPEC_PUSHPOP_MULT)); | |
5213 break; | |
5214 } | |
5215 | |
5216 for (j = 2, i++; j < (num_regs + 1); i++) | |
5217 if (mask & (1 << i)) | |
5218 { | |
5219 rtx reg = gen_rtx_REG (SImode, i); | |
5220 XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg); | |
5221 j++; | |
5222 } | |
5223 | |
5224 par = emit_jump_insn (par); | |
5225 } | |
5226 | |
5227 | |
5228 /* Generate the function prologue. */ | |
5229 | |
5230 void | |
5231 csky_expand_prologue (void) | |
5232 { | |
5233 rtx_insn *insn; | |
5234 unsigned long func_type = get_csky_current_func_type (); | |
5235 unsigned int reg_mask; | |
5236 int reg_size; | |
5237 | |
5238 if (CSKY_FUNCTION_IS_NAKED (func_type)) | |
5239 { | |
5240 if (flag_stack_usage_info) | |
5241 current_function_static_stack_size = 0; | |
5242 return; | |
5243 } | |
5244 | |
5245 csky_layout_stack_frame (); | |
5246 reg_mask = cfun->machine->reg_mask; | |
5247 reg_size = cfun->machine->reg_size; | |
5248 | |
5249 /* Adjust stack pointer past argument overflow area. */ | |
5250 if (cfun->machine->arg_size != 0) | |
5251 { | |
5252 int offset = cfun->machine->arg_size; | |
5253 expand_csky_stack_adjust (- offset); | |
5254 | |
5255 /* If we have a parameter passed partially in regs and partially | |
5256 in memory, the registers will have been stored to memory already | |
5257 in function.c. So we only need to copy varargs from registers | |
5258 to stack. */ | |
5259 if (cfun->machine->uses_anonymous_args) | |
5260 { | |
5261 int rn = CSKY_FIRST_PARM_REGNUM + CSKY_NPARM_REGS - 1; | |
5262 for (offset -= 4; offset >= 0; offset -= 4, rn--) | |
5263 { | |
5264 rtx dst = gen_frame_mem (SImode, | |
5265 plus_constant (Pmode, | |
5266 stack_pointer_rtx, | |
5267 offset)); | |
5268 insn = emit_move_insn (dst, gen_rtx_REG (SImode, rn)); | |
5269 RTX_FRAME_RELATED_P (insn) = 1; | |
5270 } | |
5271 } | |
5272 } | |
5273 | |
5274 /* Push caller-saved registers to stack. */ | |
5275 if (csky_can_use_pushpop (reg_mask)) | |
5276 emit_csky_regs_push (reg_mask); | |
5277 else if (reg_size) | |
5278 { | |
5279 int sreg = -1, ereg = -1; | |
5280 bool stm_p = csky_can_use_ldstm (reg_mask, &sreg, &ereg); | |
5281 int stm_regs = stm_p ? ereg - sreg + 1 : 0; | |
5282 int stm_size = stm_regs * 4; | |
5283 | |
5284 /* First adjust the SP to the low end of the register save area. */ | |
5285 expand_csky_stack_adjust (- reg_size); | |
5286 | |
5287 /* Emit individual register saves. Even if we are going to emit an | |
5288 stm, we may need to save individual registers above that too. */ | |
5289 if (reg_size > stm_size) | |
5290 { | |
5291 int offset = reg_size - 4; | |
5292 int regno = 31; | |
5293 for ( ; regno > ereg; regno--) | |
5294 if (reg_mask & (1 << regno)) | |
5295 { | |
5296 rtx dst = gen_rtx_MEM (SImode, | |
5297 plus_constant (Pmode, | |
5298 stack_pointer_rtx, | |
5299 offset)); | |
5300 rtx insn = emit_insn (gen_movsi (dst, | |
5301 gen_rtx_REG (SImode, regno))); | |
5302 RTX_FRAME_RELATED_P (insn) = 1; | |
5303 if (offset == stm_size) | |
5304 break; | |
5305 offset -= 4; | |
5306 } | |
5307 } | |
5308 | |
5309 /* If possible, emit a stm to do a bulk store of sequential | |
5310 registers to the stack. Note that it is an error in the ABI | |
5311 documentation that it doesn't list stm as a valid prologue | |
5312 instruction. */ | |
5313 if (stm_p) | |
5314 { | |
5315 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (stm_regs)); | |
5316 int regno, slot; | |
5317 for (regno = sreg, slot = 0; regno <= ereg; regno++, slot++) | |
5318 { | |
5319 rtx reg = gen_rtx_REG (SImode, regno); | |
5320 rtx addr = plus_constant (Pmode, stack_pointer_rtx, slot * 4); | |
5321 rtx set = gen_rtx_SET (gen_frame_mem (SImode, addr), reg); | |
5322 RTX_FRAME_RELATED_P (set) = 1; | |
5323 XVECEXP (par, 0, slot) = set; | |
5324 } | |
5325 insn = emit_insn (par); | |
5326 RTX_FRAME_RELATED_P (insn) = 1; | |
5327 } | |
5328 } | |
5329 | |
5330 /* Initialize hard frame pointer, if necessary. It points at the base | |
5331 of the register save area. */ | |
5332 if (frame_pointer_needed) | |
5333 { | |
5334 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); | |
5335 RTX_FRAME_RELATED_P (insn) = 1; | |
5336 } | |
5337 | |
5338 /* Reserve stack space for locals and outgoing args. */ | |
5339 expand_csky_stack_adjust (- cfun->machine->reg_offset); | |
5340 | |
5341 /* Put the GOT address in reg_gb for PIC, using R13 as a scratch. | |
5342 See section 4.7.1 in the ABI documentation, | |
5343 "Function Prologue for PIC". */ | |
5344 if (flag_pic && (reg_mask & (1 << PIC_OFFSET_TABLE_REGNUM))) | |
5345 { | |
5346 rtx l1 = gen_label_rtx (); | |
5347 rtx grs_label = gen_rtx_LABEL_REF (SImode, l1); | |
5348 rtx reg_gb = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM); | |
5349 rtx reg_temp = gen_rtx_REG (SImode, 13); | |
5350 | |
5351 rtx tmp0_unspec = gen_rtx_UNSPEC (Pmode, | |
5352 gen_rtvec (1, grs_label), | |
5353 UNSPEC_PIC_SYMBOL_GOTPC_GRS); | |
5354 rtx tmp1_unspec = gen_rtx_UNSPEC (Pmode, | |
5355 gen_rtvec (1, grs_label), | |
5356 UNSPEC_PIC_SYMBOL_GOTPC); | |
5357 | |
5358 emit_insn (gen_prologue_get_pc (tmp0_unspec)); | |
5359 emit_move_insn (reg_temp, tmp1_unspec); | |
5360 emit_insn (gen_addsi3 (reg_gb, reg_gb, reg_temp)); | |
5361 } | |
5362 | |
5363 if (flag_stack_usage_info) | |
5364 current_function_static_stack_size = cfun->machine->frame_size; | |
5365 | |
5366 if (!flag_sched_prolog) | |
5367 emit_insn (gen_blockage ()); | |
5368 } | |
5369 | |
5370 void | |
5371 csky_expand_epilogue (void) | |
5372 { | |
5373 unsigned long func_type = get_csky_current_func_type (); | |
5374 unsigned int reg_mask; | |
5375 int reg_size; | |
5376 int adjust; | |
5377 rtx_insn *insn; | |
5378 | |
5379 if (!flag_sched_prolog) | |
5380 emit_insn (gen_blockage ()); | |
5381 | |
5382 if (CSKY_FUNCTION_IS_NAKED (func_type)) | |
5383 { | |
5384 emit_jump_insn (gen_simple_return ()); | |
5385 return; | |
5386 } | |
5387 | |
5388 /* Get the frame information. */ | |
5389 csky_layout_stack_frame (); | |
5390 reg_mask = cfun->machine->reg_mask; | |
5391 reg_size = cfun->machine->reg_size; | |
5392 adjust = reg_size + cfun->machine->arg_size; | |
5393 | |
5394 /* Restore the SP to the base of the register save area. */ | |
5395 if (frame_pointer_needed) | |
5396 { | |
5397 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx); | |
5398 RTX_FRAME_RELATED_P (insn) = 1; | |
5399 } | |
5400 else | |
5401 expand_csky_stack_adjust (cfun->machine->reg_offset); | |
5402 | |
5403 /* Restore the callee-saved registers. */ | |
5404 if (csky_can_use_pushpop (reg_mask) | |
5405 && cfun->machine->arg_size == 0 | |
5406 && !CSKY_FUNCTION_IS_INTERRUPT (func_type) | |
5407 && !crtl->calls_eh_return) | |
5408 { | |
5409 /* Pop includes an implicit return, so we are done. */ | |
5410 emit_csky_regs_pop (reg_mask); | |
5411 return; | |
5412 } | |
5413 else if (reg_size) | |
5414 { | |
5415 int sreg = -1, ereg = -1; | |
5416 bool ldm_p = csky_can_use_ldstm (reg_mask, &sreg, &ereg); | |
5417 int ldm_regs = ldm_p ? ereg - sreg + 1 : 0; | |
5418 int ldm_size = ldm_regs * 4; | |
5419 | |
5420 /* Emit individual register loads. Even if we are going to emit an | |
5421 ldm, we may need to load individual registers above that too. */ | |
5422 if (reg_size > ldm_size) | |
5423 { | |
5424 int offset = reg_size - 4; | |
5425 int regno = 31; | |
5426 for ( ; regno > ereg; regno--) | |
5427 if (reg_mask & (1 << regno)) | |
5428 { | |
5429 rtx src = gen_frame_mem (SImode, | |
5430 plus_constant (Pmode, | |
5431 stack_pointer_rtx, | |
5432 offset)); | |
5433 rtx reg = gen_rtx_REG (SImode, regno); | |
5434 insn = emit_move_insn (reg, src); | |
5435 RTX_FRAME_RELATED_P (insn) = 1; | |
5436 add_reg_note (insn, REG_CFA_RESTORE, reg); | |
5437 if (offset == ldm_size) | |
5438 break; | |
5439 offset -= 4; | |
5440 } | |
5441 } | |
5442 | |
5443 /* If possible, emit a ldm to do a bulk load of sequential | |
5444 registers from the stack. */ | |
5445 if (ldm_p) | |
5446 { | |
5447 rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (ldm_regs)); | |
5448 int regno, slot; | |
5449 for (regno = sreg, slot = 0; regno <= ereg; regno++, slot++) | |
5450 { | |
5451 rtx reg = gen_rtx_REG (SImode, regno); | |
5452 rtx addr = plus_constant (Pmode, stack_pointer_rtx, slot * 4); | |
5453 rtx set = gen_rtx_SET (reg, gen_frame_mem (SImode, addr)); | |
5454 XVECEXP (par, 0, slot) = set; | |
5455 } | |
5456 insn = emit_insn (par); | |
5457 RTX_FRAME_RELATED_P (insn) = 1; | |
5458 for (regno = sreg; regno <= ereg; regno++) | |
5459 { | |
5460 rtx reg = gen_rtx_REG (SImode, regno); | |
5461 add_reg_note (insn, REG_CFA_RESTORE, reg); | |
5462 } | |
5463 } | |
5464 } | |
5465 | |
5466 /* Emit the final stack pointer adjustment to deallocate the saved | |
5467 registers and incoming argument area. */ | |
5468 expand_csky_stack_adjust (adjust); | |
5469 | |
5470 /* Extra stack adjustment for exception handler return. */ | |
5471 if (crtl->calls_eh_return) | |
5472 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, | |
5473 EH_RETURN_STACKADJ_RTX)); | |
5474 | |
5475 /* Now we can return. */ | |
5476 emit_jump_insn (gen_simple_return ()); | |
5477 } | |
5478 | |
5479 | |
5480 static void | |
5481 csky_output_function_prologue (FILE *f) | |
5482 { | |
5483 unsigned long func_type = get_csky_current_func_type (); | |
5484 | |
5485 switch ((int) CSKY_FUNCTION_TYPE (func_type)) | |
5486 { | |
5487 default: | |
5488 case CSKY_FT_NORMAL: | |
5489 break; | |
5490 case CSKY_FT_INTERRUPT: | |
5491 { | |
5492 asm_fprintf (f, "\t# Interrupt Service Routine.\n"); | |
5493 asm_fprintf (f, "\tnie\n\tipush\n"); | |
5494 break; | |
5495 } | |
5496 case CSKY_FT_FIQ: | |
5497 asm_fprintf (f, "\t# Fast Interrupt Service Routine.\n"); | |
5498 break; | |
5499 case CSKY_FT_EXCEPTION: | |
5500 asm_fprintf (f, "\t# CSKY Exception Handler.\n"); | |
5501 break; | |
5502 case CSKY_FT_NAKED: | |
5503 asm_fprintf (f, "\t# Naked Function: prologue and epilogue \ | |
5504 provided by programmer.\n"); | |
5505 return; | |
5506 } | |
5507 | |
5508 csky_layout_stack_frame (); | |
5509 | |
5510 /* Generate .stack_size function-name, size for callgraph; | |
5511 the default stack size is 0. */ | |
5512 if (TARGET_STACK_SIZE && cfun->machine->frame_size > 0) | |
5513 { | |
5514 gcc_assert (current_function_decl != NULL); | |
5515 const char *func_name = | |
5516 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)); | |
5517 if (func_name[0] == '*') | |
5518 asm_fprintf (f, "\t.stack_size %s, %d\n", | |
5519 &func_name[1], cfun->machine->frame_size); | |
5520 else | |
5521 asm_fprintf (f, "\t.stack_size %s, %d\n", | |
5522 func_name, cfun->machine->frame_size); | |
5523 } | |
5524 } | |
5525 | |
5526 | |
5527 static void | |
5528 csky_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED) | |
5529 { | |
5530 | |
5531 } | |
5532 | |
5533 | |
5534 /* Helper for csky_eh_return splitter: store the call frame exception | |
5535 handler address in lr. */ | |
5536 void | |
5537 csky_set_eh_return_address (rtx source, rtx scratch) | |
5538 { | |
5539 HOST_WIDE_INT delta = 0; | |
5540 rtx basereg, addr; | |
5541 unsigned int reg_mask; | |
5542 | |
5543 csky_layout_stack_frame (); | |
5544 reg_mask = cfun->machine->reg_mask; | |
5545 | |
5546 if (reg_mask & (1 << CSKY_LR_REGNUM)) | |
5547 { | |
5548 /* Find LR in the stack frame. */ | |
5549 int i = 0; | |
5550 | |
5551 if (frame_pointer_needed) | |
5552 { | |
5553 basereg = frame_pointer_rtx; | |
5554 delta = 0; | |
5555 } | |
5556 else | |
5557 { | |
5558 basereg = stack_pointer_rtx; | |
5559 delta = cfun->machine->reg_offset; | |
5560 } | |
5561 | |
5562 /* At this point, (basereg + delta) points at the low end of | |
5563 the reg save area. Regs are saved sequentially from low | |
5564 to high from this address. */ | |
5565 for (i = 0; i < CSKY_LR_REGNUM; i++) | |
5566 if (reg_mask & (1 << i)) | |
5567 delta += 4; | |
5568 | |
5569 if ((CSKY_TARGET_ARCH (CK801) && delta >= CSKY_LD16_MAX_OFFSET (Pmode)) | |
5570 || delta >= CSKY_LD32_MAX_OFFSET (Pmode)) | |
5571 { | |
5572 emit_insn (gen_movsi (scratch, GEN_INT (delta))); | |
5573 emit_insn (gen_addsi3 (scratch, scratch, basereg)); | |
5574 addr = scratch; | |
5575 } | |
5576 else | |
5577 addr = plus_constant (Pmode, basereg, delta); | |
5578 emit_move_insn (gen_frame_mem (Pmode, addr), source); | |
5579 } | |
5580 else | |
5581 emit_move_insn (gen_rtx_REG (Pmode, CSKY_LR_REGNUM), source); | |
5582 } | |
5583 | |
5584 /* Return TRUE if X references a SYMBOL_REF. */ | |
5585 | |
5586 bool | |
5587 csky_symbol_mentioned_p (rtx x) | |
5588 { | |
5589 const char *fmt; | |
5590 int i; | |
5591 | |
5592 if (GET_CODE (x) == SYMBOL_REF) | |
5593 return true; | |
5594 | |
5595 fmt = GET_RTX_FORMAT (GET_CODE (x)); | |
5596 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) | |
5597 { | |
5598 if (fmt[i] == 'E') | |
5599 { | |
5600 int j; | |
5601 | |
5602 for (j = XVECLEN (x, i) - 1; j >= 0; j--) | |
5603 if (csky_symbol_mentioned_p (XVECEXP (x, i, j))) | |
5604 return true; | |
5605 } | |
5606 else if (fmt[i] == 'e' && csky_symbol_mentioned_p (XEXP (x, i))) | |
5607 return true; | |
5608 } | |
5609 return false; | |
5610 } | |
5611 | |
5612 | |
5613 /* Return TRUE if X references a LABEL_REF. */ | |
5614 | |
5615 bool | |
5616 csky_label_mentioned_p (rtx x) | |
5617 { | |
5618 const char *fmt; | |
5619 int i; | |
5620 | |
5621 if (GET_CODE (x) == LABEL_REF) | |
5622 return true; | |
5623 | |
5624 fmt = GET_RTX_FORMAT (GET_CODE (x)); | |
5625 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) | |
5626 { | |
5627 if (fmt[i] == 'E') | |
5628 { | |
5629 int j; | |
5630 | |
5631 for (j = XVECLEN (x, i) - 1; j >= 0; j--) | |
5632 if (csky_label_mentioned_p (XVECEXP (x, i, j))) | |
5633 return true; | |
5634 } | |
5635 else if (fmt[i] == 'e' && csky_label_mentioned_p (XEXP (x, i))) | |
5636 return true; | |
5637 } | |
5638 | |
5639 return false; | |
5640 } | |
5641 | |
5642 | |
5643 static bool | |
5644 tls_unspec_mentioned_p (rtx x) | |
5645 { | |
5646 switch (GET_CODE (x)) | |
5647 { | |
5648 case CONST: | |
5649 return tls_unspec_mentioned_p (XEXP (x, 0)); | |
5650 | |
5651 case UNSPEC: | |
5652 if (XINT (x, 1) == UNSPEC_TLS) | |
5653 return true; | |
5654 | |
5655 /* Fall through. */ | |
5656 default: | |
5657 return false; | |
5658 } | |
5659 } | |
5660 | |
5661 | |
5662 /* Implement LEGITIMATE_PIC_OPERAND_P. */ | |
5663 bool | |
5664 csky_legitimate_pic_operand_p (rtx x) | |
5665 { | |
5666 if (tls_unspec_mentioned_p (x)) | |
5667 return true; | |
5668 if (csky_symbol_mentioned_p (x) || csky_label_mentioned_p (x)) | |
5669 return false; | |
5670 return true; | |
5671 } | |
5672 | |
5673 rtx | |
5674 csky_legitimize_pic_address (rtx orig, rtx reg, bool gotrel_p) | |
5675 { | |
5676 rtx pic_reg = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM); | |
5677 bool optimize_p = false; | |
5678 | |
5679 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF) | |
5680 { | |
5681 rtx pic_ref, address, rtx_tmp; | |
5682 rtx insn; | |
5683 rtx pic_reg = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM); | |
5684 int subregs = 0; | |
5685 | |
5686 if (reg == 0) | |
5687 { | |
5688 gcc_assert (can_create_pseudo_p ()); | |
5689 reg = gen_reg_rtx (Pmode); | |
5690 subregs = 1; | |
5691 } | |
5692 | |
5693 if (subregs) | |
5694 address = gen_reg_rtx (Pmode); | |
5695 else | |
5696 address = reg; | |
5697 | |
5698 if (GET_CODE (orig) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (orig)) | |
5699 { | |
5700 /* When gotrel_p generate sym@GOT, otherwise generate sym@PLT. */ | |
5701 rtx_tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), | |
5702 (gotrel_p | |
5703 ? UNSPEC_PIC_SYMBOL_GOT | |
5704 : UNSPEC_PIC_SYMBOL_PLT)); | |
5705 optimize_p = gotrel_p; | |
5706 if (flag_pic != 1) | |
5707 { | |
5708 emit_move_insn (address, rtx_tmp); | |
5709 rtx_tmp = gen_rtx_MULT (Pmode, address, GEN_INT (1)); | |
5710 } | |
5711 pic_ref = gen_const_mem (Pmode, | |
5712 gen_rtx_PLUS (Pmode, pic_reg, rtx_tmp)); | |
5713 } | |
5714 else | |
5715 { | |
5716 /* bsr symbol */ | |
5717 if (flag_pic == 1 && !gotrel_p) | |
5718 { | |
5719 pic_ref = gen_rtx_UNSPEC (Pmode, | |
5720 gen_rtvec (1, orig), | |
5721 UNSPEC_PIC_SYMBOL_BSR); | |
5722 return pic_ref; | |
5723 } | |
5724 /* grs rx, symbol */ | |
5725 else if (flag_pic == 1 && (GET_CODE (orig) == SYMBOL_REF) | |
5726 && SYMBOL_REF_FUNCTION_P (orig)) | |
5727 { | |
5728 pic_ref = gen_rtx_UNSPEC (Pmode, | |
5729 gen_rtvec (1, orig), | |
5730 UNSPEC_PIC_SYMBOL_GRS); | |
5731 return pic_ref; | |
5732 } | |
5733 /* lrw rx, symbol@GOTOFF; add rx, rx, gb */ | |
5734 else | |
5735 { | |
5736 rtx_tmp = gen_rtx_UNSPEC (Pmode, | |
5737 gen_rtvec (1, orig), | |
5738 UNSPEC_PIC_SYMBOL_GOTOFF); | |
5739 emit_move_insn (address, rtx_tmp); | |
5740 pic_ref = gen_rtx_PLUS (Pmode, address, pic_reg); | |
5741 optimize_p = true; | |
5742 } | |
5743 } | |
5744 | |
5745 insn = emit_move_insn (reg, pic_ref); | |
5746 /* Put a REG_EQUAL note on this insn, | |
5747 so that it can be optimized by loop. */ | |
5748 if (optimize_p) | |
5749 set_unique_reg_note (insn, REG_EQUAL, orig); | |
5750 | |
5751 return reg; | |
5752 } | |
5753 else if (GET_CODE (orig) == CONST) | |
5754 { | |
5755 rtx base, offset; | |
5756 | |
5757 if (GET_CODE (XEXP (orig, 0)) == PLUS | |
5758 && XEXP (XEXP (orig, 0), 1) == pic_reg) | |
5759 return orig; | |
5760 | |
5761 if (reg == 0) | |
5762 { | |
5763 gcc_assert (can_create_pseudo_p ()); | |
5764 reg = gen_reg_rtx (Pmode); | |
5765 } | |
5766 | |
5767 gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS); | |
5768 | |
5769 base = csky_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), | |
5770 reg, gotrel_p); | |
5771 offset = csky_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), | |
5772 base == reg ? 0 : reg, gotrel_p); | |
5773 | |
5774 if (GET_CODE (offset) == CONST_INT) | |
5775 return plus_constant (Pmode, base, INTVAL (offset)); | |
5776 | |
5777 return gen_rtx_PLUS (Pmode, base, offset); | |
5778 } | |
5779 | |
5780 return orig; | |
5781 } | |
5782 | |
5783 | |
5784 /* Functions to output assembly code for a function call. */ | |
5785 | |
5786 char * | |
5787 csky_output_call (rtx *operands, int index) | |
5788 { | |
5789 static char buffer[20]; | |
5790 rtx addr = operands[index]; | |
5791 | |
5792 if (REG_P (addr)) | |
5793 sprintf (buffer, "jsr\t%%%d", index); | |
5794 else if (flag_pic && (GET_CODE (addr) == UNSPEC)) | |
5795 sprintf (buffer, "bsr\t%%%d", index); | |
5796 else | |
5797 sprintf (buffer, "jbsr\t%%%d", index); | |
5798 | |
5799 return buffer; | |
5800 } | |
5801 | |
5802 | |
5803 /* Worker function for TARGET_ASM_TRAMPOLINE_TEMPLATE. | |
5804 Output assembler code for a block containing the constant parts | |
5805 of a trampoline, leaving space for the variable parts. | |
5806 Note that STATIC_CHAIN_REGNUM is t1 (aka r12) on ck801 and | |
5807 t1 (r13) otherwise. */ | |
5808 | |
5809 static void | |
5810 csky_asm_trampoline_template (FILE *f) | |
5811 { | |
5812 if (CSKY_ISA_FEATURE (2E3)) | |
5813 { | |
5814 fprintf (f, "\tlrw\t%s, [.Lstatic_chain]\n", | |
5815 reg_names[STATIC_CHAIN_REGNUM]); | |
5816 fprintf (f, "\tjmpi\t[.Lfunc_address]\n"); | |
5817 /* 2 32-bit insns = 8 bytes. */ | |
5818 } | |
5819 else if (CSKY_TARGET_ARCH (CK801)) | |
5820 { | |
5821 /* It's hard to provide general support for trampolines on this | |
5822 core. We need a register other than the one holding the | |
5823 static chain (r13) to hold the function pointer for the | |
5824 indirect jump to it. But ck801 has such a limited register set | |
5825 there is no other call-clobbered scratch register available -- in | |
5826 particular, this core does not have r12, which we use for the | |
5827 ck802 case below. If we use a callee-saved register like r4, | |
5828 saving the old value on the stack screws up the stack frame | |
5829 if there are overflow arguments pushed on the stack | |
5830 by the caller. In theory we could test for that and handle | |
5831 limited cases with parameters that all fit in r0-r3 with no | |
5832 stack overflow, but punt for now. */ | |
5833 sorry ("Nested function trampolines not supported on CK801."); | |
5834 } | |
5835 else | |
5836 { | |
5837 fprintf (f, "\tlrw\t%s, [.Lfunc_address]\n", | |
5838 reg_names[CSKY_T1_REGNUM]); | |
5839 fprintf (f, "\tlrw\t%s, [.Lstatic_chain]\n", | |
5840 reg_names[STATIC_CHAIN_REGNUM]); | |
5841 fprintf (f, "\tjmp\t%s\n", | |
5842 reg_names[CSKY_T1_REGNUM]); | |
5843 /* To align constant pool on a word boundary. */ | |
5844 fprintf (f, "\t.align 2\n"); | |
5845 /* 2 32-bit lrw insns + 16-bit jump + 16-bit pad = 12 bytes. */ | |
5846 } | |
5847 | |
5848 fprintf (f, ".Lstatic_chain:\n"); | |
5849 fprintf (f, "\t.long 0\n"); | |
5850 fprintf (f, ".Lfunc_address:\n"); | |
5851 fprintf (f, "\t.long 0\n"); | |
5852 /* 2 words of constant pool = 8 bytes. */ | |
5853 } | |
5854 | |
5855 /* Worker function for TARGET_TRAMPOLINE_INIT. */ | |
5856 | |
5857 static void | |
5858 csky_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | |
5859 { | |
5860 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); | |
5861 rtx mem, a_tramp; | |
5862 int pool = TRAMPOLINE_SIZE - 8; | |
5863 | |
5864 emit_block_move (m_tramp, assemble_trampoline_template (), | |
5865 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); | |
5866 | |
5867 mem = adjust_address (m_tramp, SImode, pool); | |
5868 emit_move_insn (mem, chain_value); | |
5869 mem = adjust_address (m_tramp, SImode, pool + 4); | |
5870 emit_move_insn (mem, fnaddr); | |
5871 | |
5872 a_tramp = XEXP (m_tramp, 0); | |
5873 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), | |
5874 LCT_NORMAL, VOIDmode, a_tramp, Pmode, | |
5875 plus_constant (Pmode, a_tramp, TRAMPOLINE_SIZE), Pmode); | |
5876 } | |
5877 | |
5878 | |
5879 /* Emit a comparison insn for float values. | |
5880 Return true if the comparison is inverted. */ | |
5881 | |
5882 bool | |
5883 csky_emit_compare_float (enum rtx_code code, rtx op0, rtx op1) | |
5884 { | |
5885 rtx cc_reg = gen_rtx_REG (CCmode, CSKY_CC_REGNUM); | |
5886 bool invert; | |
5887 machine_mode mode = GET_MODE (op1); | |
5888 | |
5889 if (op1 != CONST0_RTX (mode)) | |
5890 op1 = force_reg (mode, op1); | |
5891 | |
5892 invert = false; | |
5893 switch (code) | |
5894 { | |
5895 case EQ: | |
5896 code = NE; | |
5897 invert = true; | |
5898 break; | |
5899 | |
5900 case NE: | |
5901 break; | |
5902 case LE: | |
5903 if (op1 == CONST0_RTX (mode)) | |
5904 op1 = force_reg (mode, op1); | |
5905 break; | |
5906 case GT: | |
5907 if (op1 == CONST0_RTX (mode)) | |
5908 op1 = force_reg (mode, op1); | |
5909 break; | |
5910 case GE: | |
5911 break; | |
5912 case LT: | |
5913 if (op1 == CONST0_RTX (mode)) | |
5914 { | |
5915 code = GE; | |
5916 invert = true; | |
5917 } | |
5918 break; | |
5919 case UNORDERED: | |
5920 break; | |
5921 case ORDERED: | |
5922 code = UNORDERED; | |
5923 invert = true; | |
5924 break; | |
5925 | |
5926 default: | |
5927 break; | |
5928 } | |
5929 | |
5930 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_fmt_ee (code, CCmode, op0, op1))); | |
5931 | |
5932 return invert; | |
5933 } | |
5934 | |
5935 /* Support for the Q memory constraint. Returns true if OP is a MEM RTX | |
5936 with an address consisting of base + index or base + displacement. */ | |
5937 bool | |
5938 csky_valid_fpuv2_mem_operand (rtx op) | |
5939 { | |
5940 struct csky_address addr; | |
5941 | |
5942 if (GET_CODE (op) != MEM) | |
5943 return false; | |
5944 | |
5945 if (!decompose_csky_address (XEXP (op, 0), &addr)) | |
5946 return false; | |
5947 | |
5948 /* Verify base register. */ | |
5949 if (!is_csky_address_register_rtx_p (addr.base, 0)) | |
5950 return false; | |
5951 | |
5952 /* Verify index operand. */ | |
5953 if (addr.index) | |
5954 { | |
5955 if (!is_csky_address_register_rtx_p (addr.index, 0)) | |
5956 return false; | |
5957 | |
5958 if (addr.scale == 1 || addr.scale == 2 || addr.scale == 4 | |
5959 || addr.scale == 8) | |
5960 return true; | |
5961 | |
5962 return false; | |
5963 } | |
5964 /* Verify disp operand. */ | |
5965 else if (addr.disp) | |
5966 { | |
5967 rtx disp = addr.disp; | |
5968 | |
5969 if (!CONST_INT_P (disp)) | |
5970 return false; | |
5971 | |
5972 if (((unsigned) INTVAL (disp) % 4) == 0 | |
5973 && (unsigned) INTVAL (disp) <= (unsigned) 1020) | |
5974 return true; | |
5975 | |
5976 return false; | |
5977 } | |
5978 return true; | |
5979 } | |
5980 | |
5981 | |
5982 /* Returns the (interrupt) function type of the current | |
5983 function, or CSKY_FT_UNKNOWN if the type cannot be determined. */ | |
5984 | |
5985 static unsigned long | |
5986 csky_isr_value (tree argument) | |
5987 { | |
5988 const isr_attribute_entry *ptr; | |
5989 const char *arg; | |
5990 | |
5991 /* No argument - default to IRQ. */ | |
5992 if (argument == NULL_TREE) | |
5993 return CSKY_FT_ISR; | |
5994 | |
5995 /* Get the value of the argument. */ | |
5996 if (TREE_VALUE (argument) == NULL_TREE | |
5997 || TREE_CODE (TREE_VALUE (argument)) != STRING_CST) | |
5998 return CSKY_FT_UNKNOWN; | |
5999 | |
6000 arg = TREE_STRING_POINTER (TREE_VALUE (argument)); | |
6001 | |
6002 /* Check it against the list of known arguments. */ | |
6003 for (ptr = isr_attribute_map; ptr->arg != NULL; ptr++) | |
6004 if (strcmp (arg, ptr->arg) == 0) | |
6005 return ptr->return_value; | |
6006 | |
6007 /* An unrecognized interrupt type. */ | |
6008 return CSKY_FT_UNKNOWN; | |
6009 } | |
6010 | |
6011 /* Handle an attribute requiring a FUNCTION_DECL; | |
6012 arguments as in struct attribute_spec.handler. */ | |
6013 | |
6014 static tree | |
6015 csky_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, | |
6016 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) | |
6017 { | |
6018 if (TREE_CODE (*node) != FUNCTION_DECL) | |
6019 { | |
6020 warning (OPT_Wattributes, "%qE attribute only applies to functions", | |
6021 name); | |
6022 *no_add_attrs = true; | |
6023 } | |
6024 | |
6025 return NULL_TREE; | |
6026 } | |
6027 | |
6028 /* Handle an "interrupt" or "isr" attribute; | |
6029 arguments as in struct attribute_spec.handler. */ | |
6030 | |
6031 static tree | |
6032 csky_handle_isr_attribute (tree *node, tree name, tree args, int flags, | |
6033 bool *no_add_attrs) | |
6034 { | |
6035 | |
6036 if (!TARGET_ISTACK) | |
6037 { | |
6038 warning (OPT_Wattributes, "%qE attribute ignored without -mistack", | |
6039 name); | |
6040 *no_add_attrs = true; | |
6041 return NULL_TREE; | |
6042 } | |
6043 | |
6044 if (DECL_P (*node)) | |
6045 { | |
6046 if (TREE_CODE (*node) != FUNCTION_DECL) | |
6047 { | |
6048 warning (OPT_Wattributes, "%qE attribute only applies to functions", | |
6049 name); | |
6050 *no_add_attrs = true; | |
6051 } | |
6052 } | |
6053 else | |
6054 { | |
6055 if (TREE_CODE (*node) == FUNCTION_TYPE | |
6056 || TREE_CODE (*node) == METHOD_TYPE) | |
6057 { | |
6058 if (csky_isr_value (args) == CSKY_FT_UNKNOWN) | |
6059 { | |
6060 warning (OPT_Wattributes, "%qE attribute ignored", name); | |
6061 *no_add_attrs = true; | |
6062 } | |
6063 } | |
6064 else if (TREE_CODE (*node) == POINTER_TYPE | |
6065 && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE | |
6066 || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE) | |
6067 && csky_isr_value (args) != CSKY_FT_UNKNOWN) | |
6068 { | |
6069 *node = build_variant_type_copy (*node); | |
6070 TREE_TYPE (*node) = build_type_attribute_variant (TREE_TYPE (*node), | |
6071 tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node)))); | |
6072 *no_add_attrs = true; | |
6073 } | |
6074 else if (flags & ((int)ATTR_FLAG_DECL_NEXT | |
6075 | (int)ATTR_FLAG_FUNCTION_NEXT | |
6076 | (int)ATTR_FLAG_ARRAY_NEXT)) | |
6077 { | |
6078 *no_add_attrs = true; | |
6079 return tree_cons (name, args, NULL_TREE); | |
6080 } | |
6081 else | |
6082 warning (OPT_Wattributes, "%qE attribute ignored", name); | |
6083 } | |
6084 return NULL_TREE; | |
6085 } | |
6086 | |
6087 | |
6088 /* Implement TARGET_REGISTER_MOVE_COST: compute extra cost of moving data | |
6089 between one register class and another. */ | |
6090 | |
6091 int | |
6092 csky_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED, | |
6093 reg_class_t from, reg_class_t to) | |
6094 { | |
6095 #define GR_REG_CLASS_P(CLASS) \ | |
6096 ((CLASS) == GENERAL_REGS || (CLASS) == MINI_REGS || (CLASS) == SP_REGS \ | |
6097 || (CLASS) == LOW_REGS) | |
6098 | |
6099 #define HILO_REG_CLASS_P(CLASS) \ | |
6100 ((CLASS) == HI_REGS || (CLASS) == LO_REGS || (CLASS) == HILO_REGS) | |
6101 | |
6102 #define V_REG_CLASS_P(CLASS) \ | |
6103 ((CLASS) == V_REGS) | |
6104 | |
6105 if (V_REG_CLASS_P (from) && V_REG_CLASS_P (to)) | |
6106 return 2; | |
6107 | |
6108 if ((V_REG_CLASS_P (from) && GR_REG_CLASS_P (to)) | |
6109 || (GR_REG_CLASS_P (from) && V_REG_CLASS_P (to))) | |
6110 return 6; | |
6111 | |
6112 if ((HILO_REG_CLASS_P (from) && GR_REG_CLASS_P (to)) | |
6113 || (GR_REG_CLASS_P (from) && HILO_REG_CLASS_P (to))) | |
6114 return 16; | |
6115 | |
6116 if (HILO_REG_CLASS_P (from) && HILO_REG_CLASS_P (to)) | |
6117 return 32; | |
6118 | |
6119 if ((HILO_REG_CLASS_P (from) && V_REG_CLASS_P (to)) | |
6120 || (V_REG_CLASS_P (from) && HILO_REG_CLASS_P (to))) | |
6121 return 64; | |
6122 | |
6123 return 2; | |
6124 } | |
6125 | |
6126 | |
6127 /* Implement TARGET_MEMORY_MOVE_COST: compute the cost of moving data | |
6128 between registers and memory. */ | |
6129 | |
6130 int | |
6131 csky_memory_move_cost (machine_mode mode, reg_class_t rclass, | |
6132 bool in) | |
6133 { | |
6134 return (4 + memory_move_secondary_cost (mode, rclass, in)); | |
6135 } | |
6136 | |
6137 | |
6138 /* TARGET_RTX_COSTS helper for ck801/ck802. */ | |
6139 | |
6140 static bool | |
6141 ck802_ck801_rtx_costs (rtx x, int code, int outer_code, int *total, | |
6142 bool speed) | |
6143 { | |
6144 machine_mode mode = GET_MODE (x); | |
6145 switch (code) | |
6146 { | |
6147 /* Accessing memory costs quite a lot for first word; */ | |
6148 case MEM: | |
6149 *total = COSTS_N_INSNS (1 + CSKY_NUM_REGS (mode)); | |
6150 return false; | |
6151 case DIV: | |
6152 case UDIV: | |
6153 case MOD: | |
6154 case UMOD: | |
6155 *total = 100; | |
6156 return true; | |
6157 | |
6158 case ROTATE: | |
6159 case ROTATERT: | |
6160 case ASHIFT: | |
6161 case LSHIFTRT: | |
6162 case ASHIFTRT: | |
6163 if (speed) | |
6164 *total = 2; | |
6165 else | |
6166 *total = COSTS_N_INSNS (1); | |
6167 return false; | |
6168 | |
6169 case MINUS: | |
6170 case PLUS: | |
6171 *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode)); | |
6172 return false; | |
6173 | |
6174 case AND: | |
6175 { | |
6176 enum rtx_code subcode = GET_CODE (XEXP (x, 1)); | |
6177 | |
6178 /* If subcode is "not", we'll try to combine it into e.g. "andn" | |
6179 instruction, so give AND itself zero cost. */ | |
6180 if (subcode == NOT) | |
6181 { | |
6182 *total = 0; | |
6183 return false; | |
6184 } | |
6185 } | |
6186 /* Fall through. */ | |
6187 case XOR: | |
6188 case IOR: | |
6189 *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode)); | |
6190 return false; | |
6191 | |
6192 case MULT: | |
6193 /* FIXME: is ixw supported on ck801/ck802? */ | |
6194 /* We can use "ix.h/w" insn to replace multiply by 2 or 4. | |
6195 "ix.h/w" is a 32-bit insn, so let its cost be a little less than | |
6196 "mult" insn. */ | |
6197 if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) | |
6198 { | |
6199 unsigned HOST_WIDE_INT m | |
6200 = (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1))); | |
6201 if ((m == 2 || m == 4) && outer_code == PLUS) | |
6202 { | |
6203 *total = 2; | |
6204 return true; | |
6205 } | |
6206 else | |
6207 { | |
6208 /* Because mult is relatively slower than other operations, | |
6209 we try to use other insns when optimizing for speed. | |
6210 When optimizing for size, give it lower cost. */ | |
6211 if (speed) | |
6212 { | |
6213 *total = COSTS_N_INSNS (10 * CSKY_NUM_REGS (mode)); | |
6214 return true; | |
6215 } | |
6216 int cycle = 0; | |
6217 while (m) | |
6218 { | |
6219 m >>= 2; | |
6220 cycle++; | |
6221 } | |
6222 *total = COSTS_N_INSNS (1) + cycle; | |
6223 return false; | |
6224 } | |
6225 } | |
6226 if (!speed) | |
6227 *total = COSTS_N_INSNS (1); | |
6228 return false; | |
6229 | |
6230 case NEG: | |
6231 /* Usually, we use subtract from 0 to substitute for neg, and | |
6232 it costs 1 extra insn to move 0 to a register. */ | |
6233 *total = COSTS_N_INSNS (2 * CSKY_NUM_REGS (mode)); | |
6234 return false; | |
6235 | |
6236 case NOT: | |
6237 *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode)); | |
6238 return false; | |
6239 | |
6240 case COMPARE: | |
6241 *total = COSTS_N_INSNS (1); | |
6242 return false; | |
6243 | |
6244 case SIGN_EXTEND: | |
6245 case ZERO_EXTEND: | |
6246 *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode)); | |
6247 return false; | |
6248 | |
6249 case SIGN_EXTRACT: | |
6250 case ZERO_EXTRACT: | |
6251 if (REG_P (XEXP (x, 0)) | |
6252 && CONST_INT_P (XEXP (x, 1)) | |
6253 && CONST_INT_P (XEXP (x, 2)) | |
6254 && INTVAL (XEXP (x, 1)) == 8 | |
6255 && INTVAL (XEXP (x, 2)) % 8 == 0) | |
6256 { | |
6257 *total = COSTS_N_INSNS (1); | |
6258 return true; | |
6259 } | |
6260 *total = COSTS_N_INSNS (CSKY_NUM_REGS (mode)); | |
6261 return false; | |
6262 | |
6263 case CONST_INT: | |
6264 { | |
6265 unsigned HOST_WIDE_INT t = (unsigned HOST_WIDE_INT) (INTVAL (x)); | |
6266 | |
6267 if (outer_code == COMPARE) | |
6268 { | |
6269 if (t < 0x10000) | |
6270 *total = 0; | |
6271 else | |
6272 *total = COSTS_N_INSNS (2); | |
6273 } | |
6274 else if (outer_code == AND || outer_code == IOR || outer_code == XOR) | |
6275 { | |
6276 /* "andi,xori,ori" are 32-bit insns, so let it cost a | |
6277 little more. */ | |
6278 if (t < 0x1000) | |
6279 { | |
6280 /* Try replacing "andi" by "sextb/h", so let it cost more. */ | |
6281 if (outer_code == AND && (t == 0xff || t == 0xffff)) | |
6282 { | |
6283 *total = 8; | |
6284 return true; | |
6285 } | |
6286 *total = 2; | |
6287 } | |
6288 else if (t < 0x10000) | |
6289 *total = COSTS_N_INSNS (1); | |
6290 else | |
6291 *total = COSTS_N_INSNS (2); | |
6292 } | |
6293 else if (outer_code == PLUS || outer_code == MINUS) | |
6294 { | |
6295 /* "addi/subi rx,ry,imm", if imm<9, it is more often a | |
6296 16-bit insn. If imm>=9, use "movi" insn; it's probably | |
6297 less than "addi/subi". */ | |
6298 if (t < 9) | |
6299 *total = 0; | |
6300 else if (t < 0x1000) | |
6301 *total = 2; | |
6302 else if (t < 0x10000) | |
6303 *total = COSTS_N_INSNS (1); | |
6304 else | |
6305 *total = COSTS_N_INSNS (2); | |
6306 } | |
6307 else if (outer_code == ROTATE || outer_code == ROTATERT | |
6308 || outer_code == LSHIFTRT || outer_code == ASHIFTRT | |
6309 || outer_code == ASHIFT) | |
6310 { | |
6311 if (t < 32) | |
6312 *total = 0; | |
6313 else | |
6314 *total = COSTS_N_INSNS (2); | |
6315 } | |
6316 else | |
6317 { | |
6318 if (t < 0x10000) | |
6319 if (outer_code == SET && t < 256) | |
6320 *total = 0; | |
6321 else | |
6322 *total = COSTS_N_INSNS (1); | |
6323 else | |
6324 *total = COSTS_N_INSNS (2); | |
6325 } | |
6326 } | |
6327 return true; | |
6328 | |
6329 case CONST: | |
6330 case LABEL_REF: | |
6331 case SYMBOL_REF: | |
6332 *total = COSTS_N_INSNS (3); | |
6333 return true; | |
6334 default: | |
6335 return false; | |
6336 } | |
6337 } | |
6338 | |
6339 | |
6340 /* TARGET_RTX_COSTS helper for ck803. */ | |
6341 | |
6342 static bool | |
6343 ck803_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, | |
6344 int *total, bool speed ATTRIBUTE_UNUSED) | |
6345 { | |
6346 switch (code) | |
6347 { | |
6348 case SET: | |
6349 if (MEM_P (XEXP (x, 1))) | |
6350 { | |
6351 struct csky_address op1; | |
6352 bool address_valid | |
6353 = decompose_csky_address (XEXP (XEXP (x, 1), 0), &op1); | |
6354 if (op1.index) | |
6355 { | |
6356 *total = COSTS_N_INSNS (3); | |
6357 return true; | |
6358 } | |
6359 else if (address_valid) | |
6360 { | |
6361 *total = COSTS_N_INSNS (1); | |
6362 return true; | |
6363 } | |
6364 } | |
6365 if (REG_P (XEXP (x, 0)) && (GET_CODE (XEXP (x, 1)) == PLUS)) | |
6366 { | |
6367 rtx sub_exp = XEXP (x, 1); | |
6368 if (REG_P (XEXP (sub_exp, 0)) && REG_P (XEXP (sub_exp, 1))) | |
6369 { | |
6370 *total = COSTS_N_INSNS (1); | |
6371 return true; | |
6372 } | |
6373 } | |
6374 return false; | |
6375 case MULT: | |
6376 if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) | |
6377 { | |
6378 HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); | |
6379 if (val % 2 == 0 && val < 0xffffffff && val > 0) | |
6380 { | |
6381 *total = COSTS_N_INSNS (1); | |
6382 return true; | |
6383 } | |
6384 } | |
6385 return false; | |
6386 | |
6387 case CONST: | |
6388 case LABEL_REF: | |
6389 case SYMBOL_REF: | |
6390 *total = COSTS_N_INSNS (3); | |
6391 return true; | |
6392 default: | |
6393 return false; | |
6394 } | |
6395 } | |
6396 | |
6397 /* TARGET_RTX_COSTS helper for ck807+ arches. */ | |
6398 | |
6399 static bool | |
6400 ck807_ck810_rtx_costs (rtx x, int code, | |
6401 int outer_code ATTRIBUTE_UNUSED, | |
6402 int *total, bool speed ATTRIBUTE_UNUSED) | |
6403 { | |
6404 switch (code) | |
6405 { | |
6406 case MULT: | |
6407 if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) | |
6408 { | |
6409 HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); | |
6410 if (val % 2 == 0 && val < 0xffffffff && val > 0) | |
6411 { | |
6412 *total = COSTS_N_INSNS (1); | |
6413 return true; | |
6414 } | |
6415 } | |
6416 return false; | |
6417 | |
6418 case CONST: | |
6419 case LABEL_REF: | |
6420 case SYMBOL_REF: | |
6421 *total = COSTS_N_INSNS (3); | |
6422 return true; | |
6423 default: | |
6424 return false; | |
6425 } | |
6426 } | |
6427 | |
6428 | |
6429 /* Implement TARGET_RTX_COSTS, to compute a (partial) cost for rtx X. | |
6430 Return true if the complete cost has been computed, and false if | |
6431 subexpressions should be scanned. In either case, *TOTAL contains | |
6432 the cost result. */ | |
6433 | |
6434 static bool | |
6435 csky_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code, | |
6436 int opno ATTRIBUTE_UNUSED, int *total, bool speed) | |
6437 { | |
6438 int code = GET_CODE (x); | |
6439 | |
6440 if (CSKY_TARGET_ARCH (CK802) || CSKY_TARGET_ARCH (CK801)) | |
6441 return ck802_ck801_rtx_costs (x, code, outer_code, total, speed); | |
6442 else if (CSKY_TARGET_ARCH (CK803)) | |
6443 return ck803_rtx_costs (x, code, outer_code, total, speed); | |
6444 else if (CSKY_TARGET_ARCH (CK807) || CSKY_TARGET_ARCH (CK810)) | |
6445 return ck807_ck810_rtx_costs (x, code, outer_code, total, speed); | |
6446 else | |
6447 gcc_unreachable (); | |
6448 } | |
6449 | |
6450 /* Emit assembly code for CASESI. This is only used on CK801 and CK802 | |
6451 when optimizing for size, and uses helper functions in libgcc instead | |
6452 of doing the control transfer inline. */ | |
6453 | |
6454 const char * | |
6455 csky_output_casesi (rtx *operands) | |
6456 { | |
6457 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[0]))); | |
6458 | |
6459 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); | |
6460 | |
6461 switch (GET_MODE (diff_vec)) | |
6462 { | |
6463 case E_QImode: | |
6464 return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned | |
6465 ? "jbsr\t___gnu_csky_case_uqi" | |
6466 : "jbsr\t___gnu_csky_case_sqi"); | |
6467 case E_HImode: | |
6468 return (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned | |
6469 ? "jbsr\t___gnu_csky_case_uhi" | |
6470 : "jbsr\t___gnu_csky_case_shi"); | |
6471 case E_SImode: | |
6472 return "jbsr\t___gnu_csky_case_si"; | |
6473 default: | |
6474 gcc_unreachable (); | |
6475 } | |
6476 } | |
6477 | |
6478 /* Implement TARGET_SCHED_ISSUE_RATE. Lookup the issue rate in the | |
6479 per-core tuning structs. */ | |
6480 static int | |
6481 csky_sched_issue_rate (void) | |
6482 { | |
6483 if (CSKY_TARGET_ARCH (CK810)) | |
6484 return 2; | |
6485 else | |
6486 return 1; | |
6487 } | |
6488 | |
6489 | |
6490 /* This function implements the target macro TARGET_SCHED_ADJUST_COST. | |
6491 It corrects the value of COST based on the relationship between | |
6492 INSN and DEP through the dependence DEP_TYPE. It returns the new | |
6493 value. */ | |
6494 | |
6495 static int | |
6496 csky_sched_adjust_cost (rtx_insn *insn, | |
6497 int dep_type, | |
6498 rtx_insn *dep, | |
6499 int cost, | |
6500 unsigned int dw ATTRIBUTE_UNUSED) | |
6501 { | |
6502 if (dep_type == REG_DEP_ANTI || dep_type == REG_DEP_OUTPUT) | |
6503 return 0; | |
6504 /* The REG_DEP_TRUE situation. */ | |
6505 else if (recog_memoized (insn) >= 0 && recog_memoized (dep) >= 0) | |
6506 { | |
6507 enum attr_type insn_type = get_attr_type (insn); | |
6508 if (CSKY_TARGET_ARCH (CK803)) | |
6509 { | |
6510 /* The ld or st's base reg depends on the pre insn, | |
6511 it will delay 1 cycle. */ | |
6512 if (insn_type == TYPE_LOAD || insn_type == TYPE_STORE) | |
6513 { | |
6514 rtx pattern = PATTERN (insn); | |
6515 | |
6516 gcc_assert (GET_CODE (pattern) == SET); | |
6517 rtx addr = (insn_type == TYPE_LOAD | |
6518 ? SET_SRC (pattern) : SET_DEST (pattern)); | |
6519 | |
6520 enum rtx_code code = GET_CODE (addr); | |
6521 if (code == ZERO_EXTEND || code == SIGN_EXTEND) | |
6522 addr = XEXP (addr, 0); | |
6523 gcc_assert (GET_CODE (addr) == MEM); | |
6524 | |
6525 rtx base = XEXP (addr, 0); | |
6526 rtx reg = NULL_RTX; | |
6527 if (REG_P (base)) | |
6528 reg = base; | |
6529 if (GET_CODE (base) == PLUS | |
6530 && GET_CODE (XEXP (base, 0)) == REG) | |
6531 reg = XEXP (base, 0); | |
6532 if ((reg != NULL_RTX) && reg_set_p (reg, PATTERN (dep))) | |
6533 return 2; | |
6534 } | |
6535 } | |
6536 else if (CSKY_TARGET_ARCH (CK802)) | |
6537 { | |
6538 if ((insn_type == TYPE_CALL_JSR || insn_type == TYPE_BRANCH_JMP) | |
6539 && get_attr_type (dep) != TYPE_LOAD) | |
6540 return 1; | |
6541 | |
6542 if (insn_type == TYPE_LOAD || insn_type == TYPE_STORE) | |
6543 { | |
6544 rtx pattern = PATTERN (insn); | |
6545 | |
6546 gcc_assert (GET_CODE (pattern) == SET); | |
6547 | |
6548 rtx addr = (insn_type == TYPE_LOAD | |
6549 ? SET_SRC (pattern) : SET_DEST (pattern)); | |
6550 | |
6551 enum rtx_code code = GET_CODE (addr); | |
6552 if (code == ZERO_EXTEND || code == SIGN_EXTEND) | |
6553 addr = XEXP (addr, 0); | |
6554 gcc_assert (GET_CODE (addr) == MEM); | |
6555 | |
6556 rtx base = XEXP (addr, 0); | |
6557 rtx reg = NULL_RTX; | |
6558 if (REG_P (base)) | |
6559 reg = base; | |
6560 if (GET_CODE (base) == PLUS | |
6561 && GET_CODE (XEXP (base, 0)) == REG) | |
6562 reg = XEXP (base, 0); | |
6563 if ((reg != NULL_RTX) && reg_set_p (reg, PATTERN (dep)) | |
6564 && get_attr_type (dep) != TYPE_LOAD) | |
6565 return 1; | |
6566 | |
6567 if (insn_type == TYPE_STORE | |
6568 && reg_referenced_p (SET_SRC (pattern), PATTERN (dep))) | |
6569 return 1; | |
6570 } | |
6571 } | |
6572 } | |
6573 return cost; | |
6574 } | |
6575 | |
6576 static bool | |
6577 csky_warn_func_return (tree decl) | |
6578 { | |
6579 /* Naked functions are implemented entirely in assembly, including the | |
6580 return sequence, so suppress warnings about this. */ | |
6581 return lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) == NULL_TREE; | |
6582 } | |
6583 | |
6584 | |
6585 /* Implement TARGET_RETURN_IN_MEMORY to decide whether TYPE should be | |
6586 returned in memory (true) or in a register (false). | |
6587 FNTYPE is the type of the function making the call. */ | |
6588 static bool | |
6589 csky_return_in_memory (const_tree type, | |
6590 const_tree fntype ATTRIBUTE_UNUSED) | |
6591 { | |
6592 const HOST_WIDE_INT size = int_size_in_bytes (type); | |
6593 return (size == -1 || size > 2 * UNITS_PER_WORD); | |
6594 } | |
6595 | |
6596 | |
6597 /* Implement TARGET_DWARF_REGISTER_SPAN. | |
6598 Dwarf models VFP registers as 64-bit or 128-bit registers default. | |
6599 GCC models tham as 32-bit registers, so we need to describe this to | |
6600 the DWARF generation code. Other registers can use the default. */ | |
6601 static rtx | |
6602 csky_dwarf_register_span (rtx rtl) | |
6603 { | |
6604 machine_mode mode; | |
6605 unsigned regno; | |
6606 rtx parts[16]; | |
6607 int nregs; | |
6608 int i; | |
6609 | |
6610 regno = REGNO (rtl); | |
6611 if (!CSKY_VREG_P (regno)) | |
6612 return NULL_RTX; | |
6613 | |
6614 mode = GET_MODE (rtl); | |
6615 if (GET_MODE_SIZE (mode) < 8) | |
6616 return NULL_RTX; | |
6617 | |
6618 if (TARGET_SOFT_FPU) | |
6619 { | |
6620 nregs = GET_MODE_SIZE (mode) / 4; | |
6621 for (i = 0; i < nregs; i += 2) | |
6622 if (TARGET_BIG_ENDIAN) | |
6623 { | |
6624 parts[i] = gen_rtx_REG (SImode, regno + i + 1); | |
6625 parts[i + 1] = gen_rtx_REG (SImode, regno + i); | |
6626 } | |
6627 else | |
6628 { | |
6629 parts[i] = gen_rtx_REG (SImode, regno + i); | |
6630 parts[i + 1] = gen_rtx_REG (SImode, regno + i + 1); | |
6631 } | |
6632 } | |
6633 else | |
6634 { | |
6635 /* FIXME: dwarf2 considers all general registers to be the same | |
6636 as the CPU bit width. Transform the 64-bit FPU registers to | |
6637 32 bits here, and we will modify the unwind processing to | |
6638 fit CSKY architecture later. */ | |
6639 nregs = GET_MODE_SIZE (mode) / 8; | |
6640 for (i = 0; i < nregs; i++) | |
6641 parts[i] = gen_rtx_REG (SImode, regno + i); | |
6642 } | |
6643 | |
6644 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nregs , parts)); | |
6645 } | |
6646 | |
6647 /* Implement TARGET_INIT_LIBFUNCS. */ | |
6648 | |
6649 static void | |
6650 csky_init_libfuncs (void) | |
6651 { | |
6652 if (TARGET_CSKY_LINUX) | |
6653 init_sync_libfuncs (UNITS_PER_WORD); | |
6654 if (!TARGET_LIBCCRT) | |
6655 return; | |
6656 | |
6657 #define CSKY_GCC_SYM(sym) "__csky_ccrt_" # sym | |
6658 | |
6659 /* int */ | |
6660 | |
6661 /* Arithmetic functions */ | |
6662 set_optab_libfunc (ashl_optab, DImode, CSKY_GCC_SYM (ashldi3)); | |
6663 set_optab_libfunc (ashr_optab, DImode, CSKY_GCC_SYM (ashrdi3)); | |
6664 set_optab_libfunc (sdiv_optab, SImode, CSKY_GCC_SYM (divsi3)); | |
6665 set_optab_libfunc (sdiv_optab, DImode, CSKY_GCC_SYM (divdi3)); | |
6666 set_optab_libfunc (lshr_optab, DImode, CSKY_GCC_SYM (lshrdi3)); | |
6667 set_optab_libfunc (smod_optab, SImode, CSKY_GCC_SYM (modsi3)); | |
6668 set_optab_libfunc (smod_optab, DImode, CSKY_GCC_SYM (moddi3)); | |
6669 set_optab_libfunc (smul_optab, DImode, CSKY_GCC_SYM (muldi3)); | |
6670 set_optab_libfunc (neg_optab, DImode, CSKY_GCC_SYM (negdi2)); | |
6671 set_optab_libfunc (udiv_optab, SImode, CSKY_GCC_SYM (udivsi3)); | |
6672 set_optab_libfunc (udiv_optab, DImode, CSKY_GCC_SYM (udivdi3)); | |
6673 set_optab_libfunc (udivmod_optab, DImode, CSKY_GCC_SYM (udivmoddi4)); | |
6674 set_optab_libfunc (umod_optab, SImode, CSKY_GCC_SYM (umodsi3)); | |
6675 set_optab_libfunc (umod_optab, DImode, CSKY_GCC_SYM (umoddi3)); | |
6676 | |
6677 /* Comparison functions */ | |
6678 set_optab_libfunc (cmp_optab, DImode, CSKY_GCC_SYM (cmpdi2)); | |
6679 set_optab_libfunc (ucmp_optab, DImode, CSKY_GCC_SYM (ucmpdi2)); | |
6680 | |
6681 /* Trapping arithmetic functions */ | |
6682 set_optab_libfunc (absv_optab, SImode, CSKY_GCC_SYM (absvsi2)); | |
6683 set_optab_libfunc (absv_optab, DImode, CSKY_GCC_SYM (absvdi2)); | |
6684 set_optab_libfunc (addv_optab, SImode, CSKY_GCC_SYM (addvsi3)); | |
6685 set_optab_libfunc (addv_optab, DImode, CSKY_GCC_SYM (addvdi3)); | |
6686 set_optab_libfunc (smulv_optab, SImode, CSKY_GCC_SYM (mulvsi3)); | |
6687 set_optab_libfunc (smulv_optab, DImode, CSKY_GCC_SYM (mulvdi3)); | |
6688 set_optab_libfunc (negv_optab, SImode, CSKY_GCC_SYM (negvsi2)); | |
6689 set_optab_libfunc (negv_optab, DImode, CSKY_GCC_SYM (negvdi2)); | |
6690 set_optab_libfunc (subv_optab, SImode, CSKY_GCC_SYM (subvsi3)); | |
6691 set_optab_libfunc (subv_optab, DImode, CSKY_GCC_SYM (subvdi3)); | |
6692 | |
6693 /* Bit operations */ | |
6694 set_optab_libfunc (clz_optab, SImode, CSKY_GCC_SYM (clzsi2)); | |
6695 set_optab_libfunc (clz_optab, DImode, CSKY_GCC_SYM (clzdi2)); | |
6696 set_optab_libfunc (ctz_optab, SImode, CSKY_GCC_SYM (ctzsi2)); | |
6697 set_optab_libfunc (ctz_optab, DImode, CSKY_GCC_SYM (ctzdi2)); | |
6698 set_optab_libfunc (ffs_optab, DImode, CSKY_GCC_SYM (ffsdi2)); | |
6699 set_optab_libfunc (parity_optab, SImode, CSKY_GCC_SYM (paritysi2)); | |
6700 set_optab_libfunc (parity_optab, DImode, CSKY_GCC_SYM (paritydi2)); | |
6701 set_optab_libfunc (popcount_optab,SImode, CSKY_GCC_SYM (popcountsi2)); | |
6702 set_optab_libfunc (popcount_optab,DImode, CSKY_GCC_SYM (popcountdi2)); | |
6703 set_optab_libfunc (bswap_optab, SImode, CSKY_GCC_SYM (bswapsi2)); | |
6704 set_optab_libfunc (bswap_optab, DImode, CSKY_GCC_SYM (bswapdi2)); | |
6705 | |
6706 /* float */ | |
6707 | |
6708 /* Arithmetic functions */ | |
6709 set_optab_libfunc (add_optab, SFmode, CSKY_GCC_SYM (addsf3)); | |
6710 set_optab_libfunc (add_optab, DFmode, CSKY_GCC_SYM (adddf3)); | |
6711 set_optab_libfunc (sub_optab, SFmode, CSKY_GCC_SYM (subsf3)); | |
6712 set_optab_libfunc (sub_optab, DFmode, CSKY_GCC_SYM (subdf3)); | |
6713 set_optab_libfunc (smul_optab, SFmode, CSKY_GCC_SYM (mulsf3)); | |
6714 set_optab_libfunc (smul_optab, DFmode, CSKY_GCC_SYM (muldf3)); | |
6715 set_optab_libfunc (sdiv_optab, SFmode, CSKY_GCC_SYM (divsf3)); | |
6716 set_optab_libfunc (sdiv_optab, DFmode, CSKY_GCC_SYM (divdf3)); | |
6717 set_optab_libfunc (neg_optab, SFmode, CSKY_GCC_SYM (negsf2)); | |
6718 set_optab_libfunc (neg_optab, DFmode, CSKY_GCC_SYM (negdf2)); | |
6719 | |
6720 /* Conversion functions */ | |
6721 set_conv_libfunc (sext_optab, DFmode, SFmode, CSKY_GCC_SYM (extendsfdf2)); | |
6722 set_conv_libfunc (trunc_optab, SFmode, DFmode, CSKY_GCC_SYM (truncdfsf2)); | |
6723 set_conv_libfunc (sfix_optab, SImode, SFmode, CSKY_GCC_SYM (fixsfsi)); | |
6724 set_conv_libfunc (sfix_optab, SImode, DFmode, CSKY_GCC_SYM (fixdfsi)); | |
6725 set_conv_libfunc (sfix_optab, DImode, SFmode, CSKY_GCC_SYM (fixsfdi)); | |
6726 set_conv_libfunc (sfix_optab, DImode, DFmode, CSKY_GCC_SYM (fixdfdi)); | |
6727 set_conv_libfunc (ufix_optab, SImode, SFmode, CSKY_GCC_SYM (fixunssfsi)); | |
6728 set_conv_libfunc (ufix_optab, SImode, DFmode, CSKY_GCC_SYM (fixunsdfsi)); | |
6729 set_conv_libfunc (ufix_optab, DImode, SFmode, CSKY_GCC_SYM (fixunssfdi)); | |
6730 set_conv_libfunc (ufix_optab, DImode, DFmode, CSKY_GCC_SYM (fixunsdfdi)); | |
6731 set_conv_libfunc (sfloat_optab, SFmode, SImode, CSKY_GCC_SYM (floatsisf)); | |
6732 set_conv_libfunc (sfloat_optab, DFmode, SImode, CSKY_GCC_SYM (floatsidf)); | |
6733 set_conv_libfunc (sfloat_optab, SFmode, DImode, CSKY_GCC_SYM (floatdisf)); | |
6734 set_conv_libfunc (sfloat_optab, DFmode, DImode, CSKY_GCC_SYM (floatdidf)); | |
6735 set_conv_libfunc (ufloat_optab, SFmode, SImode, CSKY_GCC_SYM (floatunsisf)); | |
6736 set_conv_libfunc (ufloat_optab, DFmode, SImode, CSKY_GCC_SYM (floatunsidf)); | |
6737 set_conv_libfunc (ufloat_optab, SFmode, DImode, CSKY_GCC_SYM (floatundisf)); | |
6738 set_conv_libfunc (ufloat_optab, DFmode, DImode, CSKY_GCC_SYM (floatundidf)); | |
6739 | |
6740 /* Comparison functions */ | |
6741 set_optab_libfunc (cmp_optab, SFmode, CSKY_GCC_SYM (cmpsf2)); | |
6742 set_optab_libfunc (cmp_optab, DFmode, CSKY_GCC_SYM (cmpdf2)); | |
6743 set_optab_libfunc (unord_optab, SFmode, CSKY_GCC_SYM (unordsf2)); | |
6744 set_optab_libfunc (unord_optab, DFmode, CSKY_GCC_SYM (unorddf2)); | |
6745 set_optab_libfunc (eq_optab, SFmode, CSKY_GCC_SYM (eqsf2)); | |
6746 set_optab_libfunc (eq_optab, DFmode, CSKY_GCC_SYM (eqdf2)); | |
6747 set_optab_libfunc (ne_optab, SFmode, CSKY_GCC_SYM (nesf2)); | |
6748 set_optab_libfunc (ne_optab, DFmode, CSKY_GCC_SYM (nedf2)); | |
6749 set_optab_libfunc (ge_optab, SFmode, CSKY_GCC_SYM (gesf2)); | |
6750 set_optab_libfunc (ge_optab, DFmode, CSKY_GCC_SYM (gedf2)); | |
6751 set_optab_libfunc (lt_optab, SFmode, CSKY_GCC_SYM (ltsf2)); | |
6752 set_optab_libfunc (lt_optab, DFmode, CSKY_GCC_SYM (ltdf2)); | |
6753 set_optab_libfunc (le_optab, SFmode, CSKY_GCC_SYM (lesf2)); | |
6754 set_optab_libfunc (le_optab, DFmode, CSKY_GCC_SYM (ledf2)); | |
6755 set_optab_libfunc (gt_optab, SFmode, CSKY_GCC_SYM (gtsf2)); | |
6756 set_optab_libfunc (gt_optab, DFmode, CSKY_GCC_SYM (gtdf2)); | |
6757 } | |
6758 | |
6759 | |
6760 /* Implement TARGET_ADDRESS_COST to estimate cost of the memory address X. | |
6761 For C-SKY, (register) and (register + offset) have the same cost. | |
6762 Other situations cost more. */ | |
6763 | |
6764 static int | |
6765 csky_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED, | |
6766 addr_space_t as ATTRIBUTE_UNUSED, | |
6767 bool speed ATTRIBUTE_UNUSED) | |
6768 { | |
6769 enum rtx_code code = GET_CODE (x); | |
6770 | |
6771 if (code == REG) | |
6772 return COSTS_N_INSNS (1); | |
6773 if (code == PLUS | |
6774 && REG_P (XEXP (x, 0)) | |
6775 && CONST_INT_P (XEXP (x, 1))) | |
6776 return COSTS_N_INSNS (1); | |
6777 | |
6778 return COSTS_N_INSNS (3); | |
6779 } | |
6780 | |
6781 | |
6782 /* Implement TARGET_FIXED_CONDITION_CODE_REGS. */ | |
6783 | |
6784 static bool | |
6785 csky_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) | |
6786 { | |
6787 *p1 = CSKY_CC_REGNUM; | |
6788 *p2 = INVALID_REGNUM; | |
6789 return true; | |
6790 } | |
6791 | |
6792 | |
6793 struct gcc_target targetm = TARGET_INITIALIZER; | |
6794 | |
6795 #include "gt-csky.h" |