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