2014-10-27 Andrew MacLeod <amacleod@redhat.com>
[official-gcc.git] / gcc / config / cr16 / cr16.c
blob29284106ab842d645e26a425c9f72f71b361d208
1 /* Output routines for CR16 processor.
2 Copyright (C) 2012-2014 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 "tree.h"
27 #include "stor-layout.h"
28 #include "calls.h"
29 #include "tm_p.h"
30 #include "regs.h"
31 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "output.h"
35 #include "insn-codes.h"
36 #include "insn-attr.h"
37 #include "flags.h"
38 #include "except.h"
39 #include "hashtab.h"
40 #include "hash-set.h"
41 #include "vec.h"
42 #include "machmode.h"
43 #include "input.h"
44 #include "function.h"
45 #include "recog.h"
46 #include "expr.h"
47 #include "optabs.h"
48 #include "diagnostic-core.h"
49 #include "predict.h"
50 #include "dominance.h"
51 #include "cfg.h"
52 #include "cfgrtl.h"
53 #include "cfganal.h"
54 #include "lcm.h"
55 #include "cfgbuild.h"
56 #include "cfgcleanup.h"
57 #include "basic-block.h"
58 #include "target.h"
59 #include "target-def.h"
60 #include "df.h"
61 #include "builtins.h"
63 /* Definitions. */
65 /* Maximum number of register used for passing parameters. */
66 #define MAX_REG_FOR_PASSING_ARGS 6
68 /* Minimum number register used for passing parameters. */
69 #define MIN_REG_FOR_PASSING_ARGS 2
71 /* The maximum count of words supported in the assembly of the architecture in
72 a push/pop instruction. */
73 #define MAX_COUNT 8
75 /* Predicate is true if the current function is a 'noreturn' function,
76 i.e. it is qualified as volatile. */
77 #define FUNC_IS_NORETURN_P(decl) (TREE_THIS_VOLATILE (decl))
79 /* Predicate that holds when we need to save registers even for 'noreturn'
80 functions, to accommodate for unwinding. */
81 #define MUST_SAVE_REGS_P() \
82 (flag_unwind_tables || (flag_exceptions && !UI_SJLJ))
84 /* Nonzero if the rtx X is a signed const int of n bits. */
85 #define RTX_SIGNED_INT_FITS_N_BITS(X, n) \
86 ((GET_CODE (X) == CONST_INT \
87 && SIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
89 /* Nonzero if the rtx X is an unsigned const int of n bits. */
90 #define RTX_UNSIGNED_INT_FITS_N_BITS(X, n) \
91 ((GET_CODE (X) == CONST_INT \
92 && UNSIGNED_INT_FITS_N_BITS (INTVAL (X), n)) ? 1 : 0)
94 /* Structure for stack computations. */
96 /* variable definitions in the struture
97 args_size Number of bytes saved on the stack for local
98 variables
100 reg_size Number of bytes saved on the stack for
101 non-scratch registers
103 total_size The sum of 2 sizes: locals vars and padding byte
104 for saving the registers. Used in expand_prologue()
105 and expand_epilogue()
107 last_reg_to_save Will hold the number of the last register the
108 prologue saves, -1 if no register is saved
110 save_regs[16] Each object in the array is a register number.
111 Mark 1 for registers that need to be saved
113 num_regs Number of registers saved
115 initialized Non-zero if frame size already calculated, not
116 used yet
118 function_makes_calls Does the function make calls ? not used yet. */
120 struct cr16_frame_info
122 unsigned long var_size;
123 unsigned long args_size;
124 unsigned int reg_size;
125 unsigned long total_size;
126 long last_reg_to_save;
127 long save_regs[FIRST_PSEUDO_REGISTER];
128 int num_regs;
129 int initialized;
130 int function_makes_calls;
133 /* Current frame information calculated by cr16_compute_frame_size. */
134 static struct cr16_frame_info current_frame_info;
136 /* Static Variables. */
138 /* Data model that was supplied by user via command line option
139 This will be overridden in case of invalid combination
140 of core and data model options are supplied. */
141 static enum data_model_type data_model = DM_DEFAULT;
143 /* TARGETM Function Prototypes and forward declarations */
144 static void cr16_print_operand (FILE *, rtx, int);
145 static void cr16_print_operand_address (FILE *, rtx);
147 /* Stack layout and calling conventions. */
148 #undef TARGET_STRUCT_VALUE_RTX
149 #define TARGET_STRUCT_VALUE_RTX cr16_struct_value_rtx
150 #undef TARGET_RETURN_IN_MEMORY
151 #define TARGET_RETURN_IN_MEMORY cr16_return_in_memory
153 /* Target-specific uses of '__attribute__'. */
154 #undef TARGET_ATTRIBUTE_TABLE
155 #define TARGET_ATTRIBUTE_TABLE cr16_attribute_table
156 #undef TARGET_NARROW_VOLATILE_BITFIELD
157 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
159 /* EH related. */
160 #undef TARGET_UNWIND_WORD_MODE
161 #define TARGET_UNWIND_WORD_MODE cr16_unwind_word_mode
163 /* Override Options. */
164 #undef TARGET_OPTION_OVERRIDE
165 #define TARGET_OPTION_OVERRIDE cr16_override_options
167 /* Conditional register usuage. */
168 #undef TARGET_CONDITIONAL_REGISTER_USAGE
169 #define TARGET_CONDITIONAL_REGISTER_USAGE cr16_conditional_register_usage
171 /* Controlling register spills. */
172 #undef TARGET_CLASS_LIKELY_SPILLED_P
173 #define TARGET_CLASS_LIKELY_SPILLED_P cr16_class_likely_spilled_p
175 /* Passing function arguments. */
176 #undef TARGET_FUNCTION_ARG
177 #define TARGET_FUNCTION_ARG cr16_function_arg
178 #undef TARGET_FUNCTION_ARG_ADVANCE
179 #define TARGET_FUNCTION_ARG_ADVANCE cr16_function_arg_advance
180 #undef TARGET_RETURN_POPS_ARGS
181 #define TARGET_RETURN_POPS_ARGS cr16_return_pops_args
183 /* Initialize the GCC target structure. */
184 #undef TARGET_FRAME_POINTER_REQUIRED
185 #define TARGET_FRAME_POINTER_REQUIRED cr16_frame_pointer_required
186 #undef TARGET_CAN_ELIMINATE
187 #define TARGET_CAN_ELIMINATE cr16_can_eliminate
188 #undef TARGET_LEGITIMIZE_ADDRESS
189 #define TARGET_LEGITIMIZE_ADDRESS cr16_legitimize_address
190 #undef TARGET_LEGITIMATE_CONSTANT_P
191 #define TARGET_LEGITIMATE_CONSTANT_P cr16_legitimate_constant_p
192 #undef TARGET_LEGITIMATE_ADDRESS_P
193 #define TARGET_LEGITIMATE_ADDRESS_P cr16_legitimate_address_p
195 /* Returning function value. */
196 #undef TARGET_FUNCTION_VALUE
197 #define TARGET_FUNCTION_VALUE cr16_function_value
198 #undef TARGET_LIBCALL_VALUE
199 #define TARGET_LIBCALL_VALUE cr16_libcall_value
200 #undef TARGET_FUNCTION_VALUE_REGNO_P
201 #define TARGET_FUNCTION_VALUE_REGNO_P cr16_function_value_regno_p
203 /* printing the values. */
204 #undef TARGET_PRINT_OPERAND
205 #define TARGET_PRINT_OPERAND cr16_print_operand
206 #undef TARGET_PRINT_OPERAND_ADDRESS
207 #define TARGET_PRINT_OPERAND_ADDRESS cr16_print_operand_address
209 /* Relative costs of operations. */
210 #undef TARGET_ADDRESS_COST
211 #define TARGET_ADDRESS_COST cr16_address_cost
212 #undef TARGET_REGISTER_MOVE_COST
213 #define TARGET_REGISTER_MOVE_COST cr16_register_move_cost
214 #undef TARGET_MEMORY_MOVE_COST
215 #define TARGET_MEMORY_MOVE_COST cr16_memory_move_cost
217 /* Table of machine attributes. */
218 static const struct attribute_spec cr16_attribute_table[] = {
219 /* ISRs have special prologue and epilogue requirements. */
220 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
221 affects_type_identity }. */
222 {"interrupt", 0, 0, false, true, true, NULL, false},
223 {NULL, 0, 0, false, false, false, NULL, false}
226 /* TARGET_ASM_UNALIGNED_xx_OP generates .?byte directive
227 .?byte directive along with @c is not understood by assembler.
228 Therefore, make all TARGET_ASM_UNALIGNED_xx_OP same
229 as TARGET_ASM_ALIGNED_xx_OP. */
230 #undef TARGET_ASM_UNALIGNED_HI_OP
231 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
232 #undef TARGET_ASM_UNALIGNED_SI_OP
233 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
234 #undef TARGET_ASM_UNALIGNED_DI_OP
235 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
237 /* Target hook implementations. */
239 /* Implements hook TARGET_RETURN_IN_MEMORY. */
240 static bool
241 cr16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
243 const HOST_WIDE_INT size = int_size_in_bytes (type);
244 return ((size == -1) || (size > 8));
247 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
248 static bool
249 cr16_class_likely_spilled_p (reg_class_t rclass)
251 if ((rclass) == SHORT_REGS || (rclass) == DOUBLE_BASE_REGS
252 || (rclass) == LONG_REGS || (rclass) == GENERAL_REGS)
253 return true;
255 return false;
258 static int
259 cr16_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
260 tree funtype ATTRIBUTE_UNUSED,
261 int size ATTRIBUTE_UNUSED)
263 return 0;
266 /* Returns true if data model selected via command line option
267 is same as function argument. */
268 bool
269 cr16_is_data_model (enum data_model_type model)
271 return (model == data_model);
274 /* Parse relevant options and override. */
275 static void
276 cr16_override_options (void)
278 /* Disable -fdelete-null-pointer-checks option for CR16 target.
279 Programs which rely on NULL pointer dereferences _not_ halting the
280 program may not work properly with this option. So disable this
281 option. */
282 flag_delete_null_pointer_checks = 0;
284 /* FIXME: To avoid spill_failure ICE during exception handling,
285 * disable cse_fllow_jumps. The spill error occurs when compiler
286 * can't find a suitable candidate in GENERAL_REGS class to reload
287 * a 32bit register.
288 * Need to find a better way of avoiding this situation. */
289 if (flag_exceptions)
290 flag_cse_follow_jumps = 0;
292 /* If -fpic option, data_model == DM_FAR. */
293 if (flag_pic == NEAR_PIC)
295 data_model = DM_FAR;
298 /* The only option we want to examine is data model option. */
299 if (cr16_data_model)
301 if (strcmp (cr16_data_model, "medium") == 0)
302 data_model = DM_DEFAULT;
303 else if (strcmp (cr16_data_model, "near") == 0)
304 data_model = DM_NEAR;
305 else if (strcmp (cr16_data_model, "far") == 0)
307 if (TARGET_CR16CP)
308 data_model = DM_FAR;
309 else
310 error ("data-model=far not valid for cr16c architecture");
312 else
313 error ("invalid data model option -mdata-model=%s", cr16_data_model);
315 else
316 data_model = DM_DEFAULT;
319 /* Implements the macro TARGET_CONDITIONAL_REGISTER_USAGE. */
320 static void
321 cr16_conditional_register_usage (void)
323 if (flag_pic)
325 fixed_regs[12] = call_used_regs[12] = 1;
329 /* Stack layout and calling conventions routines. */
331 /* Return nonzero if the current function being compiled is an interrupt
332 function as specified by the "interrupt" attribute. */
334 cr16_interrupt_function_p (void)
336 tree attributes;
338 attributes = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
339 return (lookup_attribute ("interrupt", attributes) != NULL_TREE);
342 /* Compute values for the array current_frame_info.save_regs and the variable
343 current_frame_info.reg_size. The index of current_frame_info.save_regs
344 is numbers of register, each will get 1 if we need to save it in the
345 current function, 0 if not. current_frame_info.reg_size is the total sum
346 of the registers being saved. */
347 static void
348 cr16_compute_save_regs (void)
350 unsigned int regno;
352 /* Initialize here so in case the function is no-return it will be -1. */
353 current_frame_info.last_reg_to_save = -1;
355 /* Initialize the number of bytes to be saved. */
356 current_frame_info.reg_size = 0;
358 /* No need to save any registers if the function never returns. */
359 if (FUNC_IS_NORETURN_P (current_function_decl) && !MUST_SAVE_REGS_P ())
360 return;
362 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
364 if (fixed_regs[regno])
366 current_frame_info.save_regs[regno] = 0;
367 continue;
370 /* If this reg is used and not call-used (except RA), save it. */
371 if (cr16_interrupt_function_p ())
373 if (!crtl->is_leaf && call_used_regs[regno])
374 /* This is a volatile reg in a non-leaf interrupt routine - save
375 it for the sake of its sons. */
376 current_frame_info.save_regs[regno] = 1;
377 else if (df_regs_ever_live_p (regno))
378 /* This reg is used - save it. */
379 current_frame_info.save_regs[regno] = 1;
380 else
381 /* This reg is not used, and is not a volatile - don't save. */
382 current_frame_info.save_regs[regno] = 0;
384 else
386 /* If this reg is used and not call-used (except RA), save it. */
387 if (df_regs_ever_live_p (regno)
388 && (!call_used_regs[regno] || regno == RETURN_ADDRESS_REGNUM))
389 current_frame_info.save_regs[regno] = 1;
390 else
391 current_frame_info.save_regs[regno] = 0;
395 /* Save registers so the exception handler can modify them. */
396 if (crtl->calls_eh_return)
398 unsigned int i;
400 for (i = 0;; ++i)
402 regno = EH_RETURN_DATA_REGNO (i);
403 if (INVALID_REGNUM == regno)
404 break;
405 current_frame_info.save_regs[regno] = 1;
409 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
410 if (current_frame_info.save_regs[regno] == 1)
412 current_frame_info.last_reg_to_save = regno;
413 if (regno >= CR16_FIRST_DWORD_REGISTER)
414 current_frame_info.reg_size += CR16_UNITS_PER_DWORD;
415 else
416 current_frame_info.reg_size += UNITS_PER_WORD;
420 /* Compute the size of the local area and the size to be adjusted by the
421 prologue and epilogue. */
422 static void
423 cr16_compute_frame (void)
425 /* For aligning the local variables. */
426 int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
427 int padding_locals;
429 /* Padding needed for each element of the frame. */
430 current_frame_info.var_size = get_frame_size ();
432 /* Align to the stack alignment. */
433 padding_locals = current_frame_info.var_size % stack_alignment;
434 if (padding_locals)
435 padding_locals = stack_alignment - padding_locals;
437 current_frame_info.var_size += padding_locals;
438 current_frame_info.total_size = current_frame_info.var_size
439 + (ACCUMULATE_OUTGOING_ARGS
440 ? crtl->outgoing_args_size : 0);
443 /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */
445 cr16_initial_elimination_offset (int from, int to)
447 /* Compute this since we need to use current_frame_info.reg_size. */
448 cr16_compute_save_regs ();
450 /* Compute this since we need to use current_frame_info.var_size. */
451 cr16_compute_frame ();
453 if (((from) == FRAME_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
454 return (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0);
455 else if (((from) == ARG_POINTER_REGNUM) && ((to) == FRAME_POINTER_REGNUM))
456 return (current_frame_info.reg_size + current_frame_info.var_size);
457 else if (((from) == ARG_POINTER_REGNUM) && ((to) == STACK_POINTER_REGNUM))
458 return (current_frame_info.reg_size + current_frame_info.var_size
459 + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0));
460 else
461 gcc_unreachable ();
464 /* Register Usage. */
466 /* Return the class number of the smallest class containing reg number REGNO.
467 This could be a conditional expression or could index an array. */
468 enum reg_class
469 cr16_regno_reg_class (int regno)
471 if ((regno >= 0) && (regno < CR16_FIRST_DWORD_REGISTER))
472 return SHORT_REGS;
474 if ((regno >= CR16_FIRST_DWORD_REGISTER) && (regno < FIRST_PSEUDO_REGISTER))
475 return LONG_REGS;
477 return NO_REGS;
480 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
482 cr16_hard_regno_mode_ok (int regno, enum machine_mode mode)
484 if ((GET_MODE_SIZE (mode) >= 4) && (regno == 11))
485 return 0;
487 if (mode == DImode || mode == DFmode)
489 if ((regno > 8) || (regno & 1))
490 return 0;
491 return 1;
494 if ((TARGET_INT32)
495 && ((regno >= 12) && (GET_MODE_SIZE (mode) < 4 )))
496 return 0;
498 /* CC can only hold CCmode values. */
499 if (GET_MODE_CLASS (mode) == MODE_CC)
500 return 0;
501 return 1;
504 /* Returns register number for function return value.*/
505 static inline unsigned int
506 cr16_ret_register (void)
508 return 0;
511 /* Implements hook TARGET_STRUCT_VALUE_RTX. */
512 static rtx
513 cr16_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
514 int incoming ATTRIBUTE_UNUSED)
516 return gen_rtx_REG (Pmode, cr16_ret_register ());
519 /* Returning function value. */
521 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */
522 static bool
523 cr16_function_value_regno_p (const unsigned int regno)
525 return (regno == cr16_ret_register ());
528 /* Create an RTX representing the place where a
529 library function returns a value of mode MODE. */
530 static rtx
531 cr16_libcall_value (enum machine_mode mode,
532 const_rtx func ATTRIBUTE_UNUSED)
534 return gen_rtx_REG (mode, cr16_ret_register ());
537 /* Create an RTX representing the place where a
538 function returns a value of data type VALTYPE. */
539 static rtx
540 cr16_function_value (const_tree type,
541 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
542 bool outgoing ATTRIBUTE_UNUSED)
544 return gen_rtx_REG (TYPE_MODE (type), cr16_ret_register ());
547 /* Passing function arguments. */
549 /* If enough param regs are available for passing the param of type TYPE return
550 the number of registers needed else 0. */
551 static int
552 enough_regs_for_param (CUMULATIVE_ARGS * cum, const_tree type,
553 enum machine_mode mode)
555 int type_size;
556 int remaining_size;
558 if (mode != BLKmode)
559 type_size = GET_MODE_BITSIZE (mode);
560 else
561 type_size = int_size_in_bytes (type) * BITS_PER_UNIT;
563 remaining_size = BITS_PER_WORD * (MAX_REG_FOR_PASSING_ARGS
564 - (MIN_REG_FOR_PASSING_ARGS + cum->ints) +
567 /* Any variable which is too big to pass in two registers, will pass on
568 stack. */
569 if ((remaining_size >= type_size) && (type_size <= 2 * BITS_PER_WORD))
570 return (type_size + BITS_PER_WORD - 1) / BITS_PER_WORD;
572 return 0;
575 /* Implements the macro FUNCTION_ARG defined in cr16.h. */
576 static rtx
577 cr16_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
578 const_tree type, bool named ATTRIBUTE_UNUSED)
580 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
581 cum->last_parm_in_reg = 0;
583 /* function_arg () is called with this type just after all the args have
584 had their registers assigned. The rtx that function_arg returns from
585 this type is supposed to pass to 'gen_call' but currently it is not
586 implemented (see macro GEN_CALL). */
587 if (type == void_type_node)
588 return NULL_RTX;
590 if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
591 return NULL_RTX;
593 if (mode == BLKmode)
595 /* Enable structures that need padding bytes at the end to pass to a
596 function in registers. */
597 if (enough_regs_for_param (cum, type, mode) != 0)
599 cum->last_parm_in_reg = 1;
600 return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
604 if ((MIN_REG_FOR_PASSING_ARGS + cum->ints) > MAX_REG_FOR_PASSING_ARGS)
605 return NULL_RTX;
606 else
608 if (enough_regs_for_param (cum, type, mode) != 0)
610 cum->last_parm_in_reg = 1;
611 return gen_rtx_REG (mode, MIN_REG_FOR_PASSING_ARGS + cum->ints);
615 return NULL_RTX;
618 /* Implements the macro INIT_CUMULATIVE_ARGS defined in cr16.h. */
619 void
620 cr16_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
621 rtx libfunc ATTRIBUTE_UNUSED)
623 tree param, next_param;
625 cum->ints = 0;
627 /* Determine if this function has variable arguments. This is indicated by
628 the last argument being 'void_type_mode' if there are no variable
629 arguments. Change here for a different vararg. */
630 for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
631 param != NULL_TREE; param = next_param)
633 next_param = TREE_CHAIN (param);
634 if ((next_param == NULL_TREE) && (TREE_VALUE (param) != void_type_node))
636 cum->ints = -1;
637 return;
642 /* Implements the macro FUNCTION_ARG_ADVANCE defined in cr16.h. */
643 static void
644 cr16_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
645 const_tree type, bool named ATTRIBUTE_UNUSED)
647 CUMULATIVE_ARGS * cum = get_cumulative_args (cum_v);
649 /* l holds the number of registers required. */
650 int l = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
652 /* If the parameter isn't passed on a register don't advance cum. */
653 if (!cum->last_parm_in_reg)
654 return;
656 if (targetm.calls.must_pass_in_stack (mode, type) || (cum->ints < 0))
657 return;
659 if ((mode == SImode) || (mode == HImode)
660 || (mode == QImode) || (mode == DImode))
662 if (l <= 1)
663 cum->ints += 1;
664 else
665 cum->ints += l;
667 else if ((mode == SFmode) || (mode == DFmode))
668 cum->ints += l;
669 else if ((mode) == BLKmode)
671 if ((l = enough_regs_for_param (cum, type, mode)) != 0)
672 cum->ints += l;
674 return;
677 /* Implements the macro FUNCTION_ARG_REGNO_P defined in cr16.h.
678 Return nonzero if N is a register used for passing parameters. */
680 cr16_function_arg_regno_p (int n)
682 return ((n <= MAX_REG_FOR_PASSING_ARGS) && (n >= MIN_REG_FOR_PASSING_ARGS));
685 /* Addressing modes.
686 Following set of function implement the macro GO_IF_LEGITIMATE_ADDRESS
687 defined in cr16.h. */
689 /* Helper function to check if is a valid base register that can
690 hold address. */
691 static int
692 cr16_addr_reg_p (rtx addr_reg)
694 rtx reg;
696 if (REG_P (addr_reg))
697 reg = addr_reg;
698 else if ((GET_CODE (addr_reg) == SUBREG)
699 && REG_P (SUBREG_REG (addr_reg))
700 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (addr_reg)))
701 <= UNITS_PER_WORD))
702 reg = SUBREG_REG (addr_reg);
703 else
704 return FALSE;
706 if (GET_MODE (reg) != Pmode)
707 return FALSE;
709 return TRUE;
712 /* Helper functions: Created specifically for decomposing operand of CONST
713 Recursively look into expression x for code or data symbol.
714 The function expects the expression to contain combination of
715 SYMBOL_REF, CONST_INT, (PLUS or MINUS)
716 LABEL_REF, CONST_INT, (PLUS or MINUS)
717 SYMBOL_REF
718 LABEL_REF
719 All other combinations will result in code = -1 and data = ILLEGAL_DM
720 code data
721 -1 ILLEGAL_DM The expression did not contain SYMBOL_REF or LABEL_REF
722 0 DM_FAR SYMBOL_REF was found and it was far data reference.
723 0 DM_DEFAULT SYMBOL_REF was found and it was medium data reference.
724 1 ILLEGAL_DM LABEL_REF was found.
725 2 ILLEGAL_DM SYMBOL_REF was found and it was function reference. */
726 void
727 cr16_decompose_const (rtx x, int *code, enum data_model_type *data,
728 bool treat_as_const)
730 *code = -1;
731 *data = ILLEGAL_DM;
732 switch (GET_CODE (x))
734 case SYMBOL_REF:
735 *code = SYMBOL_REF_FUNCTION_P (x) ? 2 : 0;
736 /* 2 indicates func sym. */
737 if (*code == 0)
739 if (CR16_TARGET_DATA_NEAR)
740 *data = DM_DEFAULT;
741 else if (CR16_TARGET_DATA_MEDIUM)
742 *data = DM_FAR;
743 else if (CR16_TARGET_DATA_FAR)
745 if (treat_as_const)
746 /* This will be used only for printing
747 the qualifier. This call is (may be)
748 made by cr16_print_operand_address. */
749 *data = DM_FAR;
750 else
751 /* This call is (may be) made by
752 cr16_legitimate_address_p. */
753 *data = ILLEGAL_DM;
756 return;
758 case LABEL_REF:
759 /* 1 - indicates non-function symbol. */
760 *code = 1;
761 return;
763 case PLUS:
764 case MINUS:
765 /* Look into the tree nodes. */
766 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
767 cr16_decompose_const (XEXP (x, 1), code, data, treat_as_const);
768 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
769 cr16_decompose_const (XEXP (x, 0), code, data, treat_as_const);
770 return;
771 default:
772 return;
776 /* Decompose Address
777 This function decomposes the address returns the type of address
778 as defined in enum cr16_addrtype. It also fills the parameter *out.
779 The decomposed address can be used for two purposes. One to
780 check if the address is valid and second to print the address
781 operand.
783 Following tables list valid address supported in CR16C/C+ architectures.
784 Legend:
785 aN : Absoulte address N-bit address
786 R : One 16-bit register
787 RP : Consecutive two 16-bit registers or one 32-bit register
788 I : One 32-bit register
789 dispN : Signed displacement of N-bits
791 ----Code addresses----
792 Branch operands:
793 disp9 : CR16_ABSOLUTE (disp)
794 disp17 : CR16_ABSOLUTE (disp)
795 disp25 : CR16_ABSOLUTE (disp)
796 RP + disp25 : CR16_REGP_REL (base, disp)
798 Jump operands:
799 RP : CR16_REGP_REL (base, disp=0)
800 a24 : CR16_ABSOLUTE (disp)
802 ----Data addresses----
803 a20 : CR16_ABSOLUTE (disp) near (1M)
804 a24 : CR16_ABSOLUTE (disp) medium (16M)
805 R + d20 : CR16_REG_REL (base, disp) near (1M+64K)
806 RP + d4 : CR16_REGP_REL (base, disp) far (4G)
807 RP + d16 : CR16_REGP_REL (base, disp) far (4G)
808 RP + d20 : CR16_REGP_REL (base, disp) far (4G)
809 I : *** Valid but port does not support this
810 I + a20 : *** Valid but port does not support this
811 I + RP + d14: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
812 I + RP + d20: CR16_INDEX_REGP_REL (base, index, disp) far (4G)
814 Decomposing Data model in case of absolute address.
816 Target Option Address type Resultant Data ref type
817 ---------------------- ------------ -----------------------
818 CR16_TARGET_MODEL_NEAR ABS20 DM_DEFAULT
819 CR16_TARGET_MODEL_NEAR IMM20 DM_DEFAULT
820 CR16_TARGET_MODEL_NEAR ABS24 Invalid
821 CR16_TARGET_MODEL_NEAR IMM32 Invalid
823 CR16_TARGET_MODEL_MEDIUM ABS20 DM_DEFAULT
824 CR16_TARGET_MODEL_MEDIUM IMM20 DM_DEFAULT
825 CR16_TARGET_MODEL_MEDIUM ABS24 DM_FAR
826 CR16_TARGET_MODEL_MEDIUM IMM32 Invalid
828 CR16_TARGET_MODEL_FAR ABS20 DM_DEFAULT
829 CR16_TARGET_MODEL_FAR IMM20 DM_DEFAULT
830 CR16_TARGET_MODEL_FAR ABS24 DM_FAR
831 CR16_TARGET_MODEL_FAR IMM32 DM_FAR. */
832 enum cr16_addrtype
833 cr16_decompose_address (rtx addr, struct cr16_address *out,
834 bool debug_print, bool treat_as_const)
836 rtx base = NULL_RTX, disp = NULL_RTX, index = NULL_RTX;
837 enum data_model_type data = ILLEGAL_DM;
838 int code = -1;
839 enum cr16_addrtype retval = CR16_INVALID;
841 switch (GET_CODE (addr))
843 case CONST_INT:
844 /* Absolute address (known at compile time). */
845 code = 0;
846 if (debug_print)
847 fprintf (stderr, "\ncode:%d", code);
848 disp = addr;
850 if (debug_print)
852 fprintf (stderr, "\ndisp:");
853 debug_rtx (disp);
856 if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
858 data = DM_DEFAULT;
859 if (debug_print)
860 fprintf (stderr, "\ndata:%d", data);
861 retval = CR16_ABSOLUTE;
863 else if (UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 24))
865 if (!CR16_TARGET_DATA_NEAR)
867 data = DM_FAR;
868 if (debug_print)
869 fprintf (stderr, "\ndata:%d", data);
870 retval = CR16_ABSOLUTE;
872 else
873 return CR16_INVALID; /* ABS24 is not support in NEAR model. */
875 else
876 return CR16_INVALID;
877 break;
879 case CONST:
880 /* A CONST is an expression of PLUS or MINUS with
881 CONST_INT, SYMBOL_REF or LABEL_REF. This is the
882 result of assembly-time arithmetic computation. */
883 retval = CR16_ABSOLUTE;
884 disp = addr;
885 /* Call the helper function to check the validity. */
886 cr16_decompose_const (XEXP (addr, 0), &code, &data, treat_as_const);
887 if ((code == 0) && (data == ILLEGAL_DM))
888 /* CONST is not valid code or data address. */
889 return CR16_INVALID;
890 if (debug_print)
892 fprintf (stderr, "\ndisp:");
893 debug_rtx (disp);
894 fprintf (stderr, "\ncode:%d", code);
895 fprintf (stderr, "\ndata:%d", data);
897 break;
899 case LABEL_REF:
900 retval = CR16_ABSOLUTE;
901 disp = addr;
902 /* 1 - indicates non-function symbol. */
903 code = 1;
904 if (debug_print)
906 fprintf (stderr, "\ndisp:");
907 debug_rtx (disp);
908 fprintf (stderr, "\ncode:%d", code);
910 break;
912 case SYMBOL_REF:
913 /* Absolute address (known at link time). */
914 retval = CR16_ABSOLUTE;
915 disp = addr;
916 /* This is a code address if symbol_ref is a function. */
917 /* 2 indicates func sym. */
918 code = SYMBOL_REF_FUNCTION_P (addr) ? 2 : 0;
919 if (debug_print)
921 fprintf (stderr, "\ndisp:");
922 debug_rtx (disp);
923 fprintf (stderr, "\ncode:%d", code);
925 /* If not function ref then check if valid data ref. */
926 if (code == 0)
928 if (CR16_TARGET_DATA_NEAR)
929 data = DM_DEFAULT;
930 else if (CR16_TARGET_DATA_MEDIUM)
931 data = DM_FAR;
932 else if (CR16_TARGET_DATA_FAR)
934 if (treat_as_const)
935 /* This will be used only for printing the
936 qualifier. This call is (may be) made
937 by cr16_print_operand_address. */
938 data = DM_FAR;
939 else
940 /* This call is (may be) made by
941 cr16_legitimate_address_p. */
942 return CR16_INVALID;
944 else
945 data = DM_DEFAULT;
947 if (debug_print)
948 fprintf (stderr, "\ndata:%d", data);
949 break;
951 case REG:
952 case SUBREG:
953 /* Register relative address. */
954 /* Assume REG fits in a single register. */
955 retval = CR16_REG_REL;
956 if (GET_MODE_BITSIZE (GET_MODE (addr)) > BITS_PER_WORD)
957 if (!LONG_REG_P (REGNO (addr)))
958 /* REG will result in reg pair. */
959 retval = CR16_REGP_REL;
960 base = addr;
961 if (debug_print)
963 fprintf (stderr, "\nbase:");
964 debug_rtx (base);
966 break;
968 case PLUS:
969 switch (GET_CODE (XEXP (addr, 0)))
971 case REG:
972 case SUBREG:
973 /* REG + DISP20. */
974 /* All Reg relative addresses having a displacement needs
975 to fit in 20-bits. */
976 disp = XEXP (addr, 1);
977 if (debug_print)
979 fprintf (stderr, "\ndisp:");
980 debug_rtx (disp);
982 switch (GET_CODE (XEXP (addr, 1)))
984 case CONST_INT:
985 /* Shall fit in 20-bits. */
986 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
987 return CR16_INVALID;
988 code = 0;
989 if (debug_print)
990 fprintf (stderr, "\ncode:%d", code);
991 break;
993 case UNSPEC:
994 switch (XINT (XEXP (addr, 1), 1))
996 case UNSPEC_LIBRARY_OFFSET:
997 default:
998 gcc_unreachable ();
1000 break;
1002 case LABEL_REF:
1003 case SYMBOL_REF:
1004 case CONST:
1005 /* This is also a valid expression for address.
1006 However, we cannot ascertain if the resultant
1007 displacement will be valid 20-bit value. Therefore,
1008 lets not allow such an expression for now. This will
1009 be updated when we find a way to validate this
1010 expression as legitimate address.
1011 Till then fall through CR16_INVALID. */
1012 default:
1013 return CR16_INVALID;
1016 /* Now check if REG can fit into single or pair regs. */
1017 retval = CR16_REG_REL;
1018 base = XEXP (addr, 0);
1019 if (debug_print)
1021 fprintf (stderr, "\nbase:");
1022 debug_rtx (base);
1024 if (GET_MODE_BITSIZE (GET_MODE ((XEXP (addr, 0)))) > BITS_PER_WORD)
1026 if (!LONG_REG_P (REGNO ((XEXP (addr, 0)))))
1027 /* REG will result in reg pair. */
1028 retval = CR16_REGP_REL;
1030 break;
1032 case PLUS:
1033 /* Valid expr:
1034 plus
1037 plus idx
1040 reg const_int
1042 Check if the operand 1 is valid index register. */
1043 data = ILLEGAL_DM;
1044 if (debug_print)
1045 fprintf (stderr, "\ndata:%d", data);
1046 switch (GET_CODE (XEXP (addr, 1)))
1048 case REG:
1049 case SUBREG:
1050 if (!REG_OK_FOR_INDEX_P (XEXP (addr, 1)))
1051 return CR16_INVALID;
1052 /* OK. REG is a valid index register. */
1053 index = XEXP (addr, 1);
1054 if (debug_print)
1056 fprintf (stderr, "\nindex:");
1057 debug_rtx (index);
1059 break;
1060 default:
1061 return CR16_INVALID;
1063 /* Check if operand 0 of operand 0 is REGP. */
1064 switch (GET_CODE (XEXP (XEXP (addr, 0), 0)))
1066 case REG:
1067 case SUBREG:
1068 /* Now check if REG is a REGP and not in LONG regs. */
1069 if (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (addr, 0), 0)))
1070 > BITS_PER_WORD)
1072 if (REGNO (XEXP (XEXP (addr, 0), 0))
1073 >= CR16_FIRST_DWORD_REGISTER)
1074 return CR16_INVALID;
1075 base = XEXP (XEXP (addr, 0), 0);
1076 if (debug_print)
1078 fprintf (stderr, "\nbase:");
1079 debug_rtx (base);
1082 else
1083 return CR16_INVALID;
1084 break;
1085 default:
1086 return CR16_INVALID;
1088 /* Now check if the operand 1 of operand 0 is const_int. */
1089 if (GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
1091 disp = XEXP (XEXP (addr, 0), 1);
1092 if (debug_print)
1094 fprintf (stderr, "\ndisp:");
1095 debug_rtx (disp);
1097 if (!UNSIGNED_INT_FITS_N_BITS (INTVAL (disp), 20))
1098 return CR16_INVALID;
1100 else
1101 return CR16_INVALID;
1102 retval = CR16_INDEX_REGP_REL;
1103 break;
1104 default:
1105 return CR16_INVALID;
1107 break;
1109 default:
1110 return CR16_INVALID;
1113 /* Check if the base and index registers are valid. */
1114 if (base && !(cr16_addr_reg_p (base)))
1115 return CR16_INVALID;
1116 if (base && !(CR16_REG_OK_FOR_BASE_P (base)))
1117 return CR16_INVALID;
1118 if (index && !(REG_OK_FOR_INDEX_P (index)))
1119 return CR16_INVALID;
1121 /* Write the decomposition to out parameter. */
1122 out->base = base;
1123 out->disp = disp;
1124 out->index = index;
1125 out->data = data;
1126 out->code = code;
1128 return retval;
1131 /* Return non-zero value if 'x' is legitimate PIC operand
1132 when generating PIC code. */
1134 legitimate_pic_operand_p (rtx x)
1136 switch (GET_CODE (x))
1138 case SYMBOL_REF:
1139 return 0;
1140 break;
1141 case LABEL_REF:
1142 return 0;
1143 break;
1144 case CONST:
1145 /* REVISIT: Use something like symbol_referenced_p. */
1146 if (GET_CODE (XEXP (x, 0)) == PLUS
1147 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
1148 || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
1149 && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
1150 return 0;
1151 break;
1152 case MEM:
1153 return legitimate_pic_operand_p (XEXP (x, 0));
1154 break;
1155 default:
1156 break;
1158 return 1;
1161 /* Convert a non-PIC address in `orig' to a PIC address in `reg'.
1163 Input Output (-f pic) Output (-f PIC)
1164 orig reg
1166 C1 symbol symbol@BRO (r12) symbol@GOT (r12)
1168 C2 symbol + offset symbol+offset@BRO (r12) symbol+offset@GOT (r12)
1170 NOTE: @BRO is added using unspec:BRO
1171 NOTE: @GOT is added using unspec:GOT. */
1173 legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
1174 rtx reg)
1176 /* First handle a simple SYMBOL_REF or LABEL_REF. */
1177 if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
1179 if (reg == 0)
1180 reg = gen_reg_rtx (Pmode);
1182 if (flag_pic == NEAR_PIC)
1184 /* Unspec to handle -fpic option. */
1185 emit_insn (gen_unspec_bro_addr (reg, orig));
1186 emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
1188 else if (flag_pic == FAR_PIC)
1190 /* Unspec to handle -fPIC option. */
1191 emit_insn (gen_unspec_got_addr (reg, orig));
1193 return reg;
1195 else if (GET_CODE (orig) == CONST)
1197 /* To handle (symbol + offset). */
1198 rtx base, offset;
1200 if (GET_CODE (XEXP (orig, 0)) == PLUS
1201 && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
1202 return orig;
1204 if (reg == 0)
1206 gcc_assert (can_create_pseudo_p ());
1207 reg = gen_reg_rtx (Pmode);
1210 gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
1212 base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
1213 offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
1214 base == reg ? 0 : reg);
1216 /* REVISIT: Optimize for const-offsets. */
1217 emit_insn (gen_addsi3 (reg, base, offset));
1219 return reg;
1221 return orig;
1224 /* Implementation of TARGET_LEGITIMATE_ADDRESS_P. */
1225 static bool
1226 cr16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
1227 rtx addr, bool strict)
1229 enum cr16_addrtype addrtype;
1230 struct cr16_address address;
1232 if (TARGET_DEBUG_ADDR)
1234 fprintf (stderr,
1235 "\n======\nTARGET_LEGITIMATE_ADDRESS_P, mode = %s, strict = %d",
1236 GET_MODE_NAME (mode), strict);
1237 debug_rtx (addr);
1239 addrtype = cr16_decompose_address (addr, &address,
1240 (TARGET_DEBUG_ADDR ? 1 : 0), FALSE);
1242 if (TARGET_DEBUG_ADDR)
1244 const char *typestr;
1246 switch (addrtype)
1248 case CR16_INVALID:
1249 typestr = "invalid";
1250 break;
1251 case CR16_ABSOLUTE:
1252 typestr = "absolute";
1253 break;
1254 case CR16_REG_REL:
1255 typestr = "register relative";
1256 break;
1257 case CR16_REGP_REL:
1258 typestr = "register pair relative";
1259 break;
1260 case CR16_INDEX_REGP_REL:
1261 typestr = "index + register pair relative";
1262 break;
1263 default:
1264 gcc_unreachable ();
1266 fprintf (stderr, "\ncr16 address type: %s\n", typestr);
1269 if (addrtype == CR16_INVALID)
1270 return FALSE;
1272 if (strict)
1274 if (address.base
1275 && !REGNO_MODE_OK_FOR_BASE_P (REGNO (address.base), mode))
1277 if (TARGET_DEBUG_ADDR)
1278 fprintf (stderr, "base register not strict\n");
1279 return FALSE;
1281 if (address.index && !REGNO_OK_FOR_INDEX_P (REGNO (address.index)))
1283 if (TARGET_DEBUG_ADDR)
1284 fprintf (stderr, "index register not strict\n");
1285 return FALSE;
1289 /* Return true if addressing mode is register relative. */
1290 if (flag_pic)
1292 if (addrtype == CR16_REG_REL || addrtype == CR16_REGP_REL)
1293 return TRUE;
1294 else
1295 return FALSE;
1298 return TRUE;
1301 /* Routines to compute costs. */
1303 /* Return cost of the memory address x. */
1304 static int
1305 cr16_address_cost (rtx addr, enum machine_mode mode ATTRIBUTE_UNUSED,
1306 addr_space_t as ATTRIBUTE_UNUSED,
1307 bool speed ATTRIBUTE_UNUSED)
1309 enum cr16_addrtype addrtype;
1310 struct cr16_address address;
1311 int cost = 2;
1313 addrtype = cr16_decompose_address (addr, &address, 0, FALSE);
1315 gcc_assert (addrtype != CR16_INVALID);
1317 /* CR16_ABSOLUTE : 3
1318 CR16_REG_REL (disp !=0) : 4
1319 CR16_REG_REL (disp ==0) : 5
1320 CR16_REGP_REL (disp !=0) : 6
1321 CR16_REGP_REL (disp ==0) : 7
1322 CR16_INDEX_REGP_REL (disp !=0) : 8
1323 CR16_INDEX_REGP_REL (disp ==0) : 9. */
1324 switch (addrtype)
1326 case CR16_ABSOLUTE:
1327 cost += 1;
1328 break;
1329 case CR16_REGP_REL:
1330 cost += 2;
1331 /* Fall through. */
1332 case CR16_REG_REL:
1333 cost += 3;
1334 if (address.disp)
1335 cost -= 1;
1336 break;
1337 case CR16_INDEX_REGP_REL:
1338 cost += 7;
1339 if (address.disp)
1340 cost -= 1;
1341 default:
1342 break;
1345 if (TARGET_DEBUG_ADDR)
1347 fprintf (stderr, "\n======\nmacro TARGET_ADDRESS_COST = %d\n", cost);
1348 debug_rtx (addr);
1351 return cost;
1355 /* Implement `TARGET_REGISTER_MOVE_COST'. */
1356 static int
1357 cr16_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1358 reg_class_t from ATTRIBUTE_UNUSED, reg_class_t to)
1360 return (to != GENERAL_REGS ? 8 : 2);
1363 /* Implement `TARGET_MEMORY_MOVE_COST'. */
1365 /* Return the cost of moving data of mode MODE between a register of class
1366 CLASS and memory; IN is zero if the value is to be written to memory,
1367 nonzero if it is to be read in. This cost is relative to those in
1368 REGISTER_MOVE_COST. */
1369 static int
1370 cr16_memory_move_cost (enum machine_mode mode,
1371 reg_class_t rclass ATTRIBUTE_UNUSED,
1372 bool in ATTRIBUTE_UNUSED)
1374 /* One LD or ST takes twice the time of a simple reg-reg move. */
1375 if (reg_classes_intersect_p (rclass, GENERAL_REGS))
1376 return (4 * HARD_REGNO_NREGS (0, mode));
1377 else
1378 return (100);
1381 /* Instruction output. */
1383 /* Check if a const_double is ok for cr16 store-immediate instructions. */
1385 cr16_const_double_ok (rtx op)
1387 if (GET_MODE (op) == SFmode)
1389 REAL_VALUE_TYPE r;
1390 long l;
1391 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1392 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1393 return UNSIGNED_INT_FITS_N_BITS (l, 4) ? 1 : 0;
1396 return ((UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_LOW (op), 4)) &&
1397 (UNSIGNED_INT_FITS_N_BITS (CONST_DOUBLE_HIGH (op), 4))) ? 1 : 0;
1400 /* Returns bit position of first 0 or 1 bit.
1401 It is safe to assume val as 16-bit wide. */
1403 cr16_operand_bit_pos (int val, int bitval)
1405 int i;
1406 if (bitval == 0)
1407 val = ~val;
1409 for (i = 0; i < 16; i++)
1410 if (val & (1 << i))
1411 break;
1412 return i;
1415 /* Implements the macro PRINT_OPERAND defined in cr16.h. */
1416 static void
1417 cr16_print_operand (FILE * file, rtx x, int code)
1419 int ptr_dereference = 0;
1421 switch (code)
1423 case 'd':
1425 const char *cr16_cmp_str;
1426 switch (GET_CODE (x))
1428 /* MD: compare (reg, reg or imm) but CR16: cmp (reg or imm, reg)
1429 -> swap all non symmetric ops. */
1430 case EQ:
1431 cr16_cmp_str = "eq";
1432 break;
1433 case NE:
1434 cr16_cmp_str = "ne";
1435 break;
1436 case GT:
1437 cr16_cmp_str = "lt";
1438 break;
1439 case GTU:
1440 cr16_cmp_str = "lo";
1441 break;
1442 case LT:
1443 cr16_cmp_str = "gt";
1444 break;
1445 case LTU:
1446 cr16_cmp_str = "hi";
1447 break;
1448 case GE:
1449 cr16_cmp_str = "le";
1450 break;
1451 case GEU:
1452 cr16_cmp_str = "ls";
1453 break;
1454 case LE:
1455 cr16_cmp_str = "ge";
1456 break;
1457 case LEU:
1458 cr16_cmp_str = "hs";
1459 break;
1460 default:
1461 gcc_unreachable ();
1463 fprintf (file, "%s", cr16_cmp_str);
1464 return;
1466 case '$':
1467 putc ('$', file);
1468 return;
1470 case 'p':
1471 if (GET_CODE (x) == REG)
1473 /* For Push instructions, we should not print register pairs. */
1474 fprintf (file, "%s", reg_names[REGNO (x)]);
1475 return;
1477 break;
1479 case 'b':
1480 /* Print the immediate address for bal
1481 'b' is used instead of 'a' to avoid compiler calling
1482 the GO_IF_LEGITIMATE_ADDRESS which cannot
1483 perform checks on const_int code addresses as it
1484 assumes all const_int are data addresses. */
1485 fprintf (file, "0x%lx", INTVAL (x));
1486 return;
1488 case 'r':
1489 /* Print bit position of first 0. */
1490 fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 0));
1491 return;
1493 case 's':
1494 /* Print bit position of first 1. */
1495 fprintf (file, "%d", cr16_operand_bit_pos (INTVAL (x), 1));
1496 return;
1497 case 'g':
1498 /* 'g' is used for implicit mem: dereference. */
1499 ptr_dereference = 1;
1500 case 'f':
1501 case 0:
1502 /* default. */
1503 switch (GET_CODE (x))
1505 case REG:
1506 if (GET_MODE_BITSIZE (GET_MODE (x)) > BITS_PER_WORD)
1508 if (LONG_REG_P (REGNO (x)))
1509 fprintf (file, "(%s)", reg_names[REGNO (x)]);
1510 else
1511 fprintf (file, "(%s,%s)", reg_names[REGNO (x) + 1],
1512 reg_names[REGNO (x)]);
1514 else
1515 fprintf (file, "%s", reg_names[REGNO (x)]);
1516 return;
1518 case MEM:
1519 output_address (XEXP (x, 0));
1520 return;
1522 case CONST_DOUBLE:
1524 REAL_VALUE_TYPE r;
1525 long l;
1527 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
1528 REAL_VALUE_TO_TARGET_SINGLE (r, l);
1530 fprintf (file, "$0x%lx", l);
1531 return;
1533 case CONST_INT:
1535 fprintf (file, "$%ld", INTVAL (x));
1536 return;
1538 case UNSPEC:
1539 switch (XINT (x, 1))
1541 default:
1542 gcc_unreachable ();
1544 break;
1546 default:
1547 if (!ptr_dereference)
1549 putc ('$', file);
1551 cr16_print_operand_address (file, x);
1552 return;
1554 default:
1555 output_operand_lossage ("invalid %%xn code");
1558 gcc_unreachable ();
1561 /* Implements the macro PRINT_OPERAND_ADDRESS defined in cr16.h. */
1563 static void
1564 cr16_print_operand_address (FILE * file, rtx addr)
1566 enum cr16_addrtype addrtype;
1567 struct cr16_address address;
1569 /* Decompose the address. Also ask it to treat address as constant. */
1570 addrtype = cr16_decompose_address (addr, &address, 0, TRUE);
1572 if (address.disp && GET_CODE (address.disp) == UNSPEC)
1574 debug_rtx (addr);
1577 switch (addrtype)
1579 case CR16_REG_REL:
1580 if (address.disp)
1582 if (GET_CODE (address.disp) == UNSPEC)
1583 cr16_print_operand (file, address.disp, 0);
1584 else
1585 output_addr_const (file, address.disp);
1587 else
1588 fprintf (file, "0");
1589 fprintf (file, "(%s)", reg_names[REGNO (address.base)]);
1590 break;
1592 case CR16_ABSOLUTE:
1593 if (address.disp)
1594 output_addr_const (file, address.disp);
1595 else
1596 fprintf (file, "0");
1597 break;
1599 case CR16_INDEX_REGP_REL:
1600 fprintf (file, "[%s]", reg_names[REGNO (address.index)]);
1601 /* Fall through. */
1602 case CR16_REGP_REL:
1603 if (address.disp)
1605 if (GET_CODE (address.disp) == UNSPEC)
1606 cr16_print_operand (file, address.disp, 0);
1607 else
1608 output_addr_const (file, address.disp);
1610 else
1611 fprintf (file, "0");
1612 fprintf (file, "(%s,%s)", reg_names[REGNO (address.base) + 1],
1613 reg_names[REGNO (address.base)]);
1614 break;
1615 default:
1616 debug_rtx (addr);
1617 gcc_unreachable ();
1619 /* Add qualifiers to the address expression that was just printed. */
1620 if (flag_pic < NEAR_PIC && address.code == 0)
1622 if (address.data == DM_FAR)
1623 /* Addr contains SYMBOL_REF & far data ptr. */
1624 fprintf (file, "@l");
1625 else if (address.data == DM_DEFAULT)
1626 /* Addr contains SYMBOL_REF & medium data ptr. */
1627 fprintf (file, "@m");
1628 /* Addr contains SYMBOL_REF & medium data ptr. */
1629 else if (address.data == DM_NEAR)
1630 /* Addr contains SYMBOL_REF & near data ptr. */
1631 fprintf (file, "@s");
1633 else if (flag_pic == NEAR_PIC
1634 && (address.code == 0) && (address.data == DM_FAR
1635 || address.data == DM_DEFAULT
1636 || address.data == DM_NEAR))
1638 fprintf (file, "@l");
1640 else if (flag_pic == NEAR_PIC && address.code == 2)
1642 fprintf (file, "pic");
1644 else if (flag_pic == NEAR_PIC && address.code == 1)
1646 fprintf (file, "@cpic");
1649 else if (flag_pic == FAR_PIC && address.code == 2)
1651 /* REVISIT: cr16 register indirect jump expects a 1-bit right shifted
1652 address ! GOTc tells assembler this symbol is a text-address
1653 This needs to be fixed in such a way that this offset is done
1654 only in the case where an address is being used for indirect jump
1655 or call. Determining the potential usage of loadd is of course not
1656 possible always. Eventually, this has to be fixed in the
1657 processor. */
1658 fprintf (file, "GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
1660 else if (flag_pic == FAR_PIC && address.code == 1)
1662 fprintf (file, "@cGOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
1665 else if (flag_pic == FAR_PIC &&
1666 (address.data == DM_FAR || address.data == DM_DEFAULT
1667 || address.data == DM_NEAR))
1669 fprintf (file, "@GOT (%s)", reg_names[PIC_OFFSET_TABLE_REGNUM]);
1673 /* Machine description helper functions. */
1675 /* Called from cr16.md. The return value depends on the parameter push_or_pop:
1676 When push_or_pop is zero -> string for push instructions of prologue.
1677 When push_or_pop is nonzero -> string for pop/popret/retx in epilogue.
1678 Relies on the assumptions:
1679 1. RA is the last register to be saved.
1680 2. The maximal value of the counter is MAX_COUNT. */
1681 char *
1682 cr16_prepare_push_pop_string (int push_or_pop)
1684 /* j is the number of registers being saved, takes care that there won't be
1685 more than 8 in one push/pop instruction. */
1687 /* For the register mask string. */
1688 static char one_inst_str[50];
1690 /* i is the index of current_frame_info.save_regs[], going from 0 until
1691 current_frame_info.last_reg_to_save. */
1692 int i, start_reg;
1693 int word_cnt;
1694 int print_ra;
1695 char *return_str;
1697 /* For reversing on the push instructions if there are more than one. */
1698 char *temp_str;
1700 return_str = (char *) xmalloc (160);
1701 temp_str = (char *) xmalloc (160);
1703 /* Initialize. */
1704 memset (return_str, 0, 3);
1706 i = 0;
1707 while (i <= current_frame_info.last_reg_to_save)
1709 /* Prepare mask for one instruction. */
1710 one_inst_str[0] = 0;
1712 /* To count number of words in one instruction. */
1713 word_cnt = 0;
1714 start_reg = i;
1715 print_ra = 0;
1716 while ((word_cnt < MAX_COUNT)
1717 && (i <= current_frame_info.last_reg_to_save))
1719 /* For each non consecutive save register,
1720 a new instruction shall be generated. */
1721 if (!current_frame_info.save_regs[i])
1723 /* Move to next reg and break. */
1724 ++i;
1725 break;
1728 if (i == RETURN_ADDRESS_REGNUM)
1729 print_ra = 1;
1730 else
1732 /* Check especially if adding 2 does not cross the MAX_COUNT. */
1733 if ((word_cnt + ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2))
1734 >= MAX_COUNT)
1735 break;
1736 /* Increase word count by 2 for long registers except RA. */
1737 word_cnt += ((i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2);
1739 ++i;
1742 /* No need to generate any instruction as
1743 no register or RA needs to be saved. */
1744 if ((word_cnt == 0) && (print_ra == 0))
1745 continue;
1747 /* Now prepare the instruction operands. */
1748 if (word_cnt > 0)
1750 sprintf (one_inst_str, "$%d, %s", word_cnt, reg_names[start_reg]);
1751 if (print_ra)
1752 strcat (one_inst_str, ", ra");
1754 else
1755 strcat (one_inst_str, "ra");
1757 if (push_or_pop == 1)
1759 /* Pop instruction. */
1760 if (print_ra && !cr16_interrupt_function_p ()
1761 && !crtl->calls_eh_return)
1762 /* Print popret if RA is saved and its not a interrupt
1763 function. */
1764 strcpy (temp_str, "\n\tpopret\t");
1765 else
1766 strcpy (temp_str, "\n\tpop\t");
1768 strcat (temp_str, one_inst_str);
1770 /* Add the pop instruction list. */
1771 strcat (return_str, temp_str);
1773 else
1775 /* Push instruction. */
1776 strcpy (temp_str, "\n\tpush\t");
1777 strcat (temp_str, one_inst_str);
1779 /* We need to reverse the order of the instructions if there
1780 are more than one. (since the pop will not be reversed in
1781 the epilogue. */
1782 strcat (temp_str, return_str);
1783 strcpy (return_str, temp_str);
1787 if (push_or_pop == 1)
1789 /* POP. */
1790 if (cr16_interrupt_function_p ())
1791 strcat (return_str, "\n\tretx\n");
1792 else if (crtl->calls_eh_return)
1794 /* Add stack adjustment before returning to exception handler
1795 NOTE: EH_RETURN_STACKADJ_RTX must refer to (r5, r4). */
1796 strcat (return_str, "\n\taddd\t (r5, r4), (sp)\t\n");
1797 strcat (return_str, "\n\tjump\t (ra)\n");
1799 /* But before anything else, undo the adjustment addition done in
1800 cr16_expand_epilogue (). */
1801 strcpy (temp_str, "\n\tsubd\t (r5, r4), (sp)\t\n");
1802 strcat (temp_str, return_str);
1803 strcpy (return_str, temp_str);
1805 else if (!FUNC_IS_NORETURN_P (current_function_decl)
1806 && !(current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]))
1807 strcat (return_str, "\n\tjump\t (ra)\n");
1810 /* Skip the newline and the tab in the start of return_str. */
1811 return_str += 2;
1812 return return_str;
1816 /* Generate DWARF2 annotation for multi-push instruction. */
1817 static void
1818 cr16_create_dwarf_for_multi_push (rtx insn)
1820 rtx dwarf, reg, tmp;
1821 int i, j, from, to, word_cnt, dwarf_par_index, inc;
1822 enum machine_mode mode;
1823 int num_regs = 0, offset = 0, split_here = 0, total_push_bytes = 0;
1825 for (i = 0; i <= current_frame_info.last_reg_to_save; ++i)
1827 if (current_frame_info.save_regs[i])
1829 ++num_regs;
1830 if (i < CR16_FIRST_DWORD_REGISTER)
1831 total_push_bytes += 2;
1832 else
1833 total_push_bytes += 4;
1837 if (!num_regs)
1838 return;
1840 dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_regs + 1));
1841 dwarf_par_index = num_regs;
1843 from = current_frame_info.last_reg_to_save + 1;
1844 to = current_frame_info.last_reg_to_save;
1845 word_cnt = 0;
1847 for (i = current_frame_info.last_reg_to_save; i >= 0;)
1849 if (!current_frame_info.save_regs[i] || 0 == i || split_here)
1851 /* This block of regs is pushed in one instruction. */
1852 if (0 == i && current_frame_info.save_regs[i])
1853 from = 0;
1855 for (j = to; j >= from; --j)
1857 if (j < CR16_FIRST_DWORD_REGISTER)
1859 mode = HImode;
1860 inc = 1;
1862 else
1864 mode = SImode;
1865 inc = 2;
1867 reg = gen_rtx_REG (mode, j);
1868 offset += 2 * inc;
1869 tmp = gen_rtx_SET (VOIDmode,
1870 gen_frame_mem (mode,
1871 plus_constant
1872 (Pmode, stack_pointer_rtx,
1873 total_push_bytes - offset)),
1874 reg);
1875 RTX_FRAME_RELATED_P (tmp) = 1;
1876 XVECEXP (dwarf, 0, dwarf_par_index--) = tmp;
1878 from = i;
1879 to = --i;
1880 split_here = 0;
1881 word_cnt = 0;
1882 continue;
1885 if (i != RETURN_ADDRESS_REGNUM)
1887 inc = (i < CR16_FIRST_DWORD_REGISTER) ? 1 : 2;
1888 if (word_cnt + inc >= MAX_COUNT || FRAME_POINTER_REGNUM == i)
1890 split_here = 1;
1891 from = i;
1892 continue;
1894 word_cnt += inc;
1897 from = i--;
1900 tmp = gen_rtx_SET (SImode, stack_pointer_rtx,
1901 gen_rtx_PLUS (SImode, stack_pointer_rtx,
1902 GEN_INT (-offset)));
1903 RTX_FRAME_RELATED_P (tmp) = 1;
1904 XVECEXP (dwarf, 0, 0) = tmp;
1906 add_reg_note (insn, REG_FRAME_RELATED_EXPR, dwarf);
1910 CompactRISC CR16 Architecture stack layout:
1912 0 +---------------------
1917 +==================== Sp (x) = Ap (x+1)
1918 A | Args for functions
1919 | | called by X and Dynamically
1920 | | Dynamic allocations allocated and
1921 | | (alloca, variable deallocated
1922 Stack | length arrays).
1923 grows +-------------------- Fp (x)
1924 down| | Local variables of X
1925 ward| +--------------------
1926 | | Regs saved for X-1
1927 | +==================== Sp (x-1) = Ap (x)
1928 | Args for func X
1929 | pushed by X-1
1930 +-------------------- Fp (x-1)
1935 void
1936 cr16_expand_prologue (void)
1938 rtx insn;
1940 cr16_compute_frame ();
1941 cr16_compute_save_regs ();
1943 /* If there is no need in push and adjustment to sp, return. */
1944 if ((current_frame_info.total_size + current_frame_info.reg_size) == 0)
1945 return;
1947 if (current_frame_info.last_reg_to_save != -1)
1949 /* If there are registers to push. */
1950 insn = emit_insn (gen_push_for_prologue
1951 (GEN_INT (current_frame_info.reg_size)));
1952 cr16_create_dwarf_for_multi_push (insn);
1953 RTX_FRAME_RELATED_P (insn) = 1;
1957 if (current_frame_info.total_size > 0)
1959 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1960 GEN_INT (-current_frame_info.total_size)));
1961 RTX_FRAME_RELATED_P (insn) = 1;
1964 if (frame_pointer_needed)
1966 /* Initialize the frame pointer with the value of the stack pointer
1967 pointing now to the locals. */
1968 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1972 /* Generate insn that updates the stack for local variables and padding
1973 for registers we save. - Generate the appropriate return insn. */
1974 void
1975 cr16_expand_epilogue (void)
1977 rtx insn;
1979 /* Nonzero if we need to return and pop only RA. This will generate a
1980 different insn. This differentiate is for the peepholes for call as
1981 last statement in function. */
1982 int only_popret_RA = (current_frame_info.save_regs[RETURN_ADDRESS_REGNUM]
1983 && (current_frame_info.reg_size
1984 == CR16_UNITS_PER_DWORD));
1986 if (frame_pointer_needed)
1988 /* Restore the stack pointer with the frame pointers value. */
1989 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
1992 if (current_frame_info.total_size > 0)
1994 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
1995 GEN_INT (current_frame_info.total_size)));
1996 RTX_FRAME_RELATED_P (insn) = 1;
1999 if (crtl->calls_eh_return)
2001 /* Add this here so that (r5, r4) is actually loaded with the adjustment
2002 value; otherwise, the load might be optimized away...
2003 NOTE: remember to subtract the adjustment before popping the regs
2004 and add it back before returning. */
2005 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2006 EH_RETURN_STACKADJ_RTX));
2009 if (cr16_interrupt_function_p ())
2011 insn = emit_jump_insn (gen_interrupt_return ());
2012 RTX_FRAME_RELATED_P (insn) = 1;
2014 else if (crtl->calls_eh_return)
2016 /* Special case, pop what's necessary, adjust SP and jump to (RA). */
2017 insn = emit_jump_insn (gen_pop_and_popret_return
2018 (GEN_INT (current_frame_info.reg_size)));
2019 RTX_FRAME_RELATED_P (insn) = 1;
2021 else if (current_frame_info.last_reg_to_save == -1)
2022 /* Nothing to pop. */
2023 /* Don't output jump for interrupt routine, only retx. */
2024 emit_jump_insn (gen_jump_return ());
2025 else if (only_popret_RA)
2027 insn = emit_jump_insn (gen_popret_RA_return ());
2028 RTX_FRAME_RELATED_P (insn) = 1;
2030 else
2032 insn = emit_jump_insn (gen_pop_and_popret_return
2033 (GEN_INT (current_frame_info.reg_size)));
2034 RTX_FRAME_RELATED_P (insn) = 1;
2038 /* Implements FRAME_POINTER_REQUIRED. */
2039 static bool
2040 cr16_frame_pointer_required (void)
2042 return (cfun->calls_alloca || crtl->calls_eh_return
2043 || cfun->has_nonlocal_label || crtl->calls_eh_return);
2046 static bool
2047 cr16_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
2049 return (to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true);
2053 /* A C compound statement that attempts to replace X with
2054 a valid memory address for an operand of mode MODE. WIN
2055 will be a C statement label elsewhere in the code.
2056 X will always be the result of a call to break_out_memory_refs (),
2057 and OLDX will be the operand that was given to that function to
2058 produce X.
2059 The code generated by this macro should not alter the
2060 substructure of X. If it transforms X into a more legitimate form,
2061 it should assign X (which will always be a C variable) a new value. */
2062 static rtx
2063 cr16_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
2064 enum machine_mode mode ATTRIBUTE_UNUSED)
2066 if (flag_pic)
2067 return legitimize_pic_address (orig_x, mode, NULL_RTX);
2068 else
2069 return x;
2072 /* Implement TARGET_LEGITIMATE_CONSTANT_P
2073 Nonzero if X is a legitimate constant for an immediate
2074 operand on the target machine. You can assume that X
2075 satisfies CONSTANT_P. In cr16c treat legitimize float
2076 constant as an immediate operand. */
2077 static bool
2078 cr16_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
2079 rtx x ATTRIBUTE_UNUSED)
2081 return 1;
2084 void
2085 notice_update_cc (rtx exp)
2087 if (GET_CODE (exp) == SET)
2089 /* Jumps do not alter the cc's. */
2090 if (SET_DEST (exp) == pc_rtx)
2091 return;
2093 /* Moving register or memory into a register:
2094 it doesn't alter the cc's, but it might invalidate
2095 the RTX's which we remember the cc's came from.
2096 (Note that moving a constant 0 or 1 MAY set the cc's). */
2097 if (REG_P (SET_DEST (exp))
2098 && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM))
2100 return;
2103 /* Moving register into memory doesn't alter the cc's.
2104 It may invalidate the RTX's which we remember the cc's came from. */
2105 if (GET_CODE (SET_DEST (exp)) == MEM && REG_P (SET_SRC (exp)))
2107 return;
2111 CC_STATUS_INIT;
2112 return;
2115 static enum machine_mode
2116 cr16_unwind_word_mode (void)
2118 return SImode;
2121 /* Helper function for md file. This function is used to emit arithmetic
2122 DI instructions. The argument "num" decides which instruction to be
2123 printed. */
2124 const char *
2125 cr16_emit_add_sub_di (rtx *operands, enum rtx_code code)
2127 rtx lo_op[2] ;
2128 rtx hi0_op[2] ;
2129 rtx hi1_op[2] ;
2131 lo_op[0] = gen_lowpart (SImode, operands[0]);
2132 hi0_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 4);
2133 hi1_op[0] = simplify_gen_subreg (HImode, operands[0], DImode, 6);
2135 lo_op[1] = gen_lowpart (SImode, operands[2]);
2136 hi0_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 4);
2137 hi1_op[1] = simplify_gen_subreg (HImode, operands[2], DImode, 6);
2139 switch (code)
2141 case PLUS:
2143 output_asm_insn ("addd\t%1, %0", lo_op) ;
2144 output_asm_insn ("addcw\t%1, %0", hi0_op) ;
2145 output_asm_insn ("addcw\t%1, %0", hi1_op) ;
2146 break;
2148 case MINUS:
2150 output_asm_insn ("subd\t%1, %0", lo_op) ;
2151 output_asm_insn ("subcw\t%1, %0", hi0_op) ;
2152 output_asm_insn ("subcw\t%1, %0", hi1_op) ;
2153 break;
2155 default:
2156 break;
2159 return "";
2163 /* Helper function for md file. This function is used to emit logical
2164 DI instructions. The argument "num" decides which instruction to be
2165 printed. */
2166 const char *
2167 cr16_emit_logical_di (rtx *operands, enum rtx_code code)
2169 rtx lo_op[2] ;
2170 rtx hi_op[2] ;
2172 lo_op[0] = gen_lowpart (SImode, operands[0]);
2173 hi_op[0] = simplify_gen_subreg (SImode, operands[0], DImode, 4);
2175 lo_op[1] = gen_lowpart (SImode, operands[2]);
2176 hi_op[1] = simplify_gen_subreg (SImode, operands[2], DImode, 4);
2178 switch (code)
2180 case AND:
2182 output_asm_insn ("andd\t%1, %0", lo_op) ;
2183 output_asm_insn ("andd\t%1, %0", hi_op) ;
2184 return "";
2186 case IOR:
2188 output_asm_insn ("ord\t%1, %0", lo_op) ;
2189 output_asm_insn ("ord\t%1, %0", hi_op) ;
2190 return "";
2192 case XOR:
2194 output_asm_insn ("xord\t%1, %0", lo_op) ;
2195 output_asm_insn ("xord\t%1, %0", hi_op) ;
2196 return "";
2198 default:
2199 break;
2202 return "";
2205 /* Initialize 'targetm' variable which contains pointers to functions
2206 and data relating to the target machine. */
2208 struct gcc_target targetm = TARGET_INITIALIZER;