gcc/
[official-gcc.git] / gcc / config / cr16 / cr16.c
blob73653325efb5621980ed7d569925d5387de33f87
1 /* Output routines for CR16 processor.
2 Copyright (C) 2012-2015 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 "tm.h"
25 #include "rtl.h"
26 #include "alias.h"
27 #include "symtab.h"
28 #include "tree.h"
29 #include "fold-const.h"
30 #include "stor-layout.h"
31 #include "calls.h"
32 #include "tm_p.h"
33 #include "regs.h"
34 #include "hard-reg-set.h"
35 #include "insn-config.h"
36 #include "conditions.h"
37 #include "output.h"
38 #include "insn-codes.h"
39 #include "insn-attr.h"
40 #include "flags.h"
41 #include "except.h"
42 #include "function.h"
43 #include "recog.h"
44 #include "expmed.h"
45 #include "dojump.h"
46 #include "explow.h"
47 #include "emit-rtl.h"
48 #include "varasm.h"
49 #include "stmt.h"
50 #include "expr.h"
51 #include "optabs.h"
52 #include "diagnostic-core.h"
53 #include "predict.h"
54 #include "dominance.h"
55 #include "cfg.h"
56 #include "cfgrtl.h"
57 #include "cfganal.h"
58 #include "lcm.h"
59 #include "cfgbuild.h"
60 #include "cfgcleanup.h"
61 #include "basic-block.h"
62 #include "target.h"
63 #include "df.h"
64 #include "builtins.h"
66 #include "target-def.h"
68 /* Definitions. */
70 /* Maximum number of register used for passing parameters. */
71 #define MAX_REG_FOR_PASSING_ARGS 6
73 /* Minimum number register used for passing parameters. */
74 #define MIN_REG_FOR_PASSING_ARGS 2
76 /* The maximum count of words supported in the assembly of the architecture in
77 a push/pop instruction. */
78 #define MAX_COUNT 8
80 /* Predicate is true if the current function is a 'noreturn' function,
81 i.e. it is qualified as volatile. */
82 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
84 /* Predicate that holds when we need to save registers even for 'noreturn'
85 functions, to accommodate for unwinding. */
86 #define MUST_SAVE_REGS_P() \
87 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
89 /* Nonzero if the rtx X is a signed const int of n bits. */
90 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
91 ((GET_CODE (X) == CONST_INT \
92 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
94 /* Nonzero if the rtx X is an unsigned const int of n bits. */
95 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
96 ((GET_CODE (X) == CONST_INT \
97 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
99 /* Structure for stack computations. */
101 /* variable definitions in the struture
102 args_size Number of bytes saved on the stack for local
103 variables
105 reg_size Number of bytes saved on the stack for
106 non-scratch registers
108 total_size The sum of 2 sizes: locals vars and padding byte
109 for saving the registers. Used in expand_prologue()
110 and expand_epilogue()
112 last_reg_to_save Will hold the number of the last register the
113 prologue saves, -1 if no register is saved
115 save_regs[16] Each object in the array is a register number.
116 Mark 1 for registers that need to be saved
118 num_regs Number of registers saved
120 initialized Non-zero if frame size already calculated, not
121 used yet
123 function_makes_calls Does the function make calls ? not used yet. */
125 struct cr16_frame_info
127 unsigned long var_size;
128 unsigned long args_size;
129 unsigned int reg_size;
130 unsigned long total_size;
131 long last_reg_to_save;
132 long save_regs[FIRST_PSEUDO_REGISTER];
133 int num_regs;
134 int initialized;
135 int function_makes_calls;
138 /* Current frame information calculated by cr16_compute_frame_size. */
139 static struct cr16_frame_info current_frame_info;
141 /* Static Variables. */
143 /* Data model that was supplied by user via command line option
144 This will be overridden in case of invalid combination
145 of core and data model options are supplied. */
146 static enum data_model_type data_model = DM_DEFAULT;
148 /* TARGETM Function Prototypes and forward declarations */
149 static void cr16_print_operand (FILE *, rtx, int);
150 static void cr16_print_operand_address (FILE *, rtx);
152 /* Stack layout and calling conventions. */
153 #undef TARGET_STRUCT_VALUE_RTX
154 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
155 #undef TARGET_RETURN_IN_MEMORY
156 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
158 /* Target-specific uses of '__attribute__'. */
159 #undef TARGET_ATTRIBUTE_TABLE
160 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
161 #undef TARGET_NARROW_VOLATILE_BITFIELD
162 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
164 /* EH related. */
165 #undef TARGET_UNWIND_WORD_MODE
166 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
168 /* Override Options. */
169 #undef TARGET_OPTION_OVERRIDE
170 #define TARGET_OPTION_OVERRIDE cr16_override_options
172 /* Conditional register usuage. */
173 #undef TARGET_CONDITIONAL_REGISTER_USAGE
174 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
176 /* Controlling register spills. */
177 #undef TARGET_CLASS_LIKELY_SPILLED_P
178 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
180 /* Passing function arguments. */
181 #undef TARGET_FUNCTION_ARG
182 #define TARGET_FUNCTION_ARG cr16_function_arg
183 #undef TARGET_FUNCTION_ARG_ADVANCE
184 #define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
185 #undef TARGET_RETURN_POPS_ARGS
186 #define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
188 /* Initialize the GCC target structure. */
189 #undef TARGET_FRAME_POINTER_REQUIRED
190 #define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required
191 #undef TARGET_CAN_ELIMINATE
192 #define TARGET_CAN_ELIMINATE cr16_can_eliminate
193 #undef TARGET_LEGITIMIZE_ADDRESS
194 #define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address
195 #undef TARGET_LEGITIMATE_CONSTANT_P
196 #define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p
197 #undef TARGET_LEGITIMATE_ADDRESS_P
198 #define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p
200 /* Returning function value. */
201 #undef TARGET_FUNCTION_VALUE
202 #define TARGET_FUNCTION_VALUE cr16_function_value
203 #undef TARGET_LIBCALL_VALUE
204 #define TARGET_LIBCALL_VALUE cr16_libcall_value
205 #undef TARGET_FUNCTION_VALUE_REGNO_P
206 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
208 /* printing the values. */
209 #undef TARGET_PRINT_OPERAND
210 #define TARGET_PRINT_OPERAND cr16_print_operand
211 #undef TARGET_PRINT_OPERAND_ADDRESS
212 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
214 /* Relative costs of operations. */
215 #undef TARGET_ADDRESS_COST
216 #define TARGET_ADDRESS_COST cr16_address_cost
217 #undef TARGET_REGISTER_MOVE_COST
218 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
219 #undef TARGET_MEMORY_MOVE_COST
220 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
222 /* Table of machine attributes. */
223 static const struct attribute_spec cr16_attribute_table[] = {
224 /* ISRs have special prologue and epilogue requirements. */
225 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
226 affects_type_identity }. */
227 {"interrupt", 0, 0, false, true, true, NULL, false},
228 {NULL, 0, 0, false, false, false, NULL, false}
231 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
232 .?byte directive along with @c is not understood by assembler.
233 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
234 as TARGET_ASM_ALIGNED_xx_OP. */
235 #undef TARGET_ASM_UNALIGNED_HI_OP
236 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
237 #undef TARGET_ASM_UNALIGNED_SI_OP
238 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
239 #undef TARGET_ASM_UNALIGNED_DI_OP
240 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
242 /* Target hook implementations. */
244 /* Implements hook TARGET_RETURN_IN_MEMORY. */
245 static bool
246 cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
248 const HOST_WIDE_INT size = int_size_in_bytes (type);
249 return ((size == -1) || (size > 8));
252 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
253 static bool
254 cr16_class_likely_spilled_p (reg_class_t rclass)
256 if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS
257 || (rclass) == LONG_REGS || (rclass) == GENERAL_REGS)
258 return true;
260 return false;
263 static int
264 cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
265 tree funtype ATTRIBUTE_UNUSED,
266 int size ATTRIBUTE_UNUSED)
268 return 0;
271 /* Returns true if data model selected via command line option
272 is same as function argument. */
273 bool
274 cr16_is_data_model (enum data_model_type model)
276 return (model == data_model);
279 /* Parse relevant options and override. */
280 static void
281 cr16_override_options (void)
283 /* Disable -fdelete-null-pointer-checks option for CR16 target.
284 Programs which rely on NULL pointer dereferences _not_ halting the
285 program may not work properly with this option. So disable this
286 option. */
287 flag_delete_null_pointer_checks = 0;
289 /* FIXME: To avoid spill_failure ICE during exception handling,
290 * disable cse_fllow_jumps. The spill error occurs when compiler
291 * can't find a suitable candidate in GENERAL_REGS class to reload
292 * a 32bit register.
293 * Need to find a better way of avoiding this situation. */
294 if (flag_exceptions)
295 flag_cse_follow_jumps = 0;
297 /* If -fpic option, data_model == DM_FAR. */
298 if (flag_pic == NEAR_PIC)
300 data_model = DM_FAR;
303 /* The only option we want to examine is data model option. */
304 if (cr16_data_model)
306 if (strcmp (cr16_data_model, "medium") == 0)
307 data_model = DM_DEFAULT;
308 else if (strcmp (cr16_data_model, "near") == 0)
309 data_model = DM_NEAR;
310 else if (strcmp (cr16_data_model, "far") == 0)
312 if (TARGET_CR16CP)
313 data_model = DM_FAR;
314 else
315 error ("data-model=far not valid for cr16c architecture");
317 else
318 error ("invalid data model option -mdata-model=%s", cr16_data_model);
320 else
321 data_model = DM_DEFAULT;
324 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
325 static void
326 cr16_conditional_register_usage (void)
328 if (flag_pic)
330 fixed_regs[12] = call_used_regs[12] = 1;
334 /* Stack layout and calling conventions routines. */
336 /* Return nonzero if the current function being compiled is an interrupt
337 function as specified by the "interrupt" attribute. */
339 cr16_interrupt_function_p (void)
341 tree attributes;
343 attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
344 return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
347 /* Compute values for the array current_frame_info.save_regs and the variable
348 current_frame_info.reg_size. The index of current_frame_info.save_regs
349 is numbers of register, each will get 1 if we need to save it in the
350 current function, 0 if not. current_frame_info.reg_size is the total sum
351 of the registers being saved. */
352 static void
353 cr16_compute_save_regs (void)
355 unsigned int regno;
357 /* Initialize here so in case the function is no-return it will be -1. */
358 current_frame_info.last_reg_to_save = -1;
360 /* Initialize the number of bytes to be saved. */
361 current_frame_info.reg_size = 0;
363 /* No need to save any registers if the function never returns. */
364 if (FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
365 return;
367 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
369 if (fixed_regs[regno])
371 current_frame_info.save_regs[regno] = 0;
372 continue;
375 /* If this reg is used and not call-used (except RA), save it. */
376 if (cr16_interrupt_function_p ())
378 if (!crtl->is_leaf && call_used_regs[regno])
379 /* This is a volatile reg in a non-leaf interrupt routine - save
380 it for the sake of its sons. */
381 current_frame_info.save_regs[regno] = 1;
382 else if (df_regs_ever_live_p (regno))
383 /* This reg is used - save it. */
384 current_frame_info.save_regs[regno] = 1;
385 else
386 /* This reg is not used, and is not a volatile - don't save. */
387 current_frame_info.save_regs[regno] = 0;
389 else
391 /* If this reg is used and not call-used (except RA), save it. */
392 if (df_regs_ever_live_p (regno)
393 && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
394 current_frame_info.save_regs[regno] = 1;
395 else
396 current_frame_info.save_regs[regno] = 0;
400 /* Save registers so the exception handler can modify them. */
401 if (crtl->calls_eh_return)
403 unsigned int i;
405 for (i = 0;; ++i)
407 regno = EH_RETURN_DATA_REGNO (i);
408 if (INVALID_REGNUM == regno)
409 break;
410 current_frame_info.save_regs[regno] = 1;
414 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
415 if (current_frame_info.save_regs[regno] == 1)
417 current_frame_info.last_reg_to_save = regno;
418 if (regno >= CR16_FIRST_DWORD_REGISTER)
419 current_frame_info.reg_size += CR16_UNITS_PER_DWORD;
420 else
421 current_frame_info.reg_size += UNITS_PER_WORD;
425 /* Compute the size of the local area and the size to be adjusted by the
426 prologue and epilogue. */
427 static void
428 cr16_compute_frame (void)
430 /* For aligning the local variables. */
431 int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
432 int padding_locals;
434 /* Padding needed for each element of the frame. */
435 current_frame_info.var_size = get_frame_size ();
437 /* Align to the stack alignment. */
438 padding_locals = current_frame_info.var_size % stack_alignment;
439 if (padding_locals)
440 padding_locals = stack_alignment - padding_locals;
442 current_frame_info.var_size += padding_locals;
443 current_frame_info.total_size = current_frame_info.var_size
444 + (ACCUMULATE_OUTGOING_ARGS
445 ? crtl->outgoing_args_size : 0);
448 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
450 cr16_initial_elimination_offset (int from, int to)
452 /* Compute this since we need to use current_frame_info.reg_size. */
453 cr16_compute_save_regs ();
455 /* Compute this since we need to use current_frame_info.var_size. */
456 cr16_compute_frame ();
458 if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
459 return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
460 else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
461 return (current_frame_info.reg_size + current_frame_info.var_size);
462 else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
463 return (current_frame_info.reg_size + current_frame_info.var_size
464 + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0));
465 else
466 gcc_unreachable ();
469 /* Register Usage. */
471 /* Return the class number of the smallest class containing reg number REGNO.
472 This could be a conditional expression or could index an array. */
473 enum reg_class
474 cr16_regno_reg_class (int regno)
476 if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
477 return SHORT_REGS;
479 if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
480 return LONG_REGS;
482 return NO_REGS;
485 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
487 cr16_hard_regno_mode_ok (int regno, machine_mode mode)
489 if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11))
490 return 0;
492 if (mode == DImode || mode == DFmode)
494 if ((regno > 8) || (regno & 1))
495 return 0;
496 return 1;
499 if ((TARGET_INT32)
500 && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 )))
501 return 0;
503 /* CC can only hold CCmode values. */
504 if (GET_MODE_CLASS (mode) == MODE_CC)
505 return 0;
506 return 1;
509 /* Returns register number for function return value.*/
510 static inline unsigned int
511 cr16_ret_register (void)
513 return 0;
516 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
517 static rtx
518 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
519 int incoming ATTRIBUTE_UNUSED)
521 return gen_rtx_REG (Pmode, cr16_ret_register ());
524 /* Returning function value. */
526 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
527 static bool
528 cr16_function_value_regno_p (const unsigned int regno)
530 return (regno == cr16_ret_register ());
533 /* Create an RTX representing the place where a
534 library function returns a value of mode MODE. */
535 static rtx
536 cr16_libcall_value (machine_mode mode,
537 const_rtx func ATTRIBUTE_UNUSED)
539 return gen_rtx_REG (mode, cr16_ret_register ());
542 /* Create an RTX representing the place where a
543 function returns a value of data type VALTYPE. */
544 static rtx
545 cr16_function_value (const_tree type,
546 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
547 bool outgoing ATTRIBUTE_UNUSED)
549 return gen_rtx_REG (TYPE_MODE (type), cr16_ret_register ());
552 /* Passing function arguments. */
554 /* If enough param regs are available for passing the param of type TYPE return
555 the number of registers needed else 0. */
556 static int
557 enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
558 machine_mode mode)
560 int type_size;
561 int remaining_size;
563 if (mode != BLKmode)
564 type_size = GET_MODE_BITSIZE (mode);
565 else
566 type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
568 remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
569 - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
572 /* Any variable which is too big to pass in two registers, will pass on
573 stack. */
574 if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
575 return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
577 return 0;
580 /* Implements the macro FUNCTION_ARG defined in cr16.h. */
581 static rtx
582 cr16_function_arg (cumulative_args_t cum_v, machine_mode mode,
583 const_tree type, bool named ATTRIBUTE_UNUSED)
585 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
586 cum->last_parm_in_reg = 0;
588 /* function_arg () is called with this type just after all the args have
589 had their registers assigned. The rtx that function_arg returns from
590 this type is supposed to pass to 'gen_call' but currently it is not
591 implemented (see macro GEN_CALL). */
592 if (type == void_type_node)
593 return NULL_RTX;
595 if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
596 return NULL_RTX;
598 if (mode == BLKmode)
600 /* Enable structures that need padding bytes at the end to pass to a
601 function in registers. */
602 if (enough_regs_for_param (cum, type, mode) != 0)
604 cum->last_parm_in_reg = 1;
605 return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
609 if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
610 return NULL_RTX;
611 else
613 if (enough_regs_for_param (cum, type, mode) != 0)
615 cum->last_parm_in_reg = 1;
616 return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
620 return NULL_RTX;
623 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
624 void
625 cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
626 rtx libfunc ATTRIBUTE_UNUSED)
628 tree param, next_param;
630 cum->ints = 0;
632 /* Determine if this function has variable arguments. This is indicated by
633 the last argument being 'void_type_mode' if there are no variable
634 arguments. Change here for a different vararg. */
635 for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
636 param != NULL_TREE; param = next_param)
638 next_param = TREE_CHAIN (param);
639 if ((next_param == NULL_TREE) && (TREE_VALUE (param) != void_type_node))
641 cum->ints = -1;
642 return;
647 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
648 static void
649 cr16_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
650 const_tree type, bool named ATTRIBUTE_UNUSED)
652 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
654 /* l holds the number of registers required. */
655 int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
657 /* If the parameter isn't passed on a register don't advance cum. */
658 if (!cum->last_parm_in_reg)
659 return;
661 if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
662 return;
664 if ((mode == SImode) || (mode == HImode)
665 || (mode == QImode) || (mode == DImode))
667 if (l <= 1)
668 cum->ints += 1;
669 else
670 cum->ints += l;
672 else if ((mode == SFmode) || (mode == DFmode))
673 cum->ints += l;
674 else if ((mode) == BLKmode)
676 if ((l = enough_regs_for_param (cum, type, mode)) != 0)
677 cum->ints += l;
679 return;
682 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
683 Return nonzero if N is a register used for passing parameters. */
685 cr16_function_arg_regno_p (int n)
687 return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
690 /* Addressing modes.
691 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
692 defined in cr16.h. */
694 /* Helper function to check if is a valid base register that can
695 hold address. */
696 static int
697 cr16_addr_reg_p (rtx addr_reg)
699 rtx reg;
701 if (REG_P (addr_reg))
702 reg = addr_reg;
703 else if ((GET_CODE (addr_reg) == SUBREG)
704 && REG_P (SUBREG_REG (addr_reg))
705 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
706 <= UNITS_PER_WORD))
707 reg = SUBREG_REG (addr_reg);
708 else
709 return FALSE;
711 if (GET_MODE (reg) != Pmode)
712 return FALSE;
714 return TRUE;
717 /* Helper functions: Created specifically for decomposing operand of CONST
718 Recursively look into expression x for code or data symbol.
719 The function expects the expression to contain combination of
720 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
721 LABEL_REF, CONST_INT, (PLUS or MINUS)
722 SYMBOL_REF
723 LABEL_REF
724 All other combinations will result in code = -1 and data = ILLEGAL_DM
725 code data
726 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
727 0 DM_FAR SYMBOL_REF was found and it was far data reference.
728 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
729 1 ILLEGAL_DM LABEL_REF was found.
730 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
731 void
732 cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
733 bool treat_as_const)
735 *code = -1;
736 *data = ILLEGAL_DM;
737 switch (GET_CODE (x))
739 case SYMBOL_REF:
740 *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
741 /* 2 indicates func sym. */
742 if (*code == 0)
744 if (CR16_TARGET_DATA_NEAR)
745 *data = DM_DEFAULT;
746 else if (CR16_TARGET_DATA_MEDIUM)
747 *data = DM_FAR;
748 else if (CR16_TARGET_DATA_FAR)
750 if (treat_as_const)
751 /* This will be used only for printing
752 the qualifier. This call is (may be)
753 made by cr16_print_operand_address. */
754 *data = DM_FAR;
755 else
756 /* This call is (may be) made by
757 cr16_legitimate_address_p. */
758 *data = ILLEGAL_DM;
761 return;
763 case LABEL_REF:
764 /* 1 - indicates non-function symbol. */
765 *code = 1;
766 return;
768 case PLUS:
769 case MINUS:
770 /* Look into the tree nodes. */
771 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
772 cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
773 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
774 cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
775 return;
776 default:
777 return;
781 /* Decompose Address
782 This function decomposes the address returns the type of address
783 as defined in enum cr16_addrtype. It also fills the parameter *out.
784 The decomposed address can be used for two purposes. One to
785 check if the address is valid and second to print the address
786 operand.
788 Following tables list valid address supported in CR16C/C+ architectures.
789 Legend:
790 aN : Absoulte address N-bit address
791 R : One 16-bit register
792 RP : Consecutive two 16-bit registers or one 32-bit register
793 I : One 32-bit register
794 dispN : Signed displacement of N-bits
796 ----Code addresses----
797 Branch operands:
798 disp9 : CR16_ABSOLUTE (disp)
799 disp17 : CR16_ABSOLUTE (disp)
800 disp25 : CR16_ABSOLUTE (disp)
801 RP + disp25 : CR16_REGP_REL (base, disp)
803 Jump operands:
804 RP : CR16_REGP_REL (base, disp=0)
805 a24 : CR16_ABSOLUTE (disp)
807 ----Data addresses----
808 a20 : CR16_ABSOLUTE (disp) near (1M)
809 a24 : CR16_ABSOLUTE (disp) medium (16M)
810 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
811 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
812 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
813 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
814 I : *** Valid but port does not support this
815 I + a20 : *** Valid but port does not support this
816 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
817 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
819 Decomposing Data model in case of absolute address.
821 Target Option Address type Resultant Data ref type
822 ---------------------- ------------ -----------------------
823 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
824 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
825 CR16_TARGET_MODEL_NEAR ABS24 Invalid
826 CR16_TARGET_MODEL_NEAR IMM32 Invalid
828 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
829 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
830 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
831 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
833 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
834 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
835 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
836 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
837 enum cr16_addrtype
838 cr16_decompose_address (rtx addr, struct cr16_address *out,
839 bool debug_print, bool treat_as_const)
841 rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
842 enum data_model_type data = ILLEGAL_DM;
843 int code = -1;
844 enum cr16_addrtype retval = CR16_INVALID;
846 switch (GET_CODE (addr))
848 case CONST_INT:
849 /* Absolute address (known at compile time). */
850 code = 0;
851 if (debug_print)
852 fprintf (stderr, "\ncode:%d", code);
853 disp = addr;
855 if (debug_print)
857 fprintf (stderr, "\ndisp:");
858 debug_rtx (disp);
861 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
863 data = DM_DEFAULT;
864 if (debug_print)
865 fprintf (stderr, "\ndata:%d", data);
866 retval = CR16_ABSOLUTE;
868 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
870 if (!CR16_TARGET_DATA_NEAR)
872 data = DM_FAR;
873 if (debug_print)
874 fprintf (stderr, "\ndata:%d", data);
875 retval = CR16_ABSOLUTE;
877 else
878 return CR16_INVALID; /* ABS24 is not support in NEAR model. */
880 else
881 return CR16_INVALID;
882 break;
884 case CONST:
885 /* A CONST is an expression of PLUS or MINUS with
886 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
887 result of assembly-time arithmetic computation. */
888 retval = CR16_ABSOLUTE;
889 disp = addr;
890 /* Call the helper function to check the validity. */
891 cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
892 if ((code == 0) && (data == ILLEGAL_DM))
893 /* CONST is not valid code or data address. */
894 return CR16_INVALID;
895 if (debug_print)
897 fprintf (stderr, "\ndisp:");
898 debug_rtx (disp);
899 fprintf (stderr, "\ncode:%d", code);
900 fprintf (stderr, "\ndata:%d", data);
902 break;
904 case LABEL_REF:
905 retval = CR16_ABSOLUTE;
906 disp = addr;
907 /* 1 - indicates non-function symbol. */
908 code = 1;
909 if (debug_print)
911 fprintf (stderr, "\ndisp:");
912 debug_rtx (disp);
913 fprintf (stderr, "\ncode:%d", code);
915 break;
917 case SYMBOL_REF:
918 /* Absolute address (known at link time). */
919 retval = CR16_ABSOLUTE;
920 disp = addr;
921 /* This is a code address if symbol_ref is a function. */
922 /* 2 indicates func sym. */
923 code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
924 if (debug_print)
926 fprintf (stderr, "\ndisp:");
927 debug_rtx (disp);
928 fprintf (stderr, "\ncode:%d", code);
930 /* If not function ref then check if valid data ref. */
931 if (code == 0)
933 if (CR16_TARGET_DATA_NEAR)
934 data = DM_DEFAULT;
935 else if (CR16_TARGET_DATA_MEDIUM)
936 data = DM_FAR;
937 else if (CR16_TARGET_DATA_FAR)
939 if (treat_as_const)
940 /* This will be used only for printing the
941 qualifier. This call is (may be) made
942 by cr16_print_operand_address. */
943 data = DM_FAR;
944 else
945 /* This call is (may be) made by
946 cr16_legitimate_address_p. */
947 return CR16_INVALID;
949 else
950 data = DM_DEFAULT;
952 if (debug_print)
953 fprintf (stderr, "\ndata:%d", data);
954 break;
956 case REG:
957 case SUBREG:
958 /* Register relative address. */
959 /* Assume REG fits in a single register. */
960 retval = CR16_REG_REL;
961 if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
962 if (!LONG_REG_P (REGNO (addr)))
963 /* REG will result in reg pair. */
964 retval = CR16_REGP_REL;
965 base = addr;
966 if (debug_print)
968 fprintf (stderr, "\nbase:");
969 debug_rtx (base);
971 break;
973 case PLUS:
974 switch (GET_CODE (XEXP (addr, 0)))
976 case REG:
977 case SUBREG:
978 /* REG + DISP20. */
979 /* All Reg relative addresses having a displacement needs
980 to fit in 20-bits. */
981 disp = XEXP (addr, 1);
982 if (debug_print)
984 fprintf (stderr, "\ndisp:");
985 debug_rtx (disp);
987 switch (GET_CODE (XEXP (addr, 1)))
989 case CONST_INT:
990 /* Shall fit in 20-bits. */
991 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
992 return CR16_INVALID;
993 code = 0;
994 if (debug_print)
995 fprintf (stderr, "\ncode:%d", code);
996 break;
998 case UNSPEC:
999 switch (XINT (XEXP (addr, 1), 1))
1001 case UNSPEC_LIBRARY_OFFSET:
1002 default:
1003 gcc_unreachable ();
1005 break;
1007 case LABEL_REF:
1008 case SYMBOL_REF:
1009 case CONST:
1010 /* This is also a valid expression for address.
1011 However, we cannot ascertain if the resultant
1012 displacement will be valid 20-bit value. Therefore,
1013 lets not allow such an expression for now. This will
1014 be updated when we find a way to validate this
1015 expression as legitimate address.
1016 Till then fall through CR16_INVALID. */
1017 default:
1018 return CR16_INVALID;
1021 /* Now check if REG can fit into single or pair regs. */
1022 retval = CR16_REG_REL;
1023 base = XEXP (addr, 0);
1024 if (debug_print)
1026 fprintf (stderr, "\nbase:");
1027 debug_rtx (base);
1029 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
1031 if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
1032 /* REG will result in reg pair. */
1033 retval = CR16_REGP_REL;
1035 break;
1037 case PLUS:
1038 /* Valid expr:
1039 plus
1042 plus idx
1045 reg const_int
1047 Check if the operand 1 is valid index register. */
1048 data = ILLEGAL_DM;
1049 if (debug_print)
1050 fprintf (stderr, "\ndata:%d", data);
1051 switch (GET_CODE (XEXP (addr, 1)))
1053 case REG:
1054 case SUBREG:
1055 if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
1056 return CR16_INVALID;
1057 /* OK. REG is a valid index register. */
1058 index = XEXP (addr, 1);
1059 if (debug_print)
1061 fprintf (stderr, "\nindex:");
1062 debug_rtx (index);
1064 break;
1065 default:
1066 return CR16_INVALID;
1068 /* Check if operand 0 of operand 0 is REGP. */
1069 switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
1071 case REG:
1072 case SUBREG:
1073 /* Now check if REG is a REGP and not in LONG regs. */
1074 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
1075 > BITS_PER_WORD)
1077 if (REGNO (XEXP (XEXP (addr, 0), 0))
1078 >= CR16_FIRST_DWORD_REGISTER)
1079 return CR16_INVALID;
1080 base = XEXP (XEXP (addr, 0), 0);
1081 if (debug_print)
1083 fprintf (stderr, "\nbase:");
1084 debug_rtx (base);
1087 else
1088 return CR16_INVALID;
1089 break;
1090 default:
1091 return CR16_INVALID;
1093 /* Now check if the operand 1 of operand 0 is const_int. */
1094 if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
1096 disp = XEXP (XEXP (addr, 0), 1);
1097 if (debug_print)
1099 fprintf (stderr, "\ndisp:");
1100 debug_rtx (disp);
1102 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
1103 return CR16_INVALID;
1105 else
1106 return CR16_INVALID;
1107 retval = CR16_INDEX_REGP_REL;
1108 break;
1109 default:
1110 return CR16_INVALID;
1112 break;
1114 default:
1115 return CR16_INVALID;
1118 /* Check if the base and index registers are valid. */
1119 if (base && !(cr16_addr_reg_p (base)))
1120 return CR16_INVALID;
1121 if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
1122 return CR16_INVALID;
1123 if (index && !(REG_OK_FOR_INDEX_P (index)))
1124 return CR16_INVALID;
1126 /* Write the decomposition to out parameter. */
1127 out->base = base;
1128 out->disp = disp;
1129 out->index = index;
1130 out->data = data;
1131 out->code = code;
1133 return retval;
1136 /* Return non-zero value if 'x' is legitimate PIC operand
1137 when generating PIC code. */
1139 legitimate_pic_operand_p (rtx x)
1141 switch (GET_CODE (x))
1143 case SYMBOL_REF:
1144 return 0;
1145 break;
1146 case LABEL_REF:
1147 return 0;
1148 break;
1149 case CONST:
1150 /* REVISIT: Use something like symbol_referenced_p. */
1151 if (GET_CODE (XEXP (x, 0)) == PLUS
1152 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
1153 || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
1154 && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
1155 return 0;
1156 break;
1157 case MEM:
1158 return legitimate_pic_operand_p (XEXP (x, 0));
1159 break;
1160 default:
1161 break;
1163 return 1;
1166 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
1168 Input Output (-f pic) Output (-f PIC)
1169 orig reg
1171 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
1173 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
1175 NOTE: @BRO is added using unspec:BRO
1176 NOTE: @GOT is added using unspec:GOT. */
1178 legitimize_pic_address (rtx orig, machine_mode mode ATTRIBUTE_UNUSED,
1179 rtx reg)
1181 /* First handle a simple SYMBOL_REF or LABEL_REF. */
1182 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1184 if (reg == 0)
1185 reg = gen_reg_rtx (Pmode);
1187 if (flag_pic == NEAR_PIC)
1189 /* Unspec to handle -fpic option. */
1190 emit_insn (gen_unspec_bro_addr (reg, orig));
1191 emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
1193 else if (flag_pic == FAR_PIC)
1195 /* Unspec to handle -fPIC option. */
1196 emit_insn (gen_unspec_got_addr (reg, orig));
1198 return reg;
1200 else if (GET_CODE (orig) == CONST)
1202 /* To handle (symbol + offset). */
1203 rtx base, offset;
1205 if (GET_CODE (XEXP (orig, 0)) == PLUS
1206 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1207 return orig;
1209 if (reg == 0)
1211 gcc_assert (can_create_pseudo_p ());
1212 reg = gen_reg_rtx (Pmode);
1215 gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
1217 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
1218 offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1219 base == reg ? 0 : reg);
1221 /* REVISIT: Optimize for const-offsets. */
1222 emit_insn (gen_addsi3 (reg, base, offset));
1224 return reg;
1226 return orig;
1229 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
1230 static bool
1231 cr16_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1232 rtx addr, bool strict)
1234 enum cr16_addrtype addrtype;
1235 struct cr16_address address;
1237 if (TARGET_DEBUG_ADDR)
1239 fprintf (stderr,
1240 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
1241 GET_MODE_NAME (mode), strict);
1242 debug_rtx (addr);
1244 addrtype = cr16_decompose_address (addr, &address,
1245 (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
1247 if (TARGET_DEBUG_ADDR)
1249 const char *typestr;
1251 switch (addrtype)
1253 case CR16_INVALID:
1254 typestr = "invalid";
1255 break;
1256 case CR16_ABSOLUTE:
1257 typestr = "absolute";
1258 break;
1259 case CR16_REG_REL:
1260 typestr = "register relative";
1261 break;
1262 case CR16_REGP_REL:
1263 typestr = "register pair relative";
1264 break;
1265 case CR16_INDEX_REGP_REL:
1266 typestr = "index + register pair relative";
1267 break;
1268 default:
1269 gcc_unreachable ();
1271 fprintf (stderr, "\ncr16 address type: %s\n", typestr);
1274 if (addrtype == CR16_INVALID)
1275 return FALSE;
1277 if (strict)
1279 if (address.base
1280 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
1282 if (TARGET_DEBUG_ADDR)
1283 fprintf (stderr, "base register not strict\n");
1284 return FALSE;
1286 if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
1288 if (TARGET_DEBUG_ADDR)
1289 fprintf (stderr, "index register not strict\n");
1290 return FALSE;
1294 /* Return true if addressing mode is register relative. */
1295 if (flag_pic)
1297 if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
1298 return TRUE;
1299 else
1300 return FALSE;
1303 return TRUE;
1306 /* Routines to compute costs. */
1308 /* Return cost of the memory address x. */
1309 static int
1310 cr16_address_cost (rtx addr, machine_mode mode ATTRIBUTE_UNUSED,
1311 addr_space_t as ATTRIBUTE_UNUSED,
1312 bool speed ATTRIBUTE_UNUSED)
1314 enum cr16_addrtype addrtype;
1315 struct cr16_address address;
1316 int cost = 2;
1318 addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
1320 gcc_assert (addrtype != CR16_INVALID);
1322 /* CR16_ABSOLUTE : 3
1323 CR16_REG_REL (disp !=0) : 4
1324 CR16_REG_REL (disp ==0) : 5
1325 CR16_REGP_REL (disp !=0) : 6
1326 CR16_REGP_REL (disp ==0) : 7
1327 CR16_INDEX_REGP_REL (disp !=0) : 8
1328 CR16_INDEX_REGP_REL (disp ==0) : 9. */
1329 switch (addrtype)
1331 case CR16_ABSOLUTE:
1332 cost += 1;
1333 break;
1334 case CR16_REGP_REL:
1335 cost += 2;
1336 /* Fall through. */
1337 case CR16_REG_REL:
1338 cost += 3;
1339 if (address.disp)
1340 cost -= 1;
1341 break;
1342 case CR16_INDEX_REGP_REL:
1343 cost += 7;
1344 if (address.disp)
1345 cost -= 1;
1346 default:
1347 break;
1350 if (TARGET_DEBUG_ADDR)
1352 fprintf (stderr, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost);
1353 debug_rtx (addr);
1356 return cost;
1360 /* Implement `TARGET_REGISTER_MOVE_COST'. */
1361 static int
1362 cr16_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
1363 reg_class_t from ATTRIBUTE_UNUSED, reg_class_t to)
1365 return (to != GENERAL_REGS ? 8 : 2);
1368 /* Implement `TARGET_MEMORY_MOVE_COST'. */
1370 /* Return the cost of moving data of mode MODE between a register of class
1371 CLASS and memory; IN is zero if the value is to be written to memory,
1372 nonzero if it is to be read in. This cost is relative to those in
1373 REGISTER_MOVE_COST. */
1374 static int
1375 cr16_memory_move_cost (machine_mode mode,
1376 reg_class_t rclass ATTRIBUTE_UNUSED,
1377 bool in ATTRIBUTE_UNUSED)
1379 /* One LD or ST takes twice the time of a simple reg-reg move. */
1380 if (reg_classes_intersect_p (rclass, GENERAL_REGS))
1381 return (4 * HARD_REGNO_NREGS (0, mode));
1382 else
1383 return (100);
1386 /* Instruction output. */
1388 /* Check if a const_double is ok for cr16 store-immediate instructions. */
1390 cr16_const_double_ok (rtx op)
1392 if (GET_MODE (op) == SFmode)
1394 REAL_VALUE_TYPE r;
1395 long l;
1396 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1397 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1398 return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
1401 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
1402 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
1405 /* Returns bit position of first 0 or 1 bit.
1406 It is safe to assume val as 16-bit wide. */
1408 cr16_operand_bit_pos (int val, int bitval)
1410 int i;
1411 if (bitval == 0)
1412 val = ~val;
1414 for (i = 0; i < 16; i++)
1415 if (val & (1 << i))
1416 break;
1417 return i;
1420 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
1421 static void
1422 cr16_print_operand (FILE * file, rtx x, int code)
1424 int ptr_dereference = 0;
1426 switch (code)
1428 case 'd':
1430 const char *cr16_cmp_str;
1431 switch (GET_CODE (x))
1433 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
1434 -> swap all non symmetric ops. */
1435 case EQ:
1436 cr16_cmp_str = "eq";
1437 break;
1438 case NE:
1439 cr16_cmp_str = "ne";
1440 break;
1441 case GT:
1442 cr16_cmp_str = "lt";
1443 break;
1444 case GTU:
1445 cr16_cmp_str = "lo";
1446 break;
1447 case LT:
1448 cr16_cmp_str = "gt";
1449 break;
1450 case LTU:
1451 cr16_cmp_str = "hi";
1452 break;
1453 case GE:
1454 cr16_cmp_str = "le";
1455 break;
1456 case GEU:
1457 cr16_cmp_str = "ls";
1458 break;
1459 case LE:
1460 cr16_cmp_str = "ge";
1461 break;
1462 case LEU:
1463 cr16_cmp_str = "hs";
1464 break;
1465 default:
1466 gcc_unreachable ();
1468 fprintf (file, "%s", cr16_cmp_str);
1469 return;
1471 case '$':
1472 putc ('$', file);
1473 return;
1475 case 'p':
1476 if (GET_CODE (x) == REG)
1478 /* For Push instructions, we should not print register pairs. */
1479 fprintf (file, "%s", reg_names[REGNO (x)]);
1480 return;
1482 break;
1484 case 'b':
1485 /* Print the immediate address for bal
1486 'b' is used instead of 'a' to avoid compiler calling
1487 the GO_IF_LEGITIMATE_ADDRESS which cannot
1488 perform checks on const_int code addresses as it
1489 assumes all const_int are data addresses. */
1490 fprintf (file, "0x%lx", INTVAL (x));
1491 return;
1493 case 'r':
1494 /* Print bit position of first 0. */
1495 fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
1496 return;
1498 case 's':
1499 /* Print bit position of first 1. */
1500 fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
1501 return;
1502 case 'g':
1503 /* 'g' is used for implicit mem: dereference. */
1504 ptr_dereference = 1;
1505 case 'f':
1506 case 0:
1507 /* default. */
1508 switch (GET_CODE (x))
1510 case REG:
1511 if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
1513 if (LONG_REG_P (REGNO (x)))
1514 fprintf (file, "(%s)", reg_names[REGNO (x)]);
1515 else
1516 fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
1517 reg_names[REGNO (x)]);
1519 else
1520 fprintf (file, "%s", reg_names[REGNO (x)]);
1521 return;
1523 case MEM:
1524 output_address (XEXP (x, 0));
1525 return;
1527 case CONST_DOUBLE:
1529 REAL_VALUE_TYPE r;
1530 long l;
1532 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1533 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1535 fprintf (file, "$0x%lx", l);
1536 return;
1538 case CONST_INT:
1540 fprintf (file, "$%ld", INTVAL (x));
1541 return;
1543 case UNSPEC:
1544 switch (XINT (x, 1))
1546 default:
1547 gcc_unreachable ();
1549 break;
1551 default:
1552 if (!ptr_dereference)
1554 putc ('$', file);
1556 cr16_print_operand_address (file, x);
1557 return;
1559 default:
1560 output_operand_lossage ("invalid %%xn code");
1563 gcc_unreachable ();
1566 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
1568 static void
1569 cr16_print_operand_address (FILE * file, rtx addr)
1571 enum cr16_addrtype addrtype;
1572 struct cr16_address address;
1574 /* Decompose the address. Also ask it to treat address as constant. */
1575 addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
1577 if (address.disp && GET_CODE (address.disp) == UNSPEC)
1579 debug_rtx (addr);
1582 switch (addrtype)
1584 case CR16_REG_REL:
1585 if (address.disp)
1587 if (GET_CODE (address.disp) == UNSPEC)
1588 cr16_print_operand (file, address.disp, 0);
1589 else
1590 output_addr_const (file, address.disp);
1592 else
1593 fprintf (file, "0");
1594 fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
1595 break;
1597 case CR16_ABSOLUTE:
1598 if (address.disp)
1599 output_addr_const (file, address.disp);
1600 else
1601 fprintf (file, "0");
1602 break;
1604 case CR16_INDEX_REGP_REL:
1605 fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
1606 /* Fall through. */
1607 case CR16_REGP_REL:
1608 if (address.disp)
1610 if (GET_CODE (address.disp) == UNSPEC)
1611 cr16_print_operand (file, address.disp, 0);
1612 else
1613 output_addr_const (file, address.disp);
1615 else
1616 fprintf (file, "0");
1617 fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
1618 reg_names[REGNO (address.base)]);
1619 break;
1620 default:
1621 debug_rtx (addr);
1622 gcc_unreachable ();
1624 /* Add qualifiers to the address expression that was just printed. */
1625 if (flag_pic < NEAR_PIC && address.code == 0)
1627 if (address.data == DM_FAR)
1628 /* Addr contains SYMBOL_REF & far data ptr. */
1629 fprintf (file, "@l");
1630 else if (address.data == DM_DEFAULT)
1631 /* Addr contains SYMBOL_REF & medium data ptr. */
1632 fprintf (file, "@m");
1633 /* Addr contains SYMBOL_REF & medium data ptr. */
1634 else if (address.data == DM_NEAR)
1635 /* Addr contains SYMBOL_REF & near data ptr. */
1636 fprintf (file, "@s");
1638 else if (flag_pic == NEAR_PIC
1639 && (address.code == 0) && (address.data == DM_FAR
1640 || address.data == DM_DEFAULT
1641 || address.data == DM_NEAR))
1643 fprintf (file, "@l");
1645 else if (flag_pic == NEAR_PIC && address.code == 2)
1647 fprintf (file, "pic");
1649 else if (flag_pic == NEAR_PIC && address.code == 1)
1651 fprintf (file, "@cpic");
1654 else if (flag_pic == FAR_PIC && address.code == 2)
1656 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
1657 address ! GOTc tells assembler this symbol is a text-address
1658 This needs to be fixed in such a way that this offset is done
1659 only in the case where an address is being used for indirect jump
1660 or call. Determining the potential usage of loadd is of course not
1661 possible always. Eventually, this has to be fixed in the
1662 processor. */
1663 fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
1665 else if (flag_pic == FAR_PIC && address.code == 1)
1667 fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
1670 else if (flag_pic == FAR_PIC &&
1671 (address.data == DM_FAR || address.data == DM_DEFAULT
1672 || address.data == DM_NEAR))
1674 fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
1678 /* Machine description helper functions. */
1680 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
1681 When push_or_pop is zero -> string for push instructions of prologue.
1682 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1683 Relies on the assumptions:
1684 1. RA is the last register to be saved.
1685 2. The maximal value of the counter is MAX_COUNT. */
1686 char *
1687 cr16_prepare_push_pop_string (int push_or_pop)
1689 /* j is the number of registers being saved, takes care that there won't be
1690 more than 8 in one push/pop instruction. */
1692 /* For the register mask string. */
1693 static char one_inst_str[50];
1695 /* i is the index of current_frame_info.save_regs[], going from 0 until
1696 current_frame_info.last_reg_to_save. */
1697 int i, start_reg;
1698 int word_cnt;
1699 int print_ra;
1700 char *return_str;
1702 /* For reversing on the push instructions if there are more than one. */
1703 char *temp_str;
1705 return_str = (char *) xmalloc (160);
1706 temp_str = (char *) xmalloc (160);
1708 /* Initialize. */
1709 memset (return_str, 0, 3);
1711 i = 0;
1712 while (i <= current_frame_info.last_reg_to_save)
1714 /* Prepare mask for one instruction. */
1715 one_inst_str[0] = 0;
1717 /* To count number of words in one instruction. */
1718 word_cnt = 0;
1719 start_reg = i;
1720 print_ra = 0;
1721 while ((word_cnt < MAX_COUNT)
1722 && (i <= current_frame_info.last_reg_to_save))
1724 /* For each non consecutive save register,
1725 a new instruction shall be generated. */
1726 if (!current_frame_info.save_regs[i])
1728 /* Move to next reg and break. */
1729 ++i;
1730 break;
1733 if (i == RETURN_ADDRESS_REGNUM)
1734 print_ra = 1;
1735 else
1737 /* Check especially if adding 2 does not cross the MAX_COUNT. */
1738 if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
1739 >= MAX_COUNT)
1740 break;
1741 /* Increase word count by 2 for long registers except RA. */
1742 word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
1744 ++i;
1747 /* No need to generate any instruction as
1748 no register or RA needs to be saved. */
1749 if ((word_cnt == 0) && (print_ra == 0))
1750 continue;
1752 /* Now prepare the instruction operands. */
1753 if (word_cnt > 0)
1755 sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
1756 if (print_ra)
1757 strcat (one_inst_str, ", ra");
1759 else
1760 strcat (one_inst_str, "ra");
1762 if (push_or_pop == 1)
1764 /* Pop instruction. */
1765 if (print_ra && !cr16_interrupt_function_p ()
1766 && !crtl->calls_eh_return)
1767 /* Print popret if RA is saved and its not a interrupt
1768 function. */
1769 strcpy (temp_str, "\n\tpopret\t");
1770 else
1771 strcpy (temp_str, "\n\tpop\t");
1773 strcat (temp_str, one_inst_str);
1775 /* Add the pop instruction list. */
1776 strcat (return_str, temp_str);
1778 else
1780 /* Push instruction. */
1781 strcpy (temp_str, "\n\tpush\t");
1782 strcat (temp_str, one_inst_str);
1784 /* We need to reverse the order of the instructions if there
1785 are more than one. (since the pop will not be reversed in
1786 the epilogue. */
1787 strcat (temp_str, return_str);
1788 strcpy (return_str, temp_str);
1792 if (push_or_pop == 1)
1794 /* POP. */
1795 if (cr16_interrupt_function_p ())
1796 strcat (return_str, "\n\tretx\n");
1797 else if (crtl->calls_eh_return)
1799 /* Add stack adjustment before returning to exception handler
1800 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
1801 strcat (return_str, "\n\taddd\t (r5, r4), (sp)\t\n");
1802 strcat (return_str, "\n\tjump\t (ra)\n");
1804 /* But before anything else, undo the adjustment addition done in
1805 cr16_expand_epilogue (). */
1806 strcpy (temp_str, "\n\tsubd\t (r5, r4), (sp)\t\n");
1807 strcat (temp_str, return_str);
1808 strcpy (return_str, temp_str);
1810 else if (!FUNC_IS_NORETURN_P (current_function_decl)
1811 && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]))
1812 strcat (return_str, "\n\tjump\t (ra)\n");
1815 /* Skip the newline and the tab in the start of return_str. */
1816 return_str += 2;
1817 return return_str;
1821 /* Generate DWARF2 annotation for multi-push instruction. */
1822 static void
1823 cr16_create_dwarf_for_multi_push (rtx insn)
1825 rtx dwarf, reg, tmp;
1826 int i, j, from, to, word_cnt, dwarf_par_index, inc;
1827 machine_mode mode;
1828 int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
1830 for (i = 0; i <= current_frame_info.last_reg_to_save; ++i)
1832 if (current_frame_info.save_regs[i])
1834 ++num_regs;
1835 if (i < CR16_FIRST_DWORD_REGISTER)
1836 total_push_bytes += 2;
1837 else
1838 total_push_bytes += 4;
1842 if (!num_regs)
1843 return;
1845 dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
1846 dwarf_par_index = num_regs;
1848 from = current_frame_info.last_reg_to_save + 1;
1849 to = current_frame_info.last_reg_to_save;
1850 word_cnt = 0;
1852 for (i = current_frame_info.last_reg_to_save; i >= 0;)
1854 if (!current_frame_info.save_regs[i] || 0 == i || split_here)
1856 /* This block of regs is pushed in one instruction. */
1857 if (0 == i && current_frame_info.save_regs[i])
1858 from = 0;
1860 for (j = to; j >= from; --j)
1862 if (j < CR16_FIRST_DWORD_REGISTER)
1864 mode = HImode;
1865 inc = 1;
1867 else
1869 mode = SImode;
1870 inc = 2;
1872 reg = gen_rtx_REG (mode, j);
1873 offset += 2 * inc;
1874 tmp = gen_rtx_SET (gen_frame_mem (mode,
1875 plus_constant
1876 (Pmode, stack_pointer_rtx,
1877 total_push_bytes - offset)),
1878 reg);
1879 RTX_FRAME_RELATED_P (tmp) = 1;
1880 XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
1882 from = i;
1883 to = --i;
1884 split_here = 0;
1885 word_cnt = 0;
1886 continue;
1889 if (i != RETURN_ADDRESS_REGNUM)
1891 inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
1892 if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
1894 split_here = 1;
1895 from = i;
1896 continue;
1898 word_cnt += inc;
1901 from = i--;
1904 tmp = gen_rtx_SET (stack_pointer_rtx,
1905 gen_rtx_PLUS (SImode, stack_pointer_rtx,
1906 GEN_INT (-offset)));
1907 RTX_FRAME_RELATED_P (tmp) = 1;
1908 XVECEXP (dwarf, 0, 0) = tmp;
1910 add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
1914 CompactRISC CR16 Architecture stack layout:
1916 0 +---------------------
1921 +==================== Sp (x) = Ap (x+1)
1922 A | Args for functions
1923 | | called by X and Dynamically
1924 | | Dynamic allocations allocated and
1925 | | (alloca, variable deallocated
1926 Stack | length arrays).
1927 grows +-------------------- Fp (x)
1928 down| | Local variables of X
1929 ward| +--------------------
1930 | | Regs saved for X-1
1931 | +==================== Sp (x-1) = Ap (x)
1932 | Args for func X
1933 | pushed by X-1
1934 +-------------------- Fp (x-1)
1939 void
1940 cr16_expand_prologue (void)
1942 rtx insn;
1944 cr16_compute_frame ();
1945 cr16_compute_save_regs ();
1947 /* If there is no need in push and adjustment to sp, return. */
1948 if ((current_frame_info.total_size + current_frame_info.reg_size) == 0)
1949 return;
1951 if (current_frame_info.last_reg_to_save != -1)
1953 /* If there are registers to push. */
1954 insn = emit_insn (gen_push_for_prologue
1955 (GEN_INT (current_frame_info.reg_size)));
1956 cr16_create_dwarf_for_multi_push (insn);
1957 RTX_FRAME_RELATED_P (insn) = 1;
1961 if (current_frame_info.total_size > 0)
1963 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1964 GEN_INT (-current_frame_info.total_size)));
1965 RTX_FRAME_RELATED_P (insn) = 1;
1968 if (frame_pointer_needed)
1970 /* Initialize the frame pointer with the value of the stack pointer
1971 pointing now to the locals. */
1972 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1976 /* Generate insn that updates the stack for local variables and padding
1977 for registers we save. - Generate the appropriate return insn. */
1978 void
1979 cr16_expand_epilogue (void)
1981 rtx insn;
1983 /* Nonzero if we need to return and pop only RA. This will generate a
1984 different insn. This differentiate is for the peepholes for call as
1985 last statement in function. */
1986 int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]
1987 && (current_frame_info.reg_size
1988 == CR16_UNITS_PER_DWORD));
1990 if (frame_pointer_needed)
1992 /* Restore the stack pointer with the frame pointers value. */
1993 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
1996 if (current_frame_info.total_size > 0)
1998 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1999 GEN_INT (current_frame_info.total_size)));
2000 RTX_FRAME_RELATED_P (insn) = 1;
2003 if (crtl->calls_eh_return)
2005 /* Add this here so that (r5, r4) is actually loaded with the adjustment
2006 value; otherwise, the load might be optimized away...
2007 NOTE: remember to subtract the adjustment before popping the regs
2008 and add it back before returning. */
2009 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2010 EH_RETURN_STACKADJ_RTX));
2013 if (cr16_interrupt_function_p ())
2015 insn = emit_jump_insn (gen_interrupt_return ());
2016 RTX_FRAME_RELATED_P (insn) = 1;
2018 else if (crtl->calls_eh_return)
2020 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
2021 insn = emit_jump_insn (gen_pop_and_popret_return
2022 (GEN_INT (current_frame_info.reg_size)));
2023 RTX_FRAME_RELATED_P (insn) = 1;
2025 else if (current_frame_info.last_reg_to_save == -1)
2026 /* Nothing to pop. */
2027 /* Don't output jump for interrupt routine, only retx. */
2028 emit_jump_insn (gen_jump_return ());
2029 else if (only_popret_RA)
2031 insn = emit_jump_insn (gen_popret_RA_return ());
2032 RTX_FRAME_RELATED_P (insn) = 1;
2034 else
2036 insn = emit_jump_insn (gen_pop_and_popret_return
2037 (GEN_INT (current_frame_info.reg_size)));
2038 RTX_FRAME_RELATED_P (insn) = 1;
2042 /* Implements FRAME_POINTER_REQUIRED. */
2043 static bool
2044 cr16_frame_pointer_required (void)
2046 return (cfun->calls_alloca || crtl->calls_eh_return
2047 || cfun->has_nonlocal_label || crtl->calls_eh_return);
2050 static bool
2051 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
2053 return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
2057 /* A C compound statement that attempts to replace X with
2058 a valid memory address for an operand of mode MODE. WIN
2059 will be a C statement label elsewhere in the code.
2060 X will always be the result of a call to break_out_memory_refs (),
2061 and OLDX will be the operand that was given to that function to
2062 produce X.
2063 The code generated by this macro should not alter the
2064 substructure of X. If it transforms X into a more legitimate form,
2065 it should assign X (which will always be a C variable) a new value. */
2066 static rtx
2067 cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
2068 machine_mode mode ATTRIBUTE_UNUSED)
2070 if (flag_pic)
2071 return legitimize_pic_address (orig_x, mode, NULL_RTX);
2072 else
2073 return x;
2076 /* Implement TARGET_LEGITIMATE_CONSTANT_P
2077 Nonzero if X is a legitimate constant for an immediate
2078 operand on the target machine. You can assume that X
2079 satisfies CONSTANT_P. In cr16c treat legitimize float
2080 constant as an immediate operand. */
2081 static bool
2082 cr16_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED,
2083 rtx x ATTRIBUTE_UNUSED)
2085 return 1;
2088 void
2089 notice_update_cc (rtx exp)
2091 if (GET_CODE (exp) == SET)
2093 /* Jumps do not alter the cc's. */
2094 if (SET_DEST (exp) == pc_rtx)
2095 return;
2097 /* Moving register or memory into a register:
2098 it doesn't alter the cc's, but it might invalidate
2099 the RTX's which we remember the cc's came from.
2100 (Note that moving a constant 0 or 1 MAY set the cc's). */
2101 if (REG_P (SET_DEST (exp))
2102 && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
2104 return;
2107 /* Moving register into memory doesn't alter the cc's.
2108 It may invalidate the RTX's which we remember the cc's came from. */
2109 if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
2111 return;
2115 CC_STATUS_INIT;
2116 return;
2119 static machine_mode
2120 cr16_unwind_word_mode (void)
2122 return SImode;
2125 /* Helper function for md file. This function is used to emit arithmetic
2126 DI instructions. The argument "num" decides which instruction to be
2127 printed. */
2128 const char *
2129 cr16_emit_add_sub_di (rtx *operands, enum rtx_code code)
2131 rtx lo_op[2] ;
2132 rtx hi0_op[2] ;
2133 rtx hi1_op[2] ;
2135 lo_op[0] = gen_lowpart (SImode, operands[0]);
2136 hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4);
2137 hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6);
2139 lo_op[1] = gen_lowpart (SImode, operands[2]);
2140 hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4);
2141 hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6);
2143 switch (code)
2145 case PLUS:
2147 output_asm_insn ("addd\t%1, %0", lo_op) ;
2148 output_asm_insn ("addcw\t%1, %0", hi0_op) ;
2149 output_asm_insn ("addcw\t%1, %0", hi1_op) ;
2150 break;
2152 case MINUS:
2154 output_asm_insn ("subd\t%1, %0", lo_op) ;
2155 output_asm_insn ("subcw\t%1, %0", hi0_op) ;
2156 output_asm_insn ("subcw\t%1, %0", hi1_op) ;
2157 break;
2159 default:
2160 break;
2163 return "";
2167 /* Helper function for md file. This function is used to emit logical
2168 DI instructions. The argument "num" decides which instruction to be
2169 printed. */
2170 const char *
2171 cr16_emit_logical_di (rtx *operands, enum rtx_code code)
2173 rtx lo_op[2] ;
2174 rtx hi_op[2] ;
2176 lo_op[0] = gen_lowpart (SImode, operands[0]);
2177 hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4);
2179 lo_op[1] = gen_lowpart (SImode, operands[2]);
2180 hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4);
2182 switch (code)
2184 case AND:
2186 output_asm_insn ("andd\t%1, %0", lo_op) ;
2187 output_asm_insn ("andd\t%1, %0", hi_op) ;
2188 return "";
2190 case IOR:
2192 output_asm_insn ("ord\t%1, %0", lo_op) ;
2193 output_asm_insn ("ord\t%1, %0", hi_op) ;
2194 return "";
2196 case XOR:
2198 output_asm_insn ("xord\t%1, %0", lo_op) ;
2199 output_asm_insn ("xord\t%1, %0", hi_op) ;
2200 return "";
2202 default:
2203 break;
2206 return "";
2209 /* Initialize 'targetm' variable which contains pointers to functions
2210 and data relating to the target machine. */
2212 struct gcc_target targetm = TARGET_INITIALIZER;