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