1 /* Target definitions for the MorphoRISC1
2 Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
3 Contributed by Red Hat, Inc.
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/>. */
23 #include "coretypes.h"
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-attr.h"
35 #include "integrate.h"
44 #include "insn-flags.h"
48 #include "target-def.h"
49 #include "basic-block.h"
51 /* Frame pointer register mask. */
52 #define FP_MASK (1 << (GPR_FP))
54 /* Link register mask. */
55 #define LINK_MASK (1 << (GPR_LINK))
57 /* Given a SIZE in bytes, advance to the next word. */
58 #define ROUND_ADVANCE(SIZE) (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
60 /* A C structure for machine-specific, per-function data.
61 This is added to the cfun structure. */
62 struct machine_function GTY(())
64 /* Flags if __builtin_return_address (n) with n >= 1 was used. */
65 int ra_needs_full_frame;
66 struct rtx_def * eh_stack_adjust;
67 int interrupt_handler;
71 /* Define the information needed to generate branch and scc insns.
72 This is stored from the compare operation. */
73 struct rtx_def * mt_compare_op0;
74 struct rtx_def * mt_compare_op1;
76 /* Current frame information calculated by compute_frame_size. */
77 struct mt_frame_info current_frame_info;
79 /* Zero structure to initialize current_frame_info. */
80 struct mt_frame_info zero_frame_info;
82 /* mt doesn't have unsigned compares need a library call for this. */
83 struct rtx_def * mt_ucmpsi3_libcall;
85 static int mt_flag_delayed_branch;
89 mt_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
90 int incoming ATTRIBUTE_UNUSED)
92 return gen_rtx_REG (Pmode, RETVAL_REGNUM);
95 /* Implement RETURN_ADDR_RTX. */
97 mt_return_addr_rtx (int count)
102 return get_hard_reg_initial_val (Pmode, GPR_LINK);
105 /* The following variable value indicates the number of nops required
106 between the current instruction and the next instruction to avoid
107 any pipeline hazards. */
108 static int mt_nops_required = 0;
109 static const char * mt_nop_reasons = "";
111 /* Implement ASM_OUTPUT_OPCODE. */
113 mt_asm_output_opcode (FILE *f ATTRIBUTE_UNUSED, const char *ptr)
115 if (mt_nops_required)
116 fprintf (f, ";# need %d nops because of %s\n\t",
117 mt_nops_required, mt_nop_reasons);
119 while (mt_nops_required)
121 fprintf (f, "nop\n\t");
128 /* Given an insn, return whether it's a memory operation or a branch
129 operation, otherwise return TYPE_ARITH. */
130 static enum attr_type
131 mt_get_attr_type (rtx complete_insn)
133 rtx insn = PATTERN (complete_insn);
135 if (JUMP_P (complete_insn))
137 if (CALL_P (complete_insn))
140 if (GET_CODE (insn) != SET)
143 if (SET_DEST (insn) == pc_rtx)
146 if (GET_CODE (SET_DEST (insn)) == MEM)
149 if (GET_CODE (SET_SRC (insn)) == MEM)
155 /* A helper routine for insn_dependent_p called through note_stores. */
158 insn_dependent_p_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
160 rtx * pinsn = (rtx *) data;
162 if (*pinsn && reg_mentioned_p (x, *pinsn))
166 /* Return true if anything in insn X is (anti,output,true)
167 dependent on anything in insn Y. */
170 insn_dependent_p (rtx x, rtx y)
174 if (! INSN_P (x) || ! INSN_P (y))
178 note_stores (PATTERN (x), insn_dependent_p_1, &tmp);
183 note_stores (PATTERN (y), insn_dependent_p_1, &tmp);
184 return (tmp == NULL_RTX);
188 /* Return true if anything in insn X is true dependent on anything in
191 insn_true_dependent_p (rtx x, rtx y)
195 if (! INSN_P (x) || ! INSN_P (y))
199 note_stores (PATTERN (x), insn_dependent_p_1, &tmp);
200 return (tmp == NULL_RTX);
203 /* The following determines the number of nops that need to be
204 inserted between the previous instructions and current instruction
205 to avoid pipeline hazards on the mt processor. Remember that
206 the function is not called for asm insns. */
209 mt_final_prescan_insn (rtx insn,
210 rtx * opvec ATTRIBUTE_UNUSED,
211 int noperands ATTRIBUTE_UNUSED)
214 enum attr_type prev_attr;
216 mt_nops_required = 0;
219 /* ms2 constraints are dealt with in reorg. */
223 /* Only worry about real instructions. */
227 /* Find the previous real instructions. */
228 for (prev_i = PREV_INSN (insn);
230 && (! INSN_P (prev_i)
231 || GET_CODE (PATTERN (prev_i)) == USE
232 || GET_CODE (PATTERN (prev_i)) == CLOBBER);
233 prev_i = PREV_INSN (prev_i))
235 /* If we meet a barrier, there is no flow through here. */
236 if (BARRIER_P (prev_i))
240 /* If there isn't one then there is nothing that we need do. */
241 if (prev_i == NULL || ! INSN_P (prev_i))
244 prev_attr = mt_get_attr_type (prev_i);
246 /* Delayed branch slots already taken care of by delay branch scheduling. */
247 if (prev_attr == TYPE_BRANCH)
250 switch (mt_get_attr_type (insn))
254 /* Avoid consecutive memory operation. */
255 if ((prev_attr == TYPE_LOAD || prev_attr == TYPE_STORE)
256 && TARGET_MS1_64_001)
258 mt_nops_required = 1;
259 mt_nop_reasons = "consecutive mem ops";
265 /* One cycle of delay is required between load
266 and the dependent arithmetic instruction. */
267 if (prev_attr == TYPE_LOAD
268 && insn_true_dependent_p (prev_i, insn))
270 mt_nops_required = 1;
271 mt_nop_reasons = "load->arith dependency delay";
276 if (insn_dependent_p (prev_i, insn))
278 if (prev_attr == TYPE_ARITH && TARGET_MS1_64_001)
280 /* One cycle of delay between arith
281 instructions and branch dependent on arith. */
282 mt_nops_required = 1;
283 mt_nop_reasons = "arith->branch dependency delay";
285 else if (prev_attr == TYPE_LOAD)
287 /* Two cycles of delay are required
288 between load and dependent branch. */
289 if (TARGET_MS1_64_001)
290 mt_nops_required = 2;
292 mt_nops_required = 1;
293 mt_nop_reasons = "load->branch dependency delay";
299 fatal_insn ("mt_final_prescan_insn, invalid insn #1", insn);
304 /* Print debugging information for a frame. */
306 mt_debug_stack (struct mt_frame_info * info)
312 error ("info pointer NULL");
316 fprintf (stderr, "\nStack information for function %s:\n",
317 ((current_function_decl && DECL_NAME (current_function_decl))
318 ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))
321 fprintf (stderr, "\ttotal_size = %d\n", info->total_size);
322 fprintf (stderr, "\tpretend_size = %d\n", info->pretend_size);
323 fprintf (stderr, "\targs_size = %d\n", info->args_size);
324 fprintf (stderr, "\textra_size = %d\n", info->extra_size);
325 fprintf (stderr, "\treg_size = %d\n", info->reg_size);
326 fprintf (stderr, "\tvar_size = %d\n", info->var_size);
327 fprintf (stderr, "\tframe_size = %d\n", info->frame_size);
328 fprintf (stderr, "\treg_mask = 0x%x\n", info->reg_mask);
329 fprintf (stderr, "\tsave_fp = %d\n", info->save_fp);
330 fprintf (stderr, "\tsave_lr = %d\n", info->save_lr);
331 fprintf (stderr, "\tinitialized = %d\n", info->initialized);
332 fprintf (stderr, "\tsaved registers =");
334 /* Print out reg_mask in a more readable format. */
335 for (regno = GPR_R0; regno <= GPR_LAST; regno++)
336 if ( (1 << regno) & info->reg_mask)
337 fprintf (stderr, " %s", reg_names[regno]);
343 /* Print a memory address as an operand to reference that memory location. */
346 mt_print_operand_simple_address (FILE * file, rtx addr)
349 error ("PRINT_OPERAND_ADDRESS, null pointer");
352 switch (GET_CODE (addr))
355 fprintf (file, "%s, #0", reg_names[REGNO (addr)]);
362 rtx arg0 = XEXP (addr, 0);
363 rtx arg1 = XEXP (addr, 1);
365 if (GET_CODE (arg0) == REG)
369 if (GET_CODE (offset) == REG)
370 fatal_insn ("PRINT_OPERAND_ADDRESS, 2 regs", addr);
373 else if (GET_CODE (arg1) == REG)
374 reg = arg1, offset = arg0;
375 else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
377 fprintf (file, "%s, #", reg_names[GPR_R0]);
378 output_addr_const (file, addr);
381 fprintf (file, "%s, #", reg_names[REGNO (reg)]);
382 output_addr_const (file, offset);
390 output_addr_const (file, addr);
394 fatal_insn ("PRINT_OPERAND_ADDRESS, invalid insn #1", addr);
399 /* Implement PRINT_OPERAND_ADDRESS. */
401 mt_print_operand_address (FILE * file, rtx addr)
403 if (GET_CODE (addr) == AND
404 && GET_CODE (XEXP (addr, 1)) == CONST_INT
405 && INTVAL (XEXP (addr, 1)) == -3)
406 mt_print_operand_simple_address (file, XEXP (addr, 0));
408 mt_print_operand_simple_address (file, addr);
411 /* Implement PRINT_OPERAND. */
413 mt_print_operand (FILE * file, rtx x, int code)
418 /* Output a nop if there's nothing for the delay slot. */
419 if (dbr_sequence_length () == 0)
420 fputs ("\n\tnop", file);
424 fprintf(file, "#%%hi16(");
425 output_addr_const (file, x);
430 fprintf(file, "#%%lo16(");
431 output_addr_const (file, x);
436 fprintf(file, "#%ld", ~INTVAL (x));
440 if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0)
442 fputs (reg_names[GPR_R0], file);
451 /* output_operand_lossage ("mt_print_operand: unknown code"); */
452 fprintf (file, "unknown code");
456 switch (GET_CODE (x))
459 fputs (reg_names[REGNO (x)], file);
464 fprintf(file, "#%ld", INTVAL (x));
468 mt_print_operand_address(file, XEXP (x,0));
473 output_addr_const (file, x);
477 fprintf(file, "Uknown code: %d", GET_CODE (x));
484 /* Implement INIT_CUMULATIVE_ARGS. */
486 mt_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype, rtx libname,
487 tree fndecl ATTRIBUTE_UNUSED, int incoming)
491 if (TARGET_DEBUG_ARG)
493 fprintf (stderr, "\nmt_init_cumulative_args:");
496 fputs (" incoming", stderr);
500 tree ret_type = TREE_TYPE (fntype);
501 fprintf (stderr, " return = %s,",
502 tree_code_name[ (int)TREE_CODE (ret_type) ]);
505 if (libname && GET_CODE (libname) == SYMBOL_REF)
506 fprintf (stderr, " libname = %s", XSTR (libname, 0));
508 if (cfun->returns_struct)
509 fprintf (stderr, " return-struct");
515 /* Compute the slot number to pass an argument in.
516 Returns the slot number or -1 if passing on the stack.
518 CUM is a variable of type CUMULATIVE_ARGS which gives info about
519 the preceding args and about the function being called.
520 MODE is the argument's machine mode.
521 TYPE is the data type of the argument (as a tree).
522 This is null for libcalls where that information may
524 NAMED is nonzero if this argument is a named parameter
525 (otherwise it is an extra parameter matching an ellipsis).
526 INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG.
527 *PREGNO records the register number to use if scalar type. */
530 mt_function_arg_slotno (const CUMULATIVE_ARGS * cum,
531 enum machine_mode mode,
533 int named ATTRIBUTE_UNUSED,
534 int incoming_p ATTRIBUTE_UNUSED,
537 int regbase = FIRST_ARG_REGNUM;
540 if (mode == VOIDmode || targetm.calls.must_pass_in_stack (mode, type))
543 if (slotno >= MT_NUM_ARG_REGS)
546 * pregno = regbase + slotno;
551 /* Implement FUNCTION_ARG. */
553 mt_function_arg (const CUMULATIVE_ARGS * cum,
554 enum machine_mode mode,
562 slotno = mt_function_arg_slotno (cum, mode, type, named, incoming_p, ®no);
567 reg = gen_rtx_REG (mode, regno);
572 /* Implement FUNCTION_ARG_ADVANCE. */
574 mt_function_arg_advance (CUMULATIVE_ARGS * cum,
575 enum machine_mode mode,
576 tree type ATTRIBUTE_UNUSED,
581 /* We pass 0 for incoming_p here, it doesn't matter. */
582 slotno = mt_function_arg_slotno (cum, mode, type, named, 0, ®no);
584 * cum += (mode != BLKmode
585 ? ROUND_ADVANCE (GET_MODE_SIZE (mode))
586 : ROUND_ADVANCE (int_size_in_bytes (type)));
588 if (TARGET_DEBUG_ARG)
590 "mt_function_arg_advance: words = %2d, mode = %4s, named = %d, size = %3d\n",
591 *cum, GET_MODE_NAME (mode), named,
592 (*cum) * UNITS_PER_WORD);
595 /* Implement hook TARGET_ARG_PARTIAL_BYTES.
597 Returns the number of bytes at the beginning of an argument that
598 must be put in registers. The value must be zero for arguments
599 that are passed entirely in registers or that are entirely pushed
602 mt_arg_partial_bytes (CUMULATIVE_ARGS * pcum,
603 enum machine_mode mode,
605 bool named ATTRIBUTE_UNUSED)
611 words = ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
614 words = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
616 if (! targetm.calls.pass_by_reference (&cum, mode, type, named)
617 && cum < MT_NUM_ARG_REGS
618 && (cum + words) > MT_NUM_ARG_REGS)
620 int bytes = (MT_NUM_ARG_REGS - cum) * UNITS_PER_WORD;
623 fprintf (stderr, "function_arg_partial_nregs = %d\n", bytes);
631 /* Implement TARGET_PASS_BY_REFERENCE hook. */
633 mt_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
634 enum machine_mode mode ATTRIBUTE_UNUSED,
636 bool named ATTRIBUTE_UNUSED)
638 return (type && int_size_in_bytes (type) > 4 * UNITS_PER_WORD);
641 /* Implement FUNCTION_ARG_BOUNDARY. */
643 mt_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
644 tree type ATTRIBUTE_UNUSED)
646 return BITS_PER_WORD;
649 /* Implement REG_OK_FOR_BASE_P. */
651 mt_reg_ok_for_base_p (rtx x, int strict)
654 return (((unsigned) REGNO (x)) < FIRST_PSEUDO_REGISTER);
658 /* Helper function of mt_legitimate_address_p. Return true if XINSN
659 is a simple address, otherwise false. */
661 mt_legitimate_simple_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
662 rtx xinsn, int strict)
666 fprintf (stderr, "\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
667 strict ? "" : "not ");
671 if (GET_CODE (xinsn) == REG && mt_reg_ok_for_base_p (xinsn, strict))
674 if (GET_CODE (xinsn) == PLUS
675 && GET_CODE (XEXP (xinsn, 0)) == REG
676 && mt_reg_ok_for_base_p (XEXP (xinsn, 0), strict)
677 && GET_CODE (XEXP (xinsn, 1)) == CONST_INT
678 && SMALL_INT (XEXP (xinsn, 1)))
685 /* Helper function of GO_IF_LEGITIMATE_ADDRESS. Return nonzero if
686 XINSN is a legitimate address on MT. */
688 mt_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict)
690 if (mt_legitimate_simple_address_p (mode, xinsn, strict))
694 && GET_CODE (xinsn) == AND
695 && GET_CODE (XEXP (xinsn, 1)) == CONST_INT
696 && INTVAL (XEXP (xinsn, 1)) == -3)
697 return mt_legitimate_simple_address_p (mode, XEXP (xinsn, 0), strict);
702 /* Return truth value of whether OP can be used as an operands where a
703 register or 16-bit unsigned integer is needed. */
706 uns_arith_operand (rtx op, enum machine_mode mode)
708 if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op))
711 return register_operand (op, mode);
714 /* Return truth value of whether OP can be used as an operands where a
715 16-bit integer is needed. */
718 arith_operand (rtx op, enum machine_mode mode)
720 if (GET_CODE (op) == CONST_INT && SMALL_INT (op))
723 return register_operand (op, mode);
726 /* Return truth value of whether OP is a register or the constant 0. */
729 reg_or_0_operand (rtx op, enum machine_mode mode)
731 switch (GET_CODE (op))
734 return INTVAL (op) == 0;
738 return register_operand (op, mode);
747 /* Return truth value of whether OP is a constant that requires two
748 loads to put in a register. */
751 big_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
753 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_LETTER_P (INTVAL (op), 'M'))
759 /* Return truth value of whether OP is a constant that require only
760 one load to put in a register. */
763 single_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
765 if (big_const_operand (op, mode)
766 || GET_CODE (op) == CONST
767 || GET_CODE (op) == LABEL_REF
768 || GET_CODE (op) == SYMBOL_REF)
774 /* True if the current function is an interrupt handler
775 (either via #pragma or an attribute specification). */
776 int interrupt_handler;
777 enum processor_type mt_cpu;
779 static struct machine_function *
780 mt_init_machine_status (void)
782 struct machine_function *f;
784 f = ggc_alloc_cleared (sizeof (struct machine_function));
789 /* Implement OVERRIDE_OPTIONS. */
791 mt_override_options (void)
793 if (mt_cpu_string != NULL)
795 if (!strcmp (mt_cpu_string, "ms1-64-001"))
796 mt_cpu = PROCESSOR_MS1_64_001;
797 else if (!strcmp (mt_cpu_string, "ms1-16-002"))
798 mt_cpu = PROCESSOR_MS1_16_002;
799 else if (!strcmp (mt_cpu_string, "ms1-16-003"))
800 mt_cpu = PROCESSOR_MS1_16_003;
801 else if (!strcmp (mt_cpu_string, "ms2"))
802 mt_cpu = PROCESSOR_MS2;
804 error ("bad value (%s) for -march= switch", mt_cpu_string);
807 mt_cpu = PROCESSOR_MS1_16_002;
811 flag_omit_frame_pointer = 0;
815 /* We do delayed branch filling in machine dependent reorg */
816 mt_flag_delayed_branch = flag_delayed_branch;
817 flag_delayed_branch = 0;
819 init_machine_status = mt_init_machine_status;
822 /* Do what is necessary for `va_start'. We look at the current function
823 to determine if stdarg or varargs is used and return the address of the
824 first unnamed parameter. */
827 mt_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
828 enum machine_mode mode ATTRIBUTE_UNUSED,
829 tree type ATTRIBUTE_UNUSED,
830 int *pretend_size, int no_rtl)
833 int regs = MT_NUM_ARG_REGS - *cum;
835 *pretend_size = regs < 0 ? 0 : GET_MODE_SIZE (SImode) * regs;
840 for (regno = *cum; regno < MT_NUM_ARG_REGS; regno++)
842 rtx reg = gen_rtx_REG (SImode, FIRST_ARG_REGNUM + regno);
843 rtx slot = gen_rtx_PLUS (Pmode,
844 gen_rtx_REG (SImode, ARG_POINTER_REGNUM),
845 GEN_INT (UNITS_PER_WORD * regno));
847 emit_move_insn (gen_rtx_MEM (SImode, slot), reg);
851 /* Returns the number of bytes offset between the frame pointer and the stack
852 pointer for the current function. SIZE is the number of bytes of space
853 needed for local variables. */
856 mt_compute_frame_size (int size)
859 unsigned int total_size;
860 unsigned int var_size;
861 unsigned int args_size;
862 unsigned int pretend_size;
863 unsigned int extra_size;
864 unsigned int reg_size;
865 unsigned int frame_size;
866 unsigned int reg_mask;
869 args_size = crtl->outgoing_args_size;
870 pretend_size = crtl->args.pretend_args_size;
871 extra_size = FIRST_PARM_OFFSET (0);
872 total_size = extra_size + pretend_size + args_size + var_size;
876 /* Calculate space needed for registers. */
877 for (regno = GPR_R0; regno <= GPR_LAST; regno++)
879 if (MUST_SAVE_REGISTER (regno))
881 reg_size += UNITS_PER_WORD;
882 reg_mask |= 1 << regno;
886 current_frame_info.save_fp = (df_regs_ever_live_p (GPR_FP)
887 || frame_pointer_needed
888 || interrupt_handler);
889 current_frame_info.save_lr = (df_regs_ever_live_p (GPR_LINK)
891 || interrupt_handler);
893 reg_size += (current_frame_info.save_fp + current_frame_info.save_lr)
895 total_size += reg_size;
896 total_size = ((total_size + 3) & ~3);
898 frame_size = total_size;
900 /* Save computed information. */
901 current_frame_info.pretend_size = pretend_size;
902 current_frame_info.var_size = var_size;
903 current_frame_info.args_size = args_size;
904 current_frame_info.reg_size = reg_size;
905 current_frame_info.frame_size = args_size + var_size;
906 current_frame_info.total_size = total_size;
907 current_frame_info.extra_size = extra_size;
908 current_frame_info.reg_mask = reg_mask;
909 current_frame_info.initialized = reload_completed;
914 /* Emit code to save REG in stack offset pointed to by MEM.
915 STACK_OFFSET is the offset from the SP where the save will happen.
916 This function sets the REG_FRAME_RELATED_EXPR note accordingly. */
918 mt_emit_save_restore (enum save_direction direction,
919 rtx reg, rtx mem, int stack_offset)
921 if (direction == FROM_PROCESSOR_TO_MEM)
925 insn = emit_move_insn (mem, reg);
926 RTX_FRAME_RELATED_P (insn) = 1;
929 (REG_FRAME_RELATED_EXPR,
930 gen_rtx_SET (VOIDmode,
932 gen_rtx_PLUS (SImode,
934 GEN_INT (stack_offset))),
939 emit_move_insn (reg, mem);
943 /* Emit code to save the frame pointer in the prologue and restore
944 frame pointer in epilogue. */
947 mt_emit_save_fp (enum save_direction direction,
948 struct mt_frame_info info)
951 int reg_mask = info.reg_mask & ~(FP_MASK | LINK_MASK);
952 int offset = info.total_size;
953 int stack_offset = info.total_size;
955 /* If there is nothing to save, get out now. */
956 if (! info.save_fp && ! info.save_lr && ! reg_mask)
959 /* If offset doesn't fit in a 15-bit signed integer,
960 uses a scratch registers to get a smaller offset. */
961 if (CONST_OK_FOR_LETTER_P(offset, 'O'))
962 base_reg = stack_pointer_rtx;
965 /* Use the scratch register R9 that holds old stack pointer. */
966 base_reg = gen_rtx_REG (SImode, GPR_R9);
972 offset -= UNITS_PER_WORD;
973 stack_offset -= UNITS_PER_WORD;
975 (direction, gen_rtx_REG (SImode, GPR_FP),
977 gen_rtx_PLUS (SImode, base_reg, GEN_INT (offset))),
982 /* Emit code to save registers in the prologue and restore register
986 mt_emit_save_regs (enum save_direction direction,
987 struct mt_frame_info info)
991 int reg_mask = info.reg_mask & ~(FP_MASK | LINK_MASK);
992 int offset = info.total_size;
993 int stack_offset = info.total_size;
995 /* If there is nothing to save, get out now. */
996 if (! info.save_fp && ! info.save_lr && ! reg_mask)
999 /* If offset doesn't fit in a 15-bit signed integer,
1000 uses a scratch registers to get a smaller offset. */
1001 if (CONST_OK_FOR_LETTER_P(offset, 'O'))
1002 base_reg = stack_pointer_rtx;
1005 /* Use the scratch register R9 that holds old stack pointer. */
1006 base_reg = gen_rtx_REG (SImode, GPR_R9);
1012 /* This just records the space for it, the actual move generated in
1013 mt_emit_save_fp (). */
1014 offset -= UNITS_PER_WORD;
1015 stack_offset -= UNITS_PER_WORD;
1020 offset -= UNITS_PER_WORD;
1021 stack_offset -= UNITS_PER_WORD;
1022 mt_emit_save_restore
1023 (direction, gen_rtx_REG (SImode, GPR_LINK),
1024 gen_rtx_MEM (SImode,
1025 gen_rtx_PLUS (SImode, base_reg, GEN_INT (offset))),
1029 /* Save any needed call-saved regs. */
1030 for (regno = GPR_R0; regno <= GPR_LAST; regno++)
1032 if ((reg_mask & (1 << regno)) != 0)
1034 offset -= UNITS_PER_WORD;
1035 stack_offset -= UNITS_PER_WORD;
1036 mt_emit_save_restore
1037 (direction, gen_rtx_REG (SImode, regno),
1038 gen_rtx_MEM (SImode,
1039 gen_rtx_PLUS (SImode, base_reg, GEN_INT (offset))),
1045 /* Return true if FUNC is a function with the 'interrupt' attribute. */
1047 mt_interrupt_function_p (tree func)
1051 if (TREE_CODE (func) != FUNCTION_DECL)
1054 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
1055 return a != NULL_TREE;
1058 /* Generate prologue code. */
1060 mt_expand_prologue (void)
1063 unsigned int frame_size;
1065 if (mt_interrupt_function_p (current_function_decl))
1067 interrupt_handler = 1;
1069 cfun->machine->interrupt_handler = 1;
1072 mt_compute_frame_size (get_frame_size ());
1074 if (TARGET_DEBUG_STACK)
1075 mt_debug_stack (¤t_frame_info);
1077 /* Compute size of stack adjustment. */
1078 frame_size = current_frame_info.total_size;
1080 /* If offset doesn't fit in a 15-bit signed integer,
1081 uses a scratch registers to get a smaller offset. */
1082 if (CONST_OK_FOR_LETTER_P(frame_size, 'O'))
1083 size_rtx = GEN_INT (frame_size);
1086 /* We do not have any scratch registers. */
1087 gcc_assert (!interrupt_handler);
1089 size_rtx = gen_rtx_REG (SImode, GPR_R9);
1090 insn = emit_move_insn (size_rtx, GEN_INT (frame_size & 0xffff0000));
1091 insn = emit_insn (gen_iorsi3 (size_rtx, size_rtx,
1092 GEN_INT (frame_size & 0x0000ffff)));
1095 /* Allocate stack for this frame. */
1096 /* Make stack adjustment and use scratch register if constant too
1097 large to fit as immediate. */
1100 insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
1103 RTX_FRAME_RELATED_P (insn) = 1;
1105 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1106 gen_rtx_SET (VOIDmode,
1108 gen_rtx_MINUS (SImode,
1110 GEN_INT (frame_size))),
1114 /* Set R9 to point to old sp if required for access to register save
1116 if ( current_frame_info.reg_size != 0
1117 && !CONST_OK_FOR_LETTER_P (frame_size, 'O'))
1118 emit_insn (gen_addsi3 (size_rtx, size_rtx, stack_pointer_rtx));
1120 /* Save the frame pointer. */
1121 mt_emit_save_fp (FROM_PROCESSOR_TO_MEM, current_frame_info);
1123 /* Now put the frame pointer into the frame pointer register. */
1124 if (frame_pointer_needed)
1126 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1127 RTX_FRAME_RELATED_P (insn) = 1;
1130 /* Save the registers. */
1131 mt_emit_save_regs (FROM_PROCESSOR_TO_MEM, current_frame_info);
1133 /* If we are profiling, make sure no instructions are scheduled before
1134 the call to mcount. */
1136 emit_insn (gen_blockage ());
1139 /* Implement EPILOGUE_USES. */
1141 mt_epilogue_uses (int regno)
1143 if (cfun->machine && cfun->machine->interrupt_handler && reload_completed)
1145 return regno == GPR_LINK;
1148 /* Generate epilogue. EH_MODE is NORMAL_EPILOGUE when generating a
1149 function epilogue, or EH_EPILOGUE when generating an EH
1152 mt_expand_epilogue (enum epilogue_type eh_mode)
1155 unsigned frame_size;
1157 mt_compute_frame_size (get_frame_size ());
1159 if (TARGET_DEBUG_STACK)
1160 mt_debug_stack (& current_frame_info);
1162 /* Compute size of stack adjustment. */
1163 frame_size = current_frame_info.total_size;
1165 /* If offset doesn't fit in a 15-bit signed integer,
1166 uses a scratch registers to get a smaller offset. */
1167 if (CONST_OK_FOR_LETTER_P(frame_size, 'O'))
1168 size_rtx = GEN_INT (frame_size);
1171 /* We do not have any scratch registers. */
1172 gcc_assert (!interrupt_handler);
1174 size_rtx = gen_rtx_REG (SImode, GPR_R9);
1175 insn = emit_move_insn (size_rtx, GEN_INT (frame_size & 0xffff0000));
1176 insn = emit_insn (gen_iorsi3 (size_rtx, size_rtx,
1177 GEN_INT (frame_size & 0x0000ffff)));
1178 /* Set R9 to point to old sp if required for access to register
1180 emit_insn (gen_addsi3 (size_rtx, size_rtx, stack_pointer_rtx));
1183 /* Restore sp if there was some possible change to it. */
1184 if (frame_pointer_needed)
1185 insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
1187 /* Restore the registers. */
1188 mt_emit_save_fp (FROM_MEM_TO_PROCESSOR, current_frame_info);
1189 mt_emit_save_regs (FROM_MEM_TO_PROCESSOR, current_frame_info);
1191 /* Make stack adjustment and use scratch register if constant too
1192 large to fit as immediate. */
1195 if (CONST_OK_FOR_LETTER_P(frame_size, 'O'))
1196 /* Can handle this with simple add. */
1197 insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
1201 /* Scratch reg R9 has the old sp value. */
1202 insn = emit_move_insn (stack_pointer_rtx,
1203 gen_rtx_REG (SImode, GPR_R9));
1206 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1207 gen_rtx_SET (VOIDmode,
1209 gen_rtx_PLUS (SImode,
1211 GEN_INT (frame_size))),
1215 if (cfun->machine && cfun->machine->eh_stack_adjust != NULL_RTX)
1216 /* Perform the additional bump for __throw. */
1217 emit_insn (gen_addsi3 (stack_pointer_rtx,
1219 cfun->machine->eh_stack_adjust));
1221 /* Generate the appropriate return. */
1222 if (eh_mode == EH_EPILOGUE)
1224 emit_jump_insn (gen_eh_return_internal ());
1227 else if (interrupt_handler)
1228 emit_jump_insn (gen_return_interrupt_internal ());
1230 emit_jump_insn (gen_return_internal ());
1232 /* Reset state info for each function. */
1233 interrupt_handler = 0;
1234 current_frame_info = zero_frame_info;
1236 cfun->machine->eh_stack_adjust = NULL_RTX;
1240 /* Generate code for the "eh_return" pattern. */
1242 mt_expand_eh_return (rtx * operands)
1244 if (GET_CODE (operands[0]) != REG
1245 || REGNO (operands[0]) != EH_RETURN_STACKADJ_REGNO)
1247 rtx sp = EH_RETURN_STACKADJ_RTX;
1249 emit_move_insn (sp, operands[0]);
1253 emit_insn (gen_eh_epilogue (operands[0]));
1256 /* Generate code for the "eh_epilogue" pattern. */
1258 mt_emit_eh_epilogue (rtx * operands ATTRIBUTE_UNUSED)
1260 cfun->machine->eh_stack_adjust = EH_RETURN_STACKADJ_RTX; /* operands[0]; */
1261 mt_expand_epilogue (EH_EPILOGUE);
1264 /* Handle an "interrupt" attribute. */
1266 mt_handle_interrupt_attribute (tree * node,
1268 tree args ATTRIBUTE_UNUSED,
1269 int flags ATTRIBUTE_UNUSED,
1270 bool * no_add_attrs)
1272 if (TREE_CODE (*node) != FUNCTION_DECL)
1274 warning (OPT_Wattributes,
1275 "%qs attribute only applies to functions",
1276 IDENTIFIER_POINTER (name));
1277 *no_add_attrs = true;
1283 /* Table of machine attributes. */
1284 const struct attribute_spec mt_attribute_table[] =
1286 /* name, min, max, decl?, type?, func?, handler */
1287 { "interrupt", 0, 0, false, false, false, mt_handle_interrupt_attribute },
1288 { NULL, 0, 0, false, false, false, NULL }
1291 /* Implement INITIAL_ELIMINATION_OFFSET. */
1293 mt_initial_elimination_offset (int from, int to)
1295 mt_compute_frame_size (get_frame_size ());
1297 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1300 else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1301 return current_frame_info.total_size;
1303 else if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
1304 return current_frame_info.total_size;
1310 /* Generate a compare for CODE. Return a brand-new rtx that
1311 represents the result of the compare. */
1314 mt_generate_compare (enum rtx_code code, rtx op0, rtx op1)
1316 rtx scratch0, scratch1, const_scratch;
1324 /* Need to adjust ranges for faking unsigned compares. */
1325 scratch0 = gen_reg_rtx (SImode);
1326 scratch1 = gen_reg_rtx (SImode);
1327 const_scratch = force_reg (SImode, GEN_INT(MT_MIN_INT));
1328 emit_insn (gen_addsi3 (scratch0, const_scratch, op0));
1329 emit_insn (gen_addsi3 (scratch1, const_scratch, op1));
1337 /* Adjust compare operator to fake unsigned compares. */
1353 /* Generate the actual compare. */
1354 return gen_rtx_fmt_ee (code, VOIDmode, scratch0, scratch1);
1357 /* Emit a branch of kind CODE to location LOC. */
1360 mt_emit_cbranch (enum rtx_code code, rtx loc, rtx op0, rtx op1)
1362 rtx condition_rtx, loc_ref;
1364 if (! reg_or_0_operand (op0, SImode))
1365 op0 = copy_to_mode_reg (SImode, op0);
1367 if (! reg_or_0_operand (op1, SImode))
1368 op1 = copy_to_mode_reg (SImode, op1);
1370 condition_rtx = mt_generate_compare (code, op0, op1);
1371 loc_ref = gen_rtx_LABEL_REF (VOIDmode, loc);
1372 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
1373 gen_rtx_IF_THEN_ELSE (VOIDmode, condition_rtx,
1377 /* Subfunction of the following function. Update the flags of any MEM
1378 found in part of X. */
1381 mt_set_memflags_1 (rtx x, int in_struct_p, int volatile_p)
1385 switch (GET_CODE (x))
1389 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
1390 mt_set_memflags_1 (XVECEXP (x, 0, i), in_struct_p, volatile_p);
1394 mt_set_memflags_1 (PATTERN (x), in_struct_p, volatile_p);
1398 mt_set_memflags_1 (SET_DEST (x), in_struct_p, volatile_p);
1399 mt_set_memflags_1 (SET_SRC (x), in_struct_p, volatile_p);
1403 MEM_IN_STRUCT_P (x) = in_struct_p;
1404 MEM_VOLATILE_P (x) = volatile_p;
1405 /* Sadly, we cannot use alias sets because the extra aliasing
1406 produced by the AND interferes. Given that two-byte quantities
1407 are the only thing we would be able to differentiate anyway,
1408 there does not seem to be any point in convoluting the early
1409 out of the alias check. */
1410 /* set_mem_alias_set (x, alias_set); */
1418 /* Look for any MEMs in the current sequence of insns and set the
1419 in-struct, unchanging, and volatile flags from the flags in REF.
1420 If REF is not a MEM, don't do anything. */
1423 mt_set_memflags (rtx ref)
1426 int in_struct_p, volatile_p;
1428 if (GET_CODE (ref) != MEM)
1431 in_struct_p = MEM_IN_STRUCT_P (ref);
1432 volatile_p = MEM_VOLATILE_P (ref);
1434 /* This is only called from mt.md, after having had something
1435 generated from one of the insn patterns. So if everything is
1436 zero, the pattern is already up-to-date. */
1437 if (! in_struct_p && ! volatile_p)
1440 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
1441 mt_set_memflags_1 (insn, in_struct_p, volatile_p);
1444 /* Implement SECONDARY_RELOAD_CLASS. */
1446 mt_secondary_reload_class (enum reg_class class ATTRIBUTE_UNUSED,
1447 enum machine_mode mode,
1450 if ((mode == QImode && (!TARGET_BYTE_ACCESS)) || mode == HImode)
1452 if (GET_CODE (x) == MEM
1453 || (GET_CODE (x) == REG && true_regnum (x) == -1)
1454 || (GET_CODE (x) == SUBREG
1455 && (GET_CODE (SUBREG_REG (x)) == MEM
1456 || (GET_CODE (SUBREG_REG (x)) == REG
1457 && true_regnum (SUBREG_REG (x)) == -1))))
1458 return GENERAL_REGS;
1464 /* Handle FUNCTION_VALUE, FUNCTION_OUTGOING_VALUE, and LIBCALL_VALUE
1467 mt_function_value (const_tree valtype, enum machine_mode mode, const_tree func_decl ATTRIBUTE_UNUSED)
1469 if ((mode) == DImode || (mode) == DFmode)
1470 return gen_rtx_MEM (mode, gen_rtx_REG (mode, RETURN_VALUE_REGNUM));
1473 mode = TYPE_MODE (valtype);
1475 return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);
1478 /* Split a move into two smaller pieces.
1479 MODE indicates the reduced mode. OPERANDS[0] is the original destination
1480 OPERANDS[1] is the original src. The new destinations are
1481 OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3]
1485 mt_split_words (enum machine_mode nmode,
1486 enum machine_mode omode,
1489 rtx dl,dh; /* src/dest pieces. */
1491 int move_high_first = 0; /* Assume no overlap. */
1493 switch (GET_CODE (operands[0])) /* Dest. */
1497 if ((GET_CODE (operands[1]) == REG
1498 || GET_CODE (operands[1]) == SUBREG)
1499 && true_regnum (operands[0]) <= true_regnum (operands[1]))
1500 move_high_first = 1;
1502 if (GET_CODE (operands[0]) == SUBREG)
1504 dl = gen_rtx_SUBREG (nmode, SUBREG_REG (operands[0]),
1505 SUBREG_BYTE (operands[0]) + GET_MODE_SIZE (nmode));
1506 dh = gen_rtx_SUBREG (nmode, SUBREG_REG (operands[0]), SUBREG_BYTE (operands[0]));
1508 else if (GET_CODE (operands[0]) == REG && ! IS_PSEUDO_P (operands[0]))
1510 int r = REGNO (operands[0]);
1511 dh = gen_rtx_REG (nmode, r);
1512 dl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
1516 dh = gen_rtx_SUBREG (nmode, operands[0], 0);
1517 dl = gen_rtx_SUBREG (nmode, operands[0], GET_MODE_SIZE (nmode));
1522 switch (GET_CODE (XEXP (operands[0], 0)))
1528 dl = operand_subword (operands[0],
1529 GET_MODE_SIZE (nmode)/UNITS_PER_WORD,
1531 dh = operand_subword (operands[0], 0, 0, omode);
1538 switch (GET_CODE (operands[1]))
1541 if (! IS_PSEUDO_P (operands[1]))
1543 int r = REGNO (operands[1]);
1545 sh = gen_rtx_REG (nmode, r);
1546 sl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
1550 sh = gen_rtx_SUBREG (nmode, operands[1], 0);
1551 sl = gen_rtx_SUBREG (nmode, operands[1], GET_MODE_SIZE (nmode));
1556 if (operands[1] == const0_rtx)
1557 sh = sl = const0_rtx;
1559 split_double (operands[1], & sh, & sl);
1563 if (operands[1] == const0_rtx)
1564 sh = sl = const0_rtx;
1581 sl = gen_rtx_SUBREG (nmode,
1582 SUBREG_REG (operands[1]),
1583 SUBREG_BYTE (operands[1]) + GET_MODE_SIZE (nmode));
1584 sh = gen_rtx_SUBREG (nmode,
1585 SUBREG_REG (operands[1]),
1586 SUBREG_BYTE (operands[1]));
1590 switch (GET_CODE (XEXP (operands[1], 0)))
1597 sl = operand_subword (operands[1],
1598 GET_MODE_SIZE (nmode)/UNITS_PER_WORD,
1600 sh = operand_subword (operands[1], 0, 0, omode);
1602 /* Check if the DF load is going to clobber the register
1603 used for the address, and if so make sure that is going
1604 to be the second move. */
1605 if (GET_CODE (dl) == REG
1607 == true_regnum (XEXP (XEXP (sl, 0 ), 0)))
1608 move_high_first = 1;
1615 if (move_high_first)
1632 /* Implement TARGET_MUST_PASS_IN_STACK hook. */
1634 mt_pass_in_stack (enum machine_mode mode ATTRIBUTE_UNUSED, const_tree type)
1636 return (((type) != 0
1637 && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
1638 || TREE_ADDRESSABLE (type))));
1641 /* Increment the counter for the number of loop instructions in the
1642 current function. */
1644 void mt_add_loop (void)
1646 cfun->machine->has_loops++;
1650 /* Maximum loop nesting depth. */
1651 #define MAX_LOOP_DEPTH 4
1652 /* Maximum size of a loop (allows some headroom for delayed branch slot
1654 #define MAX_LOOP_LENGTH (200 * 4)
1656 /* We need to keep a vector of loops */
1657 typedef struct loop_info *loop_info;
1658 DEF_VEC_P (loop_info);
1659 DEF_VEC_ALLOC_P (loop_info,heap);
1661 /* Information about a loop we have found (or are in the process of
1663 struct loop_info GTY (())
1665 /* loop number, for dumps */
1668 /* Predecessor block of the loop. This is the one that falls into
1669 the loop and contains the initialization instruction. */
1670 basic_block predecessor;
1672 /* First block in the loop. This is the one branched to by the dbnz
1676 /* Last block in the loop (the one with the dbnz insn */
1679 /* The successor block of the loop. This is the one the dbnz insn
1681 basic_block successor;
1683 /* The dbnz insn. */
1686 /* The initialization insn. */
1689 /* The new initialization instruction. */
1692 /* The new ending instruction. */
1695 /* The new label placed at the end of the loop. */
1698 /* The nesting depth of the loop. Set to -1 for a bad loop. */
1701 /* The length of the loop. */
1704 /* Next loop in the graph. */
1705 struct loop_info *next;
1707 /* Vector of blocks only within the loop, (excluding those within
1709 VEC (basic_block,heap) *blocks;
1711 /* Vector of inner loops within this loop */
1712 VEC (loop_info,heap) *loops;
1715 /* Information used during loop detection. */
1716 typedef struct loop_work GTY(())
1718 /* Basic block to be scanned. */
1721 /* Loop it will be within. */
1726 DEF_VEC_O (loop_work);
1727 DEF_VEC_ALLOC_O (loop_work,heap);
1729 /* Determine the nesting and length of LOOP. Return false if the loop
1733 mt_loop_nesting (loop_info loop)
1737 int inner_depth = 0;
1741 /* Make sure we only have one entry point. */
1742 if (EDGE_COUNT (loop->head->preds) == 2)
1744 loop->predecessor = EDGE_PRED (loop->head, 0)->src;
1745 if (loop->predecessor == loop->tail)
1746 /* We wanted the other predecessor. */
1747 loop->predecessor = EDGE_PRED (loop->head, 1)->src;
1749 /* We can only place a loop insn on a fall through edge of a
1750 single exit block. */
1751 if (EDGE_COUNT (loop->predecessor->succs) != 1
1752 || !(EDGE_SUCC (loop->predecessor, 0)->flags & EDGE_FALLTHRU))
1753 loop->predecessor = NULL;
1756 /* Mark this loop as bad for now. */
1758 if (loop->predecessor)
1760 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix++, inner);)
1763 mt_loop_nesting (inner);
1765 if (inner->depth < 0)
1771 if (inner_depth < inner->depth)
1772 inner_depth = inner->depth;
1773 loop->length += inner->length;
1776 /* Set the proper loop depth, if it was good. */
1777 if (inner_depth >= 0)
1778 loop->depth = inner_depth + 1;
1781 return (loop->depth > 0
1782 && loop->predecessor
1783 && loop->depth < MAX_LOOP_DEPTH
1784 && loop->length < MAX_LOOP_LENGTH);
1787 /* Determine the length of block BB. */
1790 mt_block_length (basic_block bb)
1795 for (insn = BB_HEAD (bb);
1796 insn != NEXT_INSN (BB_END (bb));
1797 insn = NEXT_INSN (insn))
1803 /* Calls are not allowed in loops. */
1804 length = MAX_LOOP_LENGTH + 1;
1808 length += get_attr_length (insn);
1813 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
1814 REG. Return true, if we find any. Don't count the loop's dbnz
1815 insn if it matches DBNZ. */
1818 mt_scan_loop (loop_info loop, rtx reg, rtx dbnz)
1824 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
1828 for (insn = BB_HEAD (bb);
1829 insn != NEXT_INSN (BB_END (bb));
1830 insn = NEXT_INSN (insn))
1836 if (reg_mentioned_p (reg, PATTERN (insn)))
1840 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
1841 if (mt_scan_loop (inner, reg, NULL_RTX))
1847 /* MS2 has a loop instruction which needs to be placed just before the
1848 loop. It indicates the end of the loop and specifies the number of
1849 loop iterations. It can be nested with an automatically maintained
1850 stack of counter and end address registers. It's an ideal
1851 candidate for doloop. Unfortunately, gcc presumes that loops
1852 always end with an explicit instruction, and the doloop_begin
1853 instruction is not a flow control instruction so it can be
1854 scheduled earlier than just before the start of the loop. To make
1855 matters worse, the optimization pipeline can duplicate loop exit
1856 and entrance blocks and fails to track abnormally exiting loops.
1857 Thus we cannot simply use doloop.
1859 What we do is emit a dbnz pattern for the doloop optimization, and
1860 let that be optimized as normal. Then in machine dependent reorg
1861 we have to repeat the loop searching algorithm. We use the
1862 flow graph to find closed loops ending in a dbnz insn. We then try
1863 and convert it to use the loop instruction. The conditions are,
1865 * the loop has no abnormal exits, duplicated end conditions or
1866 duplicated entrance blocks
1868 * the loop counter register is only used in the dbnz instruction
1871 * we can find the instruction setting the initial value of the loop
1874 * the loop is not executed more than 65535 times. (This might be
1875 changed to 2^32-1, and would therefore allow variable initializers.)
1877 * the loop is not nested more than 4 deep 5) there are no
1878 subroutine calls in the loop. */
1881 mt_reorg_loops (FILE *dump_file)
1884 loop_info loops = NULL;
1888 VEC (loop_work,heap) *works = VEC_alloc (loop_work,heap,20);
1892 bool replaced = false;
1894 /* Find all the possible loop tails. This means searching for every
1895 dbnz instruction. For each one found, create a loop_info
1896 structure and add the head block to the work list. */
1899 rtx tail = BB_END (bb);
1901 while (GET_CODE (tail) == NOTE)
1902 tail = PREV_INSN (tail);
1905 if (recog_memoized (tail) == CODE_FOR_decrement_and_branch_until_zero)
1907 /* A possible loop end */
1909 loop = XNEW (struct loop_info);
1913 loop->head = BRANCH_EDGE (bb)->dest;
1914 loop->successor = FALLTHRU_EDGE (bb)->dest;
1915 loop->predecessor = NULL;
1918 loop->length = mt_block_length (bb);
1919 loop->blocks = VEC_alloc (basic_block, heap, 20);
1920 VEC_quick_push (basic_block, loop->blocks, bb);
1922 loop->loop_no = nloops++;
1924 loop->init = loop->end_label = NULL_RTX;
1925 loop->loop_init = loop->loop_end = NULL_RTX;
1927 work = VEC_safe_push (loop_work, heap, works, NULL);
1928 work->block = loop->head;
1935 fprintf (dump_file, ";; potential loop %d ending at\n",
1937 print_rtl_single (dump_file, tail);
1942 /* Now find all the closed loops.
1943 until work list empty,
1944 if block's auxptr is set
1946 if block's loop's start != block
1949 append block's loop's fallthrough block to worklist
1950 increment this loop's depth
1951 else if block is exit block
1955 for each target of block
1957 while (VEC_iterate (loop_work, works, dwork++, work))
1961 if (bb == EXIT_BLOCK_PTR)
1962 /* We've reached the exit block. The loop must be bad. */
1966 /* We've not seen this block before. Add it to the loop's
1967 list and then add each successor to the work list. */
1969 loop->length += mt_block_length (bb);
1970 VEC_safe_push (basic_block, heap, loop->blocks, bb);
1971 FOR_EACH_EDGE (e, ei, bb->succs)
1973 if (!VEC_space (loop_work, works, 1))
1977 VEC_block_remove (loop_work, works, 0, dwork);
1981 VEC_reserve (loop_work, heap, works, 1);
1983 work = VEC_quick_push (loop_work, works, NULL);
1984 work->block = EDGE_SUCC (bb, ei.index)->dest;
1988 else if (bb->aux != loop)
1990 /* We've seen this block in a different loop. If it's not
1991 the other loop's head, then this loop must be bad.
1992 Otherwise, the other loop might be a nested loop, so
1993 continue from that loop's successor. */
1994 loop_info other = bb->aux;
1996 if (other->head != bb)
2000 VEC_safe_push (loop_info, heap, loop->loops, other);
2001 work = VEC_safe_push (loop_work, heap, works, NULL);
2003 work->block = other->successor;
2007 VEC_free (loop_work, heap, works);
2009 /* Now optimize the loops. */
2010 for (loop = loops; loop; loop = loop->next)
2012 rtx iter_reg, insn, init_insn;
2013 rtx init_val, loop_end, loop_init, end_label, head_label;
2015 if (!mt_loop_nesting (loop))
2018 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
2022 /* Get the loop iteration register. */
2023 iter_reg = SET_DEST (XVECEXP (PATTERN (loop->dbnz), 0, 1));
2025 if (!REG_P (iter_reg))
2029 fprintf (dump_file, ";; loop %d has spilled iteration count\n",
2034 /* Look for the initializing insn */
2035 init_insn = NULL_RTX;
2036 for (insn = BB_END (loop->predecessor);
2037 insn != PREV_INSN (BB_HEAD (loop->predecessor));
2038 insn = PREV_INSN (insn))
2042 if (reg_mentioned_p (iter_reg, PATTERN (insn)))
2044 rtx set = single_set (insn);
2046 if (set && rtx_equal_p (iter_reg, SET_DEST (set)))
2055 fprintf (dump_file, ";; loop %d has no initializer\n",
2061 fprintf (dump_file, ";; loop %d initialized by\n",
2063 print_rtl_single (dump_file, init_insn);
2066 init_val = PATTERN (init_insn);
2067 if (GET_CODE (init_val) == SET)
2068 init_val = SET_SRC (init_val);
2069 if (GET_CODE (init_val) != CONST_INT || INTVAL (init_val) >= 65535)
2072 fprintf (dump_file, ";; loop %d has complex initializer\n",
2077 /* Scan all the blocks to make sure they don't use iter_reg. */
2078 if (mt_scan_loop (loop, iter_reg, loop->dbnz))
2081 fprintf (dump_file, ";; loop %d uses iterator\n",
2086 /* The loop is good for replacement. */
2088 /* loop is 1 based, dbnz is zero based. */
2089 init_val = GEN_INT (INTVAL (init_val) + 1);
2091 iter_reg = gen_rtx_REG (SImode, LOOP_FIRST + loop->depth - 1);
2092 end_label = gen_label_rtx ();
2093 head_label = XEXP (SET_SRC (XVECEXP (PATTERN (loop->dbnz), 0, 0)), 1);
2094 loop_end = gen_loop_end (iter_reg, head_label);
2095 loop_init = gen_loop_init (iter_reg, init_val, end_label);
2096 loop->init = init_insn;
2097 loop->end_label = end_label;
2098 loop->loop_init = loop_init;
2099 loop->loop_end = loop_end;
2104 fprintf (dump_file, ";; replacing loop %d initializer with\n",
2106 print_rtl_single (dump_file, loop->loop_init);
2107 fprintf (dump_file, ";; replacing loop %d terminator with\n",
2109 print_rtl_single (dump_file, loop->loop_end);
2113 /* Now apply the optimizations. Do it this way so we don't mess up
2114 the flow graph half way through. */
2115 for (loop = loops; loop; loop = loop->next)
2116 if (loop->loop_init)
2118 emit_jump_insn_after (loop->loop_init, BB_END (loop->predecessor));
2119 delete_insn (loop->init);
2120 emit_label_before (loop->end_label, loop->dbnz);
2121 emit_jump_insn_before (loop->loop_end, loop->dbnz);
2122 delete_insn (loop->dbnz);
2125 /* Free up the loop structures */
2130 VEC_free (loop_info, heap, loop->loops);
2131 VEC_free (basic_block, heap, loop->blocks);
2135 if (replaced && dump_file)
2137 fprintf (dump_file, ";; Replaced loops\n");
2138 print_rtl (dump_file, get_insns ());
2142 /* Structures to hold branch information during reorg. */
2143 typedef struct branch_info
2145 rtx insn; /* The branch insn. */
2147 struct branch_info *next;
2150 typedef struct label_info
2152 rtx label; /* The label. */
2153 branch_info *branches; /* branches to this label. */
2154 struct label_info *next;
2157 /* Chain of labels found in current function, used during reorg. */
2158 static label_info *mt_labels;
2160 /* If *X is a label, add INSN to the list of branches for that
2164 mt_add_branches (rtx *x, void *insn)
2166 if (GET_CODE (*x) == LABEL_REF)
2168 branch_info *branch = xmalloc (sizeof (*branch));
2169 rtx label = XEXP (*x, 0);
2172 for (info = mt_labels; info; info = info->next)
2173 if (info->label == label)
2178 info = xmalloc (sizeof (*info));
2179 info->next = mt_labels;
2182 info->label = label;
2183 info->branches = NULL;
2186 branch->next = info->branches;
2187 info->branches = branch;
2188 branch->insn = insn;
2193 /* If BRANCH has a filled delay slot, check if INSN is dependent upon
2194 it. If so, undo the delay slot fill. Returns the next insn, if
2195 we patch out the branch. Returns the branch insn, if we cannot
2196 patch out the branch (due to anti-dependency in the delay slot).
2197 In that case, the caller must insert nops at the branch target. */
2200 mt_check_delay_slot (rtx branch, rtx insn)
2207 gcc_assert (GET_CODE (PATTERN (branch)) == SEQUENCE);
2208 if (INSN_DELETED_P (branch))
2210 slot = XVECEXP (PATTERN (branch), 0, 1);
2212 tmp = PATTERN (insn);
2213 note_stores (PATTERN (slot), insn_dependent_p_1, &tmp);
2215 /* Not dependent. */
2218 /* Undo the delay slot. */
2219 jmp = XVECEXP (PATTERN (branch), 0, 0);
2221 tmp = PATTERN (jmp);
2222 note_stores (PATTERN (slot), insn_dependent_p_1, &tmp);
2224 /* Anti dependent. */
2227 p = PREV_INSN (branch);
2228 NEXT_INSN (p) = slot;
2229 PREV_INSN (slot) = p;
2230 NEXT_INSN (slot) = jmp;
2231 PREV_INSN (jmp) = slot;
2232 NEXT_INSN (jmp) = branch;
2233 PREV_INSN (branch) = jmp;
2234 XVECEXP (PATTERN (branch), 0, 0) = NULL_RTX;
2235 XVECEXP (PATTERN (branch), 0, 1) = NULL_RTX;
2236 delete_insn (branch);
2240 /* Insert nops to satisfy pipeline constraints. We only deal with ms2
2241 constraints here. Earlier CPUs are dealt with by inserting nops with
2242 final_prescan (but that can lead to inferior code, and is
2243 impractical with ms2's JAL hazard).
2245 ms2 dynamic constraints
2246 1) a load and a following use must be separated by one insn
2247 2) an insn and a following dependent call must be separated by two insns
2249 only arith insns are placed in delay slots so #1 cannot happen with
2250 a load in a delay slot. #2 can happen with an arith insn in the
2254 mt_reorg_hazard (void)
2258 /* Find all the branches */
2259 for (insn = get_insns ();
2261 insn = NEXT_INSN (insn))
2268 jmp = PATTERN (insn);
2270 if (GET_CODE (jmp) != SEQUENCE)
2271 /* If it's not got a filled delay slot, then it can't
2275 jmp = XVECEXP (jmp, 0, 0);
2277 if (recog_memoized (jmp) == CODE_FOR_tablejump)
2278 for (jmp = XEXP (XEXP (XVECEXP (PATTERN (jmp), 0, 1), 0), 0);
2279 !JUMP_TABLE_DATA_P (jmp);
2280 jmp = NEXT_INSN (jmp))
2283 for_each_rtx (&PATTERN (jmp), mt_add_branches, insn);
2286 /* Now scan for dependencies. */
2287 for (insn = get_insns ();
2288 insn && !INSN_P (insn);
2289 insn = NEXT_INSN (insn))
2297 enum attr_type attr;
2299 gcc_assert (INSN_P (insn) && !INSN_DELETED_P (insn));
2300 for (next = NEXT_INSN (insn);
2302 next = NEXT_INSN (next))
2306 if (GET_CODE (PATTERN (next)) != USE)
2311 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
2312 jmp = XVECEXP (PATTERN (insn), 0, 0);
2314 attr = recog_memoized (jmp) >= 0 ? get_attr_type (jmp) : TYPE_UNKNOWN;
2316 if (next && attr == TYPE_LOAD)
2318 /* A load. See if NEXT is dependent, and if so insert a
2321 tmp = PATTERN (next);
2322 if (GET_CODE (tmp) == SEQUENCE)
2323 tmp = PATTERN (XVECEXP (tmp, 0, 0));
2324 note_stores (PATTERN (insn), insn_dependent_p_1, &tmp);
2326 emit_insn_after (gen_nop (), insn);
2329 if (attr == TYPE_CALL)
2331 /* A call. Make sure we're not dependent on either of the
2332 previous two dynamic instructions. */
2336 rtx rescan = NULL_RTX;
2338 for (count = 2; count && !nops;)
2342 prev = PREV_INSN (prev);
2345 /* If we reach the start of the function, we must
2346 presume the caller set the address in the delay
2347 slot of the call instruction. */
2352 if (BARRIER_P (prev))
2356 /* Look at branches to this label. */
2358 branch_info *branch;
2360 for (label = mt_labels;
2362 label = label->next)
2363 if (label->label == prev)
2365 for (branch = label->branches;
2367 branch = branch->next)
2369 tmp = mt_check_delay_slot (branch->insn, jmp);
2371 if (tmp == branch->insn)
2377 if (tmp && branch->insn == next)
2384 if (!INSN_P (prev) || GET_CODE (PATTERN (prev)) == USE)
2387 if (GET_CODE (PATTERN (prev)) == SEQUENCE)
2389 /* Look at the delay slot. */
2390 tmp = mt_check_delay_slot (prev, jmp);
2396 type = (INSN_CODE (prev) >= 0 ? get_attr_type (prev)
2398 if (type == TYPE_CALL || type == TYPE_BRANCH)
2401 if (type == TYPE_LOAD
2402 || type == TYPE_ARITH
2403 || type == TYPE_COMPLEX)
2405 tmp = PATTERN (jmp);
2406 note_stores (PATTERN (prev), insn_dependent_p_1, &tmp);
2414 if (INSN_CODE (prev) >= 0)
2419 for (next = NEXT_INSN (rescan);
2420 next && !INSN_P (next);
2421 next = NEXT_INSN (next))
2424 emit_insn_before (gen_nop (), insn);
2428 /* Free the data structures. */
2431 label_info *label = mt_labels;
2432 branch_info *branch, *next;
2434 mt_labels = label->next;
2435 for (branch = label->branches; branch; branch = next)
2437 next = branch->next;
2444 /* Fixup the looping instructions, do delayed branch scheduling, fixup
2445 scheduling hazards. */
2448 mt_machine_reorg (void)
2450 if (cfun->machine->has_loops && TARGET_MS2)
2451 mt_reorg_loops (dump_file);
2453 if (mt_flag_delayed_branch)
2454 dbr_schedule (get_insns ());
2458 /* Force all instructions to be split into their final form. */
2459 split_all_insns_noflow ();
2465 mt_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2467 return (int_size_in_bytes (type) > UNITS_PER_WORD);
2471 /* Initialize the GCC target structure. */
2472 const struct attribute_spec mt_attribute_table[];
2474 #undef TARGET_ATTRIBUTE_TABLE
2475 #define TARGET_ATTRIBUTE_TABLE mt_attribute_table
2476 #undef TARGET_STRUCT_VALUE_RTX
2477 #define TARGET_STRUCT_VALUE_RTX mt_struct_value_rtx
2478 #undef TARGET_PROMOTE_PROTOTYPES
2479 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
2480 #undef TARGET_PASS_BY_REFERENCE
2481 #define TARGET_PASS_BY_REFERENCE mt_pass_by_reference
2482 #undef TARGET_MUST_PASS_IN_STACK
2483 #define TARGET_MUST_PASS_IN_STACK mt_pass_in_stack
2484 #undef TARGET_ARG_PARTIAL_BYTES
2485 #define TARGET_ARG_PARTIAL_BYTES mt_arg_partial_bytes
2486 #undef TARGET_SETUP_INCOMING_VARARGS
2487 #define TARGET_SETUP_INCOMING_VARARGS mt_setup_incoming_varargs
2488 #undef TARGET_MACHINE_DEPENDENT_REORG
2489 #define TARGET_MACHINE_DEPENDENT_REORG mt_machine_reorg
2491 struct gcc_target targetm = TARGET_INITIALIZER;