1 /* Target definitions for the MorphoRISC1
2 Copyright (C) 2005 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 2, 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 COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
36 #include "integrate.h"
45 #include "insn-flags.h"
49 #include "target-def.h"
50 #include "basic-block.h"
52 /* Frame pointer register mask. */
53 #define FP_MASK (1 << (GPR_FP))
55 /* Link register mask. */
56 #define LINK_MASK (1 << (GPR_LINK))
59 #define MS1_INT_ARG_FIRST 1
61 /* Given a SIZE in bytes, advance to the next word. */
62 #define ROUND_ADVANCE(SIZE) (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
64 /* A C structure for machine-specific, per-function data.
65 This is added to the cfun structure. */
66 struct machine_function
GTY(())
68 /* Flags if __builtin_return_address (n) with n >= 1 was used. */
69 int ra_needs_full_frame
;
70 struct rtx_def
* eh_stack_adjust
;
71 int interrupt_handler
;
75 /* Define the information needed to generate branch and scc insns.
76 This is stored from the compare operation. */
77 struct rtx_def
* ms1_compare_op0
;
78 struct rtx_def
* ms1_compare_op1
;
80 /* Current frame information calculated by compute_frame_size. */
81 struct ms1_frame_info current_frame_info
;
83 /* Zero structure to initialize current_frame_info. */
84 struct ms1_frame_info zero_frame_info
;
86 /* ms1 doesn't have unsigned compares need a library call for this. */
87 struct rtx_def
* ms1_ucmpsi3_libcall
;
89 static int ms1_flag_delayed_branch
;
93 ms1_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED
,
94 int incoming ATTRIBUTE_UNUSED
)
96 return gen_rtx_REG (Pmode
, RETVAL_REGNUM
);
99 /* Implement RETURN_ADDR_RTX. */
101 ms1_return_addr_rtx (int count
)
106 return get_hard_reg_initial_val (Pmode
, GPR_LINK
);
109 /* The following variable value indicates the number of nops required
110 between the current instruction and the next instruction to avoid
111 any pipeline hazards. */
112 static int ms1_nops_required
= 0;
113 static const char * ms1_nop_reasons
= "";
115 /* Implement ASM_OUTPUT_OPCODE. */
117 ms1_asm_output_opcode (FILE *f ATTRIBUTE_UNUSED
, const char *ptr
)
119 if (ms1_nops_required
)
120 fprintf (f
, ";# need %d nops because of %s\n\t",
121 ms1_nops_required
, ms1_nop_reasons
);
123 while (ms1_nops_required
)
125 fprintf (f
, "or r0, r0, r0\n\t");
126 -- ms1_nops_required
;
132 /* Given an insn, return whether it's a memory operation or a branch
133 operation, otherwise return TYPE_ARITH. */
134 static enum attr_type
135 ms1_get_attr_type (rtx complete_insn
)
137 rtx insn
= PATTERN (complete_insn
);
139 if (JUMP_P (complete_insn
))
141 if (CALL_P (complete_insn
))
144 if (GET_CODE (insn
) != SET
)
147 if (SET_DEST (insn
) == pc_rtx
)
150 if (GET_CODE (SET_DEST (insn
)) == MEM
)
153 if (GET_CODE (SET_SRC (insn
)) == MEM
)
159 /* A helper routine for insn_dependent_p called through note_stores. */
162 insn_dependent_p_1 (rtx x
, rtx pat ATTRIBUTE_UNUSED
, void *data
)
164 rtx
* pinsn
= (rtx
*) data
;
166 if (*pinsn
&& reg_mentioned_p (x
, *pinsn
))
170 /* Return true if anything in insn X is (anti,output,true)
171 dependent on anything in insn Y. */
174 insn_dependent_p (rtx x
, rtx y
)
178 if (! INSN_P (x
) || ! INSN_P (y
))
182 note_stores (PATTERN (x
), insn_dependent_p_1
, &tmp
);
187 note_stores (PATTERN (y
), insn_dependent_p_1
, &tmp
);
188 return (tmp
== NULL_RTX
);
192 /* Return true if anything in insn X is true dependent on anything in
195 insn_true_dependent_p (rtx x
, rtx y
)
199 if (! INSN_P (x
) || ! INSN_P (y
))
203 note_stores (PATTERN (x
), insn_dependent_p_1
, &tmp
);
204 return (tmp
== NULL_RTX
);
207 /* The following determines the number of nops that need to be
208 inserted between the previous instructions and current instruction
209 to avoid pipeline hazards on the ms1 processor. Remember that
210 the function is not called for asm insns. */
213 ms1_final_prescan_insn (rtx insn
,
214 rtx
* opvec ATTRIBUTE_UNUSED
,
215 int noperands ATTRIBUTE_UNUSED
)
218 enum attr_type prev_attr
;
220 ms1_nops_required
= 0;
221 ms1_nop_reasons
= "";
223 /* ms2 constraints are dealt with in reorg. */
224 if (ms1_cpu
== PROCESSOR_MS2
)
227 /* Only worry about real instructions. */
231 /* Find the previous real instructions. */
232 for (prev_i
= PREV_INSN (insn
);
234 && (! INSN_P (prev_i
)
235 || GET_CODE (PATTERN (prev_i
)) == USE
236 || GET_CODE (PATTERN (prev_i
)) == CLOBBER
);
237 prev_i
= PREV_INSN (prev_i
))
239 /* If we meet a barrier, there is no flow through here. */
240 if (BARRIER_P (prev_i
))
244 /* If there isn't one then there is nothing that we need do. */
245 if (prev_i
== NULL
|| ! INSN_P (prev_i
))
248 prev_attr
= ms1_get_attr_type (prev_i
);
250 /* Delayed branch slots already taken care of by delay branch scheduling. */
251 if (prev_attr
== TYPE_BRANCH
)
254 switch (ms1_get_attr_type (insn
))
258 /* Avoid consecutive memory operation. */
259 if ((prev_attr
== TYPE_LOAD
|| prev_attr
== TYPE_STORE
)
260 && ms1_cpu
== PROCESSOR_MS1_64_001
)
262 ms1_nops_required
= 1;
263 ms1_nop_reasons
= "consecutive mem ops";
269 /* One cycle of delay is required between load
270 and the dependent arithmetic instruction. */
271 if (prev_attr
== TYPE_LOAD
272 && insn_true_dependent_p (prev_i
, insn
))
274 ms1_nops_required
= 1;
275 ms1_nop_reasons
= "load->arith dependency delay";
280 if (insn_dependent_p (prev_i
, insn
))
282 if (prev_attr
== TYPE_ARITH
283 && ms1_cpu
== PROCESSOR_MS1_64_001
)
285 /* One cycle of delay between arith
286 instructions and branch dependent on arith. */
287 ms1_nops_required
= 1;
288 ms1_nop_reasons
= "arith->branch dependency delay";
290 else if (prev_attr
== TYPE_LOAD
)
292 /* Two cycles of delay are required
293 between load and dependent branch. */
294 if (ms1_cpu
== PROCESSOR_MS1_64_001
)
295 ms1_nops_required
= 2;
297 ms1_nops_required
= 1;
298 ms1_nop_reasons
= "load->branch dependency delay";
304 fatal_insn ("ms1_final_prescan_insn, invalid insn #1", insn
);
309 /* Print debugging information for a frame. */
311 ms1_debug_stack (struct ms1_frame_info
* info
)
317 error ("info pointer NULL");
321 fprintf (stderr
, "\nStack information for function %s:\n",
322 ((current_function_decl
&& DECL_NAME (current_function_decl
))
323 ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl
))
326 fprintf (stderr
, "\ttotal_size = %d\n", info
->total_size
);
327 fprintf (stderr
, "\tpretend_size = %d\n", info
->pretend_size
);
328 fprintf (stderr
, "\targs_size = %d\n", info
->args_size
);
329 fprintf (stderr
, "\textra_size = %d\n", info
->extra_size
);
330 fprintf (stderr
, "\treg_size = %d\n", info
->reg_size
);
331 fprintf (stderr
, "\tvar_size = %d\n", info
->var_size
);
332 fprintf (stderr
, "\tframe_size = %d\n", info
->frame_size
);
333 fprintf (stderr
, "\treg_mask = 0x%x\n", info
->reg_mask
);
334 fprintf (stderr
, "\tsave_fp = %d\n", info
->save_fp
);
335 fprintf (stderr
, "\tsave_lr = %d\n", info
->save_lr
);
336 fprintf (stderr
, "\tinitialized = %d\n", info
->initialized
);
337 fprintf (stderr
, "\tsaved registers =");
339 /* Print out reg_mask in a more readable format. */
340 for (regno
= GPR_R0
; regno
<= GPR_LAST
; regno
++)
341 if ( (1 << regno
) & info
->reg_mask
)
342 fprintf (stderr
, " %s", reg_names
[regno
]);
348 /* Print a memory address as an operand to reference that memory location. */
351 ms1_print_operand_simple_address (FILE * file
, rtx addr
)
354 error ("PRINT_OPERAND_ADDRESS, null pointer");
357 switch (GET_CODE (addr
))
360 fprintf (file
, "%s, #0", reg_names
[REGNO (addr
)]);
367 rtx arg0
= XEXP (addr
, 0);
368 rtx arg1
= XEXP (addr
, 1);
370 if (GET_CODE (arg0
) == REG
)
374 if (GET_CODE (offset
) == REG
)
375 fatal_insn ("PRINT_OPERAND_ADDRESS, 2 regs", addr
);
378 else if (GET_CODE (arg1
) == REG
)
379 reg
= arg1
, offset
= arg0
;
380 else if (CONSTANT_P (arg0
) && CONSTANT_P (arg1
))
382 fprintf (file
, "%s, #", reg_names
[GPR_R0
]);
383 output_addr_const (file
, addr
);
386 fprintf (file
, "%s, #", reg_names
[REGNO (reg
)]);
387 output_addr_const (file
, offset
);
395 output_addr_const (file
, addr
);
399 fatal_insn ("PRINT_OPERAND_ADDRESS, invalid insn #1", addr
);
404 /* Implement PRINT_OPERAND_ADDRESS. */
406 ms1_print_operand_address (FILE * file
, rtx addr
)
408 if (GET_CODE (addr
) == AND
409 && GET_CODE (XEXP (addr
, 1)) == CONST_INT
410 && INTVAL (XEXP (addr
, 1)) == -3)
411 ms1_print_operand_simple_address (file
, XEXP (addr
, 0));
413 ms1_print_operand_simple_address (file
, addr
);
416 /* Implement PRINT_OPERAND. */
418 ms1_print_operand (FILE * file
, rtx x
, int code
)
423 /* Output a nop if there's nothing for the delay slot. */
424 if (dbr_sequence_length () == 0)
425 fputs ("\n\tor r0, r0, r0", file
);
429 fprintf(file
, "#%%hi16(");
430 output_addr_const (file
, x
);
435 fprintf(file
, "#%%lo16(");
436 output_addr_const (file
, x
);
441 fprintf(file
, "#%ld", ~INTVAL (x
));
445 if (GET_CODE (x
) == CONST_INT
&& INTVAL (x
) == 0)
447 fputs (reg_names
[GPR_R0
], file
);
456 /* output_operand_lossage ("ms1_print_operand: unknown code"); */
457 fprintf (file
, "unknown code");
461 switch (GET_CODE (x
))
464 fputs (reg_names
[REGNO (x
)], file
);
469 fprintf(file
, "#%ld", INTVAL (x
));
473 ms1_print_operand_address(file
, XEXP (x
,0));
478 output_addr_const (file
, x
);
482 fprintf(file
, "Uknown code: %d", GET_CODE (x
));
489 /* Implement INIT_CUMULATIVE_ARGS. */
491 ms1_init_cumulative_args (CUMULATIVE_ARGS
* cum
, tree fntype
, rtx libname
,
492 tree fndecl ATTRIBUTE_UNUSED
, int incoming
)
496 if (TARGET_DEBUG_ARG
)
498 fprintf (stderr
, "\nms1_init_cumulative_args:");
501 fputs (" incoming", stderr
);
505 tree ret_type
= TREE_TYPE (fntype
);
506 fprintf (stderr
, " return = %s,",
507 tree_code_name
[ (int)TREE_CODE (ret_type
) ]);
510 if (libname
&& GET_CODE (libname
) == SYMBOL_REF
)
511 fprintf (stderr
, " libname = %s", XSTR (libname
, 0));
513 if (cfun
->returns_struct
)
514 fprintf (stderr
, " return-struct");
520 /* Compute the slot number to pass an argument in.
521 Returns the slot number or -1 if passing on the stack.
523 CUM is a variable of type CUMULATIVE_ARGS which gives info about
524 the preceding args and about the function being called.
525 MODE is the argument's machine mode.
526 TYPE is the data type of the argument (as a tree).
527 This is null for libcalls where that information may
529 NAMED is nonzero if this argument is a named parameter
530 (otherwise it is an extra parameter matching an ellipsis).
531 INCOMING_P is zero for FUNCTION_ARG, nonzero for FUNCTION_INCOMING_ARG.
532 *PREGNO records the register number to use if scalar type. */
535 ms1_function_arg_slotno (const CUMULATIVE_ARGS
* cum
,
536 enum machine_mode mode
,
538 int named ATTRIBUTE_UNUSED
,
539 int incoming_p ATTRIBUTE_UNUSED
,
542 int regbase
= MS1_INT_ARG_FIRST
;
545 if (mode
== VOIDmode
|| targetm
.calls
.must_pass_in_stack (mode
, type
))
548 if (slotno
>= MS1_NUM_ARG_REGS
)
551 * pregno
= regbase
+ slotno
;
556 /* Implement FUNCTION_ARG. */
558 ms1_function_arg (const CUMULATIVE_ARGS
* cum
,
559 enum machine_mode mode
,
567 slotno
= ms1_function_arg_slotno (cum
, mode
, type
, named
, incoming_p
,
573 reg
= gen_rtx_REG (mode
, regno
);
578 /* Implement FUNCTION_ARG_ADVANCE. */
580 ms1_function_arg_advance (CUMULATIVE_ARGS
* cum
,
581 enum machine_mode mode
,
582 tree type ATTRIBUTE_UNUSED
,
587 /* We pass 0 for incoming_p here, it doesn't matter. */
588 slotno
= ms1_function_arg_slotno (cum
, mode
, type
, named
, 0, ®no
);
590 * cum
+= (mode
!= BLKmode
591 ? ROUND_ADVANCE (GET_MODE_SIZE (mode
))
592 : ROUND_ADVANCE (int_size_in_bytes (type
)));
594 if (TARGET_DEBUG_ARG
)
596 "ms1_function_arg_advance: words = %2d, mode = %4s, named = %d, size = %3d\n",
597 *cum
, GET_MODE_NAME (mode
), named
,
598 (*cum
) * UNITS_PER_WORD
);
601 /* Implement hook TARGET_ARG_PARTIAL_BYTES.
603 Returns the number of bytes at the beginning of an argument that
604 must be put in registers. The value must be zero for arguments
605 that are passed entirely in registers or that are entirely pushed
608 ms1_arg_partial_bytes (CUMULATIVE_ARGS
* pcum
,
609 enum machine_mode mode
,
611 bool named ATTRIBUTE_UNUSED
)
617 words
= ((int_size_in_bytes (type
) + UNITS_PER_WORD
- 1)
620 words
= (GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
622 if (! targetm
.calls
.pass_by_reference (& cum
, mode
, type
, named
)
623 && cum
< MS1_NUM_ARG_REGS
624 && (cum
+ words
) > MS1_NUM_ARG_REGS
)
626 int bytes
= (MS1_NUM_ARG_REGS
- cum
) * UNITS_PER_WORD
;
629 fprintf (stderr
, "function_arg_partial_nregs = %d\n", bytes
);
637 /* Implement TARGET_PASS_BY_REFERENCE hook. */
639 ms1_pass_by_reference (CUMULATIVE_ARGS
* cum ATTRIBUTE_UNUSED
,
640 enum machine_mode mode ATTRIBUTE_UNUSED
,
642 bool named ATTRIBUTE_UNUSED
)
644 return (type
&& int_size_in_bytes (type
) > 4 * UNITS_PER_WORD
);
647 /* Implement FUNCTION_ARG_BOUNDARY. */
649 ms1_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED
,
650 tree type ATTRIBUTE_UNUSED
)
652 return BITS_PER_WORD
;
655 /* Implement REG_OK_FOR_BASE_P. */
657 ms1_reg_ok_for_base_p (rtx x
, int strict
)
660 return (((unsigned) REGNO (x
)) < FIRST_PSEUDO_REGISTER
);
664 /* Helper function of ms1_legitimate_address_p. Return true if XINSN
665 is a simple address, otherwise false. */
667 ms1_legitimate_simple_address_p (enum machine_mode mode ATTRIBUTE_UNUSED
,
673 fprintf (stderr
, "\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
674 strict
? "" : "not ");
678 if (GET_CODE (xinsn
) == REG
&& ms1_reg_ok_for_base_p (xinsn
, strict
))
681 if (GET_CODE (xinsn
) == PLUS
682 && GET_CODE (XEXP (xinsn
, 0)) == REG
683 && ms1_reg_ok_for_base_p (XEXP (xinsn
, 0), strict
)
684 && GET_CODE (XEXP (xinsn
, 1)) == CONST_INT
685 && SMALL_INT (XEXP (xinsn
, 1)))
692 /* Helper function of GO_IF_LEGITIMATE_ADDRESS. Return non-zero if
693 XINSN is a legitimate address on MS1. */
695 ms1_legitimate_address_p (enum machine_mode mode
,
699 if (ms1_legitimate_simple_address_p (mode
, xinsn
, strict
))
703 && GET_CODE (xinsn
) == AND
704 && GET_CODE (XEXP (xinsn
, 1)) == CONST_INT
705 && INTVAL (XEXP (xinsn
, 1)) == -3)
706 return ms1_legitimate_simple_address_p (mode
, XEXP (xinsn
, 0), strict
);
711 /* Return truth value of whether OP can be used as an operands where a
712 register or 16 bit unsigned integer is needed. */
715 uns_arith_operand (rtx op
, enum machine_mode mode
)
717 if (GET_CODE (op
) == CONST_INT
&& SMALL_INT_UNSIGNED (op
))
720 return register_operand (op
, mode
);
723 /* Return truth value of whether OP can be used as an operands where a
724 16 bit integer is needed. */
727 arith_operand (rtx op
, enum machine_mode mode
)
729 if (GET_CODE (op
) == CONST_INT
&& SMALL_INT (op
))
732 return register_operand (op
, mode
);
735 /* Return truth value of whether OP is a register or the constant 0. */
738 reg_or_0_operand (rtx op
, enum machine_mode mode
)
740 switch (GET_CODE (op
))
743 return INTVAL (op
) == 0;
747 return register_operand (op
, mode
);
756 /* Return truth value of whether OP is a constant that requires two
757 loads to put in a register. */
760 big_const_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
762 if (GET_CODE (op
) == CONST_INT
&& CONST_OK_FOR_LETTER_P (INTVAL (op
), 'M'))
768 /* Return truth value of whether OP is a constant that require only
769 one load to put in a register. */
772 single_const_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
774 if (big_const_operand (op
, mode
)
775 || GET_CODE (op
) == CONST
776 || GET_CODE (op
) == LABEL_REF
777 || GET_CODE (op
) == SYMBOL_REF
)
783 /* True if the current function is an interrupt handler
784 (either via #pragma or an attribute specification). */
785 int interrupt_handler
;
786 enum processor_type ms1_cpu
;
788 static struct machine_function
*
789 ms1_init_machine_status (void)
791 struct machine_function
*f
;
793 f
= ggc_alloc_cleared (sizeof (struct machine_function
));
798 /* Implement OVERRIDE_OPTIONS. */
800 ms1_override_options (void)
802 if (ms1_cpu_string
!= NULL
)
804 if (!strcasecmp (ms1_cpu_string
, "MS1-64-001"))
805 ms1_cpu
= PROCESSOR_MS1_64_001
;
806 else if (!strcasecmp (ms1_cpu_string
, "MS1-16-002"))
807 ms1_cpu
= PROCESSOR_MS1_16_002
;
808 else if (!strcasecmp (ms1_cpu_string
, "MS1-16-003"))
809 ms1_cpu
= PROCESSOR_MS1_16_003
;
810 else if (!strcasecmp (ms1_cpu_string
, "MS2"))
811 ms1_cpu
= PROCESSOR_MS2
;
813 error ("bad value (%s) for -march= switch", ms1_cpu_string
);
816 ms1_cpu
= PROCESSOR_MS2
;
820 flag_omit_frame_pointer
= 0;
824 /* We do delayed branch filling in machine dependent reorg */
825 ms1_flag_delayed_branch
= flag_delayed_branch
;
826 flag_delayed_branch
= 0;
828 init_machine_status
= ms1_init_machine_status
;
831 /* Do what is necessary for `va_start'. We look at the current function
832 to determine if stdarg or varargs is used and return the address of the
833 first unnamed parameter. */
836 ms1_builtin_saveregs (void)
842 for (regno
= first_reg
; regno
< MS1_NUM_ARG_REGS
; regno
++)
843 emit_move_insn (gen_rtx_MEM (word_mode
,
845 gen_rtx_REG (SImode
, ARG_POINTER_REGNUM
),
846 GEN_INT (UNITS_PER_WORD
* regno
))),
847 gen_rtx_REG (word_mode
,
848 MS1_INT_ARG_FIRST
+ regno
));
850 address
= gen_rtx_PLUS (Pmode
,
851 gen_rtx_REG (SImode
, ARG_POINTER_REGNUM
),
852 GEN_INT (UNITS_PER_WORD
* first_reg
));
856 /* Implement `va_start'. */
859 ms1_va_start (tree valist
, rtx nextarg
)
861 ms1_builtin_saveregs ();
862 std_expand_builtin_va_start (valist
, nextarg
);
865 /* Returns the number of bytes offset between the frame pointer and the stack
866 pointer for the current function. SIZE is the number of bytes of space
867 needed for local variables. */
870 ms1_compute_frame_size (int size
)
873 unsigned int total_size
;
874 unsigned int var_size
;
875 unsigned int args_size
;
876 unsigned int pretend_size
;
877 unsigned int extra_size
;
878 unsigned int reg_size
;
879 unsigned int frame_size
;
880 unsigned int reg_mask
;
883 args_size
= current_function_outgoing_args_size
;
884 pretend_size
= current_function_pretend_args_size
;
885 extra_size
= FIRST_PARM_OFFSET (0);
886 total_size
= extra_size
+ pretend_size
+ args_size
+ var_size
;
890 /* Calculate space needed for registers. */
891 for (regno
= GPR_R0
; regno
<= GPR_LAST
; regno
++)
893 if (MUST_SAVE_REGISTER (regno
))
895 reg_size
+= UNITS_PER_WORD
;
896 reg_mask
|= 1 << regno
;
900 current_frame_info
.save_fp
= (regs_ever_live
[GPR_FP
]
901 || frame_pointer_needed
902 || interrupt_handler
);
903 current_frame_info
.save_lr
= (regs_ever_live
[GPR_LINK
]
905 || interrupt_handler
);
907 reg_size
+= (current_frame_info
.save_fp
+ current_frame_info
.save_lr
)
909 total_size
+= reg_size
;
910 total_size
= ((total_size
+ 3) & ~3);
912 frame_size
= total_size
;
914 /* Save computed information. */
915 current_frame_info
.pretend_size
= pretend_size
;
916 current_frame_info
.var_size
= var_size
;
917 current_frame_info
.args_size
= args_size
;
918 current_frame_info
.reg_size
= reg_size
;
919 current_frame_info
.frame_size
= args_size
+ var_size
;
920 current_frame_info
.total_size
= total_size
;
921 current_frame_info
.extra_size
= extra_size
;
922 current_frame_info
.reg_mask
= reg_mask
;
923 current_frame_info
.initialized
= reload_completed
;
928 /* Emit code to save REG in stack offset pointed to by MEM.
929 STACK_OFFSET is the offset from the SP where the save will happen.
930 This function sets the REG_FRAME_RELATED_EXPR note accordingly. */
932 ms1_emit_save_restore (enum save_direction direction
,
937 if (direction
== FROM_PROCESSOR_TO_MEM
)
941 insn
= emit_move_insn (mem
, reg
);
942 RTX_FRAME_RELATED_P (insn
) = 1;
944 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
945 gen_rtx_SET (VOIDmode
,
948 gen_rtx_PLUS (SImode
,
950 GEN_INT (stack_offset
))),
955 emit_move_insn (reg
, mem
);
959 /* Emit code to save the frame pointer in the prologue and restore
960 frame pointer in epilogue. */
963 ms1_emit_save_fp (enum save_direction direction
,
964 struct ms1_frame_info info
)
967 int reg_mask
= info
.reg_mask
& ~(FP_MASK
| LINK_MASK
);
968 int offset
= info
.total_size
;
969 int stack_offset
= info
.total_size
;
971 /* If there is nothing to save, get out now. */
972 if (! info
.save_fp
&& ! info
.save_lr
&& ! reg_mask
)
975 /* If offset doesn't fit in a 15-bit signed integer,
976 uses a scratch registers to get a smaller offset. */
977 if (CONST_OK_FOR_LETTER_P(offset
, 'O'))
978 base_reg
= stack_pointer_rtx
;
981 /* Use the scratch register R9 that holds old stack pointer. */
982 base_reg
= gen_rtx_REG (SImode
, GPR_R9
);
988 offset
-= UNITS_PER_WORD
;
989 stack_offset
-= UNITS_PER_WORD
;
990 ms1_emit_save_restore (direction
, gen_rtx_REG (SImode
, GPR_FP
),
992 gen_rtx_PLUS (SImode
, base_reg
, GEN_INT (offset
))),
997 /* Emit code to save registers in the prologue and restore register
1001 ms1_emit_save_regs (enum save_direction direction
,
1002 struct ms1_frame_info info
)
1006 int reg_mask
= info
.reg_mask
& ~(FP_MASK
| LINK_MASK
);
1007 int offset
= info
.total_size
;
1008 int stack_offset
= info
.total_size
;
1010 /* If there is nothing to save, get out now. */
1011 if (! info
.save_fp
&& ! info
.save_lr
&& ! reg_mask
)
1014 /* If offset doesn't fit in a 15-bit signed integer,
1015 uses a scratch registers to get a smaller offset. */
1016 if (CONST_OK_FOR_LETTER_P(offset
, 'O'))
1017 base_reg
= stack_pointer_rtx
;
1020 /* Use the scratch register R9 that holds old stack pointer. */
1021 base_reg
= gen_rtx_REG (SImode
, GPR_R9
);
1027 /* This just records the space for it, the actual move generated in
1028 ms1_emit_save_fp (). */
1029 offset
-= UNITS_PER_WORD
;
1030 stack_offset
-= UNITS_PER_WORD
;
1035 offset
-= UNITS_PER_WORD
;
1036 stack_offset
-= UNITS_PER_WORD
;
1037 ms1_emit_save_restore (direction
, gen_rtx_REG (SImode
, GPR_LINK
),
1038 gen_rtx_MEM (SImode
,
1039 gen_rtx_PLUS (SImode
, base_reg
, GEN_INT (offset
))),
1043 /* Save any needed call-saved regs. */
1044 for (regno
= GPR_R0
; regno
<= GPR_LAST
; regno
++)
1046 if ((reg_mask
& (1 << regno
)) != 0)
1048 offset
-= UNITS_PER_WORD
;
1049 stack_offset
-= UNITS_PER_WORD
;
1050 ms1_emit_save_restore (direction
, gen_rtx_REG (SImode
, regno
),
1051 gen_rtx_MEM (SImode
,
1052 gen_rtx_PLUS (SImode
, base_reg
, GEN_INT (offset
))),
1058 /* Return true if FUNC is a function with the 'interrupt' attribute. */
1060 ms1_interrupt_function_p (tree func
)
1064 if (TREE_CODE (func
) != FUNCTION_DECL
)
1067 a
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (func
));
1068 return a
!= NULL_TREE
;
1071 /* Generate prologue code. */
1073 ms1_expand_prologue (void)
1076 unsigned int frame_size
;
1078 if (ms1_interrupt_function_p (current_function_decl
))
1080 interrupt_handler
= 1;
1082 cfun
->machine
->interrupt_handler
= 1;
1085 ms1_compute_frame_size (get_frame_size ());
1087 if (TARGET_DEBUG_STACK
)
1088 ms1_debug_stack (¤t_frame_info
);
1090 /* Compute size of stack adjustment. */
1091 frame_size
= current_frame_info
.total_size
;
1093 /* If offset doesn't fit in a 15-bit signed integer,
1094 uses a scratch registers to get a smaller offset. */
1095 if (CONST_OK_FOR_LETTER_P(frame_size
, 'O'))
1096 size_rtx
= GEN_INT (frame_size
);
1099 /* We do not have any scratch registers. */
1100 gcc_assert (!interrupt_handler
);
1102 size_rtx
= gen_rtx_REG (SImode
, GPR_R9
);
1103 insn
= emit_move_insn (size_rtx
, GEN_INT (frame_size
& 0xffff0000));
1104 insn
= emit_insn (gen_iorsi3 (size_rtx
, size_rtx
,
1105 GEN_INT (frame_size
& 0x0000ffff)));
1108 /* Allocate stack for this frame. */
1109 /* Make stack adjustment and use scratch register if constant too
1110 large to fit as immediate. */
1113 insn
= emit_insn (gen_subsi3 (stack_pointer_rtx
,
1116 RTX_FRAME_RELATED_P (insn
) = 1;
1118 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
1119 gen_rtx_SET (VOIDmode
,
1121 gen_rtx_MINUS (SImode
,
1123 GEN_INT (frame_size
))),
1127 /* Set R9 to point to old sp if required for access to register save area. */
1128 if ( current_frame_info
.reg_size
!= 0
1129 && !CONST_OK_FOR_LETTER_P (frame_size
, 'O'))
1130 emit_insn (gen_addsi3 (size_rtx
, size_rtx
, stack_pointer_rtx
));
1132 /* Save the frame pointer. */
1133 ms1_emit_save_fp (FROM_PROCESSOR_TO_MEM
, current_frame_info
);
1135 /* Now put the frame pointer into the frame pointer register. */
1136 if (frame_pointer_needed
)
1138 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1139 RTX_FRAME_RELATED_P (insn
) = 1;
1142 /* Save the registers. */
1143 ms1_emit_save_regs (FROM_PROCESSOR_TO_MEM
, current_frame_info
);
1145 /* If we are profiling, make sure no instructions are scheduled before
1146 the call to mcount. */
1148 emit_insn (gen_blockage ());
1151 /* Implement EPILOGUE_USES. */
1153 ms1_epilogue_uses (int regno
)
1155 if (cfun
->machine
&& cfun
->machine
->interrupt_handler
&& reload_completed
)
1157 return regno
== GPR_LINK
;
1160 /* Generate epilogue. EH_MODE is NORMAL_EPILOGUE when generating a
1161 function epilogue, or EH_EPILOGUE when generating an EH
1164 ms1_expand_epilogue (enum epilogue_type eh_mode
)
1167 unsigned frame_size
;
1169 ms1_compute_frame_size (get_frame_size ());
1171 if (TARGET_DEBUG_STACK
)
1172 ms1_debug_stack (& current_frame_info
);
1174 /* Compute size of stack adjustment. */
1175 frame_size
= current_frame_info
.total_size
;
1177 /* If offset doesn't fit in a 15-bit signed integer,
1178 uses a scratch registers to get a smaller offset. */
1179 if (CONST_OK_FOR_LETTER_P(frame_size
, 'O'))
1180 size_rtx
= GEN_INT (frame_size
);
1183 /* We do not have any scratch registers. */
1184 gcc_assert (!interrupt_handler
);
1186 size_rtx
= gen_rtx_REG (SImode
, GPR_R9
);
1187 insn
= emit_move_insn (size_rtx
, GEN_INT (frame_size
& 0xffff0000));
1188 insn
= emit_insn (gen_iorsi3 (size_rtx
, size_rtx
,
1189 GEN_INT (frame_size
& 0x0000ffff)));
1190 /* Set R9 to point to old sp if required for access to register
1192 emit_insn (gen_addsi3 (size_rtx
, size_rtx
, stack_pointer_rtx
));
1195 /* Restore sp if there was some possible change to it. */
1196 if (frame_pointer_needed
)
1197 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
1199 /* Restore the registers. */
1200 ms1_emit_save_fp (FROM_MEM_TO_PROCESSOR
, current_frame_info
);
1201 ms1_emit_save_regs (FROM_MEM_TO_PROCESSOR
, current_frame_info
);
1203 /* Make stack adjustment and use scratch register if constant too
1204 large to fit as immediate. */
1207 if (CONST_OK_FOR_LETTER_P(frame_size
, 'O'))
1208 /* Can handle this with simple add. */
1209 insn
= emit_insn (gen_addsi3 (stack_pointer_rtx
,
1213 /* Scratch reg R9 has the old sp value. */
1214 insn
= emit_move_insn (stack_pointer_rtx
,
1215 gen_rtx_REG (SImode
, GPR_R9
));
1218 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR
,
1219 gen_rtx_SET (VOIDmode
,
1221 gen_rtx_PLUS (SImode
,
1223 GEN_INT (frame_size
))),
1227 if (cfun
->machine
&& cfun
->machine
->eh_stack_adjust
!= NULL_RTX
)
1228 /* Perform the additional bump for __throw. */
1229 emit_insn (gen_addsi3 (stack_pointer_rtx
,
1231 cfun
->machine
->eh_stack_adjust
));
1233 /* Generate the appropriate return. */
1234 if (eh_mode
== EH_EPILOGUE
)
1236 emit_jump_insn (gen_eh_return_internal ());
1239 else if (interrupt_handler
)
1240 emit_jump_insn (gen_return_interrupt_internal ());
1242 emit_jump_insn (gen_return_internal ());
1244 /* Reset state info for each function. */
1245 interrupt_handler
= 0;
1246 current_frame_info
= zero_frame_info
;
1248 cfun
->machine
->eh_stack_adjust
= NULL_RTX
;
1252 /* Generate code for the "eh_return" pattern. */
1254 ms1_expand_eh_return (rtx
* operands
)
1256 if (GET_CODE (operands
[0]) != REG
1257 || REGNO (operands
[0]) != EH_RETURN_STACKADJ_REGNO
)
1259 rtx sp
= EH_RETURN_STACKADJ_RTX
;
1261 emit_move_insn (sp
, operands
[0]);
1265 emit_insn (gen_eh_epilogue (operands
[0]));
1268 /* Generate code for the "eh_epilogue" pattern. */
1270 ms1_emit_eh_epilogue (rtx
* operands ATTRIBUTE_UNUSED
)
1272 cfun
->machine
->eh_stack_adjust
= EH_RETURN_STACKADJ_RTX
; /* operands[0]; */
1273 ms1_expand_epilogue (EH_EPILOGUE
);
1276 /* Handle an "interrupt" attribute. */
1278 ms1_handle_interrupt_attribute (tree
* node
,
1280 tree args ATTRIBUTE_UNUSED
,
1281 int flags ATTRIBUTE_UNUSED
,
1282 bool * no_add_attrs
)
1284 if (TREE_CODE (*node
) != FUNCTION_DECL
)
1286 warning (OPT_Wattributes
,
1287 "%qs attribute only applies to functions",
1288 IDENTIFIER_POINTER (name
));
1289 *no_add_attrs
= true;
1295 /* Table of machine attributes. */
1296 const struct attribute_spec ms1_attribute_table
[] =
1298 /* name, min, max, decl?, type?, func?, handler */
1299 { "interrupt", 0, 0, false, false, false, ms1_handle_interrupt_attribute
},
1300 { NULL
, 0, 0, false, false, false, NULL
}
1303 /* Implement INITIAL_ELIMINATION_OFFSET. */
1305 ms1_initial_elimination_offset (int from
, int to
)
1307 ms1_compute_frame_size (get_frame_size ());
1309 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
1312 else if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
1313 return current_frame_info
.total_size
;
1315 else if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
1316 return current_frame_info
.total_size
;
1322 /* Generate a compare for CODE. Return a brand-new rtx that
1323 represents the result of the compare. */
1326 ms1_generate_compare (enum rtx_code code
, rtx op0
, rtx op1
)
1328 rtx scratch0
, scratch1
, const_scratch
;
1336 /* Need to adjust ranges for faking unsigned compares. */
1337 scratch0
= gen_reg_rtx (SImode
);
1338 scratch1
= gen_reg_rtx (SImode
);
1339 const_scratch
= force_reg (SImode
, GEN_INT(MS1_MIN_INT
));
1340 emit_insn (gen_addsi3 (scratch0
, const_scratch
, op0
));
1341 emit_insn (gen_addsi3 (scratch1
, const_scratch
, op1
));
1349 /* Adjust compare operator to fake unsigned compares. */
1365 /* Generate the actual compare. */
1366 return gen_rtx_fmt_ee (code
, VOIDmode
, scratch0
, scratch1
);
1369 /* Emit a branch of kind CODE to location LOC. */
1372 ms1_emit_cbranch (enum rtx_code code
, rtx loc
, rtx op0
, rtx op1
)
1374 rtx condition_rtx
, loc_ref
;
1376 if (! reg_or_0_operand (op0
, SImode
))
1377 op0
= copy_to_mode_reg (SImode
, op0
);
1379 if (! reg_or_0_operand (op1
, SImode
))
1380 op1
= copy_to_mode_reg (SImode
, op1
);
1382 condition_rtx
= ms1_generate_compare (code
, op0
, op1
);
1383 loc_ref
= gen_rtx_LABEL_REF (VOIDmode
, loc
);
1384 emit_jump_insn (gen_rtx_SET (VOIDmode
, pc_rtx
,
1385 gen_rtx_IF_THEN_ELSE (VOIDmode
, condition_rtx
,
1389 /* Subfunction of the following function. Update the flags of any MEM
1390 found in part of X. */
1393 ms1_set_memflags_1 (rtx x
, int in_struct_p
, int volatile_p
)
1397 switch (GET_CODE (x
))
1401 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
1402 ms1_set_memflags_1 (XVECEXP (x
, 0, i
), in_struct_p
, volatile_p
);
1406 ms1_set_memflags_1 (PATTERN (x
), in_struct_p
, volatile_p
);
1410 ms1_set_memflags_1 (SET_DEST (x
), in_struct_p
, volatile_p
);
1411 ms1_set_memflags_1 (SET_SRC (x
), in_struct_p
, volatile_p
);
1415 MEM_IN_STRUCT_P (x
) = in_struct_p
;
1416 MEM_VOLATILE_P (x
) = volatile_p
;
1417 /* Sadly, we cannot use alias sets because the extra aliasing
1418 produced by the AND interferes. Given that two-byte quantities
1419 are the only thing we would be able to differentiate anyway,
1420 there does not seem to be any point in convoluting the early
1421 out of the alias check. */
1422 /* set_mem_alias_set (x, alias_set); */
1430 /* Look for any MEMs in the current sequence of insns and set the
1431 in-struct, unchanging, and volatile flags from the flags in REF.
1432 If REF is not a MEM, don't do anything. */
1435 ms1_set_memflags (rtx ref
)
1438 int in_struct_p
, volatile_p
;
1440 if (GET_CODE (ref
) != MEM
)
1443 in_struct_p
= MEM_IN_STRUCT_P (ref
);
1444 volatile_p
= MEM_VOLATILE_P (ref
);
1446 /* This is only called from ms1.md, after having had something
1447 generated from one of the insn patterns. So if everything is
1448 zero, the pattern is already up-to-date. */
1449 if (! in_struct_p
&& ! volatile_p
)
1452 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1453 ms1_set_memflags_1 (insn
, in_struct_p
, volatile_p
);
1456 /* Implement SECONDARY_RELOAD_CLASS. */
1458 ms1_secondary_reload_class (enum reg_class
class ATTRIBUTE_UNUSED
,
1459 enum machine_mode mode
,
1462 if ((mode
== QImode
&& (!TARGET_BYTE_ACCESS
)) || mode
== HImode
)
1464 if (GET_CODE (x
) == MEM
1465 || (GET_CODE (x
) == REG
&& true_regnum (x
) == -1)
1466 || (GET_CODE (x
) == SUBREG
1467 && (GET_CODE (SUBREG_REG (x
)) == MEM
1468 || (GET_CODE (SUBREG_REG (x
)) == REG
1469 && true_regnum (SUBREG_REG (x
)) == -1))))
1470 return GENERAL_REGS
;
1476 /* Handle FUNCTION_VALUE, FUNCTION_OUTGOING_VALUE, and LIBCALL_VALUE
1479 ms1_function_value (tree valtype
, enum machine_mode mode
, tree func_decl ATTRIBUTE_UNUSED
)
1481 if ((mode
) == DImode
|| (mode
) == DFmode
)
1482 return gen_rtx_MEM (mode
, gen_rtx_REG (mode
, RETURN_VALUE_REGNUM
));
1485 mode
= TYPE_MODE (valtype
);
1487 return gen_rtx_REG (mode
, RETURN_VALUE_REGNUM
);
1490 /* Split a move into two smaller pieces.
1491 MODE indicates the reduced mode. OPERANDS[0] is the original destination
1492 OPERANDS[1] is the original src. The new destinations are
1493 OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3]
1497 ms1_split_words (enum machine_mode nmode
,
1498 enum machine_mode omode
,
1501 rtx dl
,dh
; /* src/dest pieces. */
1503 int move_high_first
= 0; /* Assume no overlap. */
1505 switch (GET_CODE (operands
[0])) /* Dest. */
1509 if ((GET_CODE (operands
[1]) == REG
1510 || GET_CODE (operands
[1]) == SUBREG
)
1511 && true_regnum (operands
[0]) <= true_regnum (operands
[1]))
1512 move_high_first
= 1;
1514 if (GET_CODE (operands
[0]) == SUBREG
)
1516 dl
= gen_rtx_SUBREG (nmode
, SUBREG_REG (operands
[0]),
1517 SUBREG_BYTE (operands
[0]) + GET_MODE_SIZE (nmode
));
1518 dh
= gen_rtx_SUBREG (nmode
, SUBREG_REG (operands
[0]), SUBREG_BYTE (operands
[0]));
1520 else if (GET_CODE (operands
[0]) == REG
&& ! IS_PSEUDO_P (operands
[0]))
1522 int r
= REGNO (operands
[0]);
1523 dh
= gen_rtx_REG (nmode
, r
);
1524 dl
= gen_rtx_REG (nmode
, r
+ HARD_REGNO_NREGS (r
, nmode
));
1528 dh
= gen_rtx_SUBREG (nmode
, operands
[0], 0);
1529 dl
= gen_rtx_SUBREG (nmode
, operands
[0], GET_MODE_SIZE (nmode
));
1534 switch (GET_CODE (XEXP (operands
[0], 0)))
1540 dl
= operand_subword (operands
[0],
1541 GET_MODE_SIZE (nmode
)/UNITS_PER_WORD
,
1543 dh
= operand_subword (operands
[0], 0, 0, omode
);
1550 switch (GET_CODE (operands
[1]))
1553 if (! IS_PSEUDO_P (operands
[1]))
1555 int r
= REGNO (operands
[1]);
1557 sh
= gen_rtx_REG (nmode
, r
);
1558 sl
= gen_rtx_REG (nmode
, r
+ HARD_REGNO_NREGS (r
, nmode
));
1562 sh
= gen_rtx_SUBREG (nmode
, operands
[1], 0);
1563 sl
= gen_rtx_SUBREG (nmode
, operands
[1], GET_MODE_SIZE (nmode
));
1568 if (operands
[1] == const0_rtx
)
1569 sh
= sl
= const0_rtx
;
1571 split_double (operands
[1], & sh
, & sl
);
1575 if (operands
[1] == const0_rtx
)
1576 sh
= sl
= const0_rtx
;
1593 sl
= gen_rtx_SUBREG (nmode
,
1594 SUBREG_REG (operands
[1]),
1595 SUBREG_BYTE (operands
[1]) + GET_MODE_SIZE (nmode
));
1596 sh
= gen_rtx_SUBREG (nmode
,
1597 SUBREG_REG (operands
[1]),
1598 SUBREG_BYTE (operands
[1]));
1602 switch (GET_CODE (XEXP (operands
[1], 0)))
1609 sl
= operand_subword (operands
[1],
1610 GET_MODE_SIZE (nmode
)/UNITS_PER_WORD
,
1612 sh
= operand_subword (operands
[1], 0, 0, omode
);
1614 /* Check if the DF load is going to clobber the register
1615 used for the address, and if so make sure that is going
1616 to be the second move. */
1617 if (GET_CODE (dl
) == REG
1619 == true_regnum (XEXP (XEXP (sl
, 0 ), 0)))
1620 move_high_first
= 1;
1627 if (move_high_first
)
1644 /* Implement TARGET_MUST_PASS_IN_STACK hook. */
1646 ms1_pass_in_stack (enum machine_mode mode ATTRIBUTE_UNUSED
, tree type
)
1648 return (((type
) != 0
1649 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
1650 || TREE_ADDRESSABLE (type
))));
1653 /* Increment the counter for the number of loop instructions in the
1654 current function. */
1656 void ms1_add_loop (void)
1658 cfun
->machine
->has_loops
++;
1662 /* Maxium loop nesting depth. */
1663 #define MAX_LOOP_DEPTH 4
1664 /* Maxium size of a loop (allows some headroom for delayed branch slot
1666 #define MAX_LOOP_LENGTH (200 * 4)
1668 /* We need to keep a vector of basic blocks */
1669 DEF_VEC_P (basic_block
);
1670 DEF_VEC_ALLOC_P (basic_block
,heap
);
1672 /* And a vector of loops */
1673 typedef struct loop_info
*loop_info
;
1674 DEF_VEC_P (loop_info
);
1675 DEF_VEC_ALLOC_P (loop_info
,heap
);
1677 /* Information about a loop we have found (or are in the process of
1679 struct loop_info
GTY (())
1681 /* loop number, for dumps */
1684 /* Predecessor block of the loop. This is the one that falls into
1685 the loop and contains the initialization instruction. */
1686 basic_block predecessor
;
1688 /* First block in the loop. This is the one branched to by the dbnz
1692 /* Last block in the loop (the one with the dbnz insn */
1695 /* The successor block of the loop. This is the one the dbnz insn
1697 basic_block successor
;
1699 /* The dbnz insn. */
1702 /* The initialization insn. */
1705 /* The new initialization instruction. */
1708 /* The new ending instruction. */
1711 /* The new label placed at the end of the loop. */
1714 /* The nesting depth of the loop. Set to -1 for a bad loop. */
1717 /* The length of the loop. */
1720 /* Next loop in the graph. */
1721 struct loop_info
*next
;
1723 /* Vector of blocks only within the loop, (excluding those within
1725 VEC (basic_block
,heap
) *blocks
;
1727 /* Vector of inner loops within this loop */
1728 VEC (loop_info
,heap
) *loops
;
1731 /* Information used during loop detection. */
1732 typedef struct loop_work
GTY(())
1734 /* Basic block to be scanned. */
1737 /* Loop it will be within. */
1742 DEF_VEC_O (loop_work
);
1743 DEF_VEC_ALLOC_O (loop_work
,heap
);
1745 /* Determine the nesting and length of LOOP. Return false if the loop
1749 ms1_loop_nesting (loop_info loop
)
1753 int inner_depth
= 0;
1757 /* Make sure we only have one entry point. */
1758 if (EDGE_COUNT (loop
->head
->preds
) == 2)
1760 loop
->predecessor
= EDGE_PRED (loop
->head
, 0)->src
;
1761 if (loop
->predecessor
== loop
->tail
)
1762 /* We wanted the other predecessor. */
1763 loop
->predecessor
= EDGE_PRED (loop
->head
, 1)->src
;
1765 /* We can only place a loop insn on a fall through edge of a
1766 single exit block. */
1767 if (EDGE_COUNT (loop
->predecessor
->succs
) != 1
1768 || !(EDGE_SUCC (loop
->predecessor
, 0)->flags
& EDGE_FALLTHRU
))
1769 loop
->predecessor
= NULL
;
1772 /* Mark this loop as bad for now. */
1774 if (loop
->predecessor
)
1776 for (ix
= 0; VEC_iterate (loop_info
, loop
->loops
, ix
++, inner
);)
1779 ms1_loop_nesting (inner
);
1781 if (inner
->depth
< 0)
1787 if (inner_depth
< inner
->depth
)
1788 inner_depth
= inner
->depth
;
1789 loop
->length
+= inner
->length
;
1792 /* Set the proper loop depth, if it was good. */
1793 if (inner_depth
>= 0)
1794 loop
->depth
= inner_depth
+ 1;
1797 return (loop
->depth
> 0
1798 && loop
->predecessor
1799 && loop
->depth
< MAX_LOOP_DEPTH
1800 && loop
->length
< MAX_LOOP_LENGTH
);
1803 /* Determine the length of block BB. */
1806 ms1_block_length (basic_block bb
)
1811 for (insn
= BB_HEAD (bb
);
1812 insn
!= NEXT_INSN (BB_END (bb
));
1813 insn
= NEXT_INSN (insn
))
1819 /* Calls are not allowed in loops. */
1820 length
= MAX_LOOP_LENGTH
+ 1;
1824 length
+= get_attr_length (insn
);
1829 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
1830 REG. Return true, if we find any. Don't count the loop's dbnz
1831 insn if it matches DBNZ. */
1834 ms1_scan_loop (loop_info loop
, rtx reg
, rtx dbnz
)
1840 for (ix
= 0; VEC_iterate (basic_block
, loop
->blocks
, ix
, bb
); ix
++)
1844 for (insn
= BB_HEAD (bb
);
1845 insn
!= NEXT_INSN (BB_END (bb
));
1846 insn
= NEXT_INSN (insn
))
1852 if (reg_mentioned_p (reg
, PATTERN (insn
)))
1856 for (ix
= 0; VEC_iterate (loop_info
, loop
->loops
, ix
, inner
); ix
++)
1857 if (ms1_scan_loop (inner
, reg
, NULL_RTX
))
1863 /* MS2 has a loop instruction which needs to be placed just before the
1864 loop. It indicates the end of the loop and specifies the number of
1865 loop iterations. It can be nested with an automatically maintained
1866 stack of counter and end address registers. It's an ideal
1867 candidate for doloop. Unfortunately, gcc presumes that loops
1868 always end with an explicit instriction, and the doloop_begin
1869 instruction is not a flow control instruction so it can be
1870 scheduled earlier than just before the start of the loop. To make
1871 matters worse, the optimization pipeline can duplicate loop exit
1872 and entrance blocks and fails to track abnormally exiting loops.
1873 Thus we cannot simply use doloop.
1875 What we do is emit a dbnz pattern for the doloop optimization, and
1876 let that be optimized as normal. Then in machine dependent reorg
1877 we have to repeat the loop searching algorithm. We use the
1878 flow graph to find closed loops ending in a dbnz insn. We then try
1879 and convert it to use the loop instruction. The conditions are,
1881 * the loop has no abnormal exits, duplicated end conditions or
1882 duplicated entrance blocks
1884 * the loop counter register is only used in the dbnz instruction
1887 * we can find the instruction setting the initial value of the loop
1890 * the loop is not executed more than 65535 times. (This might be
1891 changed to 2^32-1, and would therefore allow variable initializers.)
1893 * the loop is not nested more than 4 deep 5) there are no
1894 subroutine calls in the loop. */
1897 ms1_reorg_loops (FILE *dump_file
)
1900 loop_info loops
= NULL
;
1904 VEC (loop_work
,heap
) *works
= VEC_alloc (loop_work
,heap
,20);
1908 bool replaced
= false;
1910 /* Find all the possible loop tails. This means searching for every
1911 dbnz instruction. For each one found, create a loop_info
1912 structure and add the head block to the work list. */
1915 rtx tail
= BB_END (bb
);
1917 while (GET_CODE (tail
) == NOTE
)
1918 tail
= PREV_INSN (tail
);
1921 if (recog_memoized (tail
) == CODE_FOR_decrement_and_branch_until_zero
)
1923 /* A possible loop end */
1925 loop
= XNEW (struct loop_info
);
1929 loop
->head
= BRANCH_EDGE (bb
)->dest
;
1930 loop
->successor
= FALLTHRU_EDGE (bb
)->dest
;
1931 loop
->predecessor
= NULL
;
1934 loop
->length
= ms1_block_length (bb
);
1935 loop
->blocks
= VEC_alloc (basic_block
, heap
, 20);
1936 VEC_quick_push (basic_block
, loop
->blocks
, bb
);
1938 loop
->loop_no
= nloops
++;
1940 loop
->init
= loop
->end_label
= NULL_RTX
;
1941 loop
->loop_init
= loop
->loop_end
= NULL_RTX
;
1943 work
= VEC_safe_push (loop_work
, heap
, works
, NULL
);
1944 work
->block
= loop
->head
;
1951 fprintf (dump_file
, ";; potential loop %d ending at\n",
1953 print_rtl_single (dump_file
, tail
);
1958 /* Now find all the closed loops.
1959 until work list empty,
1960 if block's auxptr is set
1962 if block's loop's start != block
1965 append block's loop's fallthrough block to worklist
1966 increment this loop's depth
1967 else if block is exit block
1971 for each target of block
1973 while (VEC_iterate (loop_work
, works
, dwork
++, work
))
1977 if (bb
== EXIT_BLOCK_PTR
)
1978 /* We've reached the exit block. The loop must be bad. */
1982 /* We've not seen this block before. Add it to the loop's
1983 list and then add each successor to the work list. */
1985 loop
->length
+= ms1_block_length (bb
);
1986 VEC_safe_push (basic_block
, heap
, loop
->blocks
, bb
);
1987 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
1989 if (!VEC_space (loop_work
, works
, 1))
1993 VEC_block_remove (loop_work
, works
, 0, dwork
);
1997 VEC_reserve (loop_work
, heap
, works
, 1);
1999 work
= VEC_quick_push (loop_work
, works
, NULL
);
2000 work
->block
= EDGE_SUCC (bb
, ei
.index
)->dest
;
2004 else if (bb
->aux
!= loop
)
2006 /* We've seen this block in a different loop. If it's not
2007 the other loop's head, then this loop must be bad.
2008 Otherwise, the other loop might be a nested loop, so
2009 continue from that loop's successor. */
2010 loop_info other
= bb
->aux
;
2012 if (other
->head
!= bb
)
2016 VEC_safe_push (loop_info
, heap
, loop
->loops
, other
);
2017 work
= VEC_safe_push (loop_work
, heap
, works
, NULL
);
2019 work
->block
= other
->successor
;
2023 VEC_free (loop_work
, heap
, works
);
2025 /* Now optimize the loops. */
2026 for (loop
= loops
; loop
; loop
= loop
->next
)
2028 rtx iter_reg
, insn
, init_insn
;
2029 rtx init_val
, loop_end
, loop_init
, end_label
, head_label
;
2031 if (!ms1_loop_nesting (loop
))
2034 fprintf (dump_file
, ";; loop %d is bad\n", loop
->loop_no
);
2038 /* Get the loop iteration register. */
2039 iter_reg
= SET_DEST (XVECEXP (PATTERN (loop
->dbnz
), 0, 1));
2041 if (!REG_P (iter_reg
))
2045 fprintf (dump_file
, ";; loop %d has spilled iteration count\n",
2050 /* Look for the initializing insn */
2051 init_insn
= NULL_RTX
;
2052 for (insn
= BB_END (loop
->predecessor
);
2053 insn
!= PREV_INSN (BB_HEAD (loop
->predecessor
));
2054 insn
= PREV_INSN (insn
))
2058 if (reg_mentioned_p (iter_reg
, PATTERN (insn
)))
2060 rtx set
= single_set (insn
);
2062 if (set
&& rtx_equal_p (iter_reg
, SET_DEST (set
)))
2071 fprintf (dump_file
, ";; loop %d has no initializer\n",
2077 fprintf (dump_file
, ";; loop %d initialized by\n",
2079 print_rtl_single (dump_file
, init_insn
);
2082 init_val
= PATTERN (init_insn
);
2083 if (GET_CODE (init_val
) == SET
)
2084 init_val
= SET_SRC (init_val
);
2085 if (GET_CODE (init_val
) != CONST_INT
|| INTVAL (init_val
) >= 65535)
2088 fprintf (dump_file
, ";; loop %d has complex initializer\n",
2093 /* Scan all the blocks to make sure they don't use iter_reg. */
2094 if (ms1_scan_loop (loop
, iter_reg
, loop
->dbnz
))
2097 fprintf (dump_file
, ";; loop %d uses iterator\n",
2102 /* The loop is good for replacement. */
2104 /* loop is 1 based, dbnz is zero based. */
2105 init_val
= GEN_INT (INTVAL (init_val
) + 1);
2107 iter_reg
= gen_rtx_REG (SImode
, LOOP_FIRST
+ loop
->depth
- 1);
2108 end_label
= gen_label_rtx ();
2109 head_label
= XEXP (SET_SRC (XVECEXP (PATTERN (loop
->dbnz
), 0, 0)), 1);
2110 loop_end
= gen_loop_end (iter_reg
, head_label
);
2111 loop_init
= gen_loop_init (iter_reg
, init_val
, end_label
);
2112 loop
->init
= init_insn
;
2113 loop
->end_label
= end_label
;
2114 loop
->loop_init
= loop_init
;
2115 loop
->loop_end
= loop_end
;
2120 fprintf (dump_file
, ";; replacing loop %d initializer with\n",
2122 print_rtl_single (dump_file
, loop
->loop_init
);
2123 fprintf (dump_file
, ";; replacing loop %d terminator with\n",
2125 print_rtl_single (dump_file
, loop
->loop_end
);
2129 /* Now apply the optimizations. Do it this way so we don't mess up
2130 the flow graph half way through. */
2131 for (loop
= loops
; loop
; loop
= loop
->next
)
2132 if (loop
->loop_init
)
2134 emit_jump_insn_after (loop
->loop_init
, BB_END (loop
->predecessor
));
2135 delete_insn (loop
->init
);
2136 emit_label_before (loop
->end_label
, loop
->dbnz
);
2137 emit_jump_insn_before (loop
->loop_end
, loop
->dbnz
);
2138 delete_insn (loop
->dbnz
);
2141 /* Free up the loop structures */
2146 VEC_free (loop_info
, heap
, loop
->loops
);
2147 VEC_free (basic_block
, heap
, loop
->blocks
);
2151 if (replaced
&& dump_file
)
2153 fprintf (dump_file
, ";; Replaced loops\n");
2154 print_rtl (dump_file
, get_insns ());
2158 /* Structures to hold branch information during reorg. */
2159 typedef struct branch_info
2161 rtx insn
; /* The branch insn. */
2163 struct branch_info
*next
;
2166 typedef struct label_info
2168 rtx label
; /* The label. */
2169 branch_info
*branches
; /* branches to this label. */
2170 struct label_info
*next
;
2173 /* Chain of labels found in current function, used during reorg. */
2174 static label_info
*ms1_labels
;
2176 /* If *X is a label, add INSN to the list of branches for that
2180 ms1_add_branches (rtx
*x
, void *insn
)
2182 if (GET_CODE (*x
) == LABEL_REF
)
2184 branch_info
*branch
= xmalloc (sizeof (*branch
));
2185 rtx label
= XEXP (*x
, 0);
2188 for (info
= ms1_labels
; info
; info
= info
->next
)
2189 if (info
->label
== label
)
2194 info
= xmalloc (sizeof (*info
));
2195 info
->next
= ms1_labels
;
2198 info
->label
= label
;
2199 info
->branches
= NULL
;
2202 branch
->next
= info
->branches
;
2203 info
->branches
= branch
;
2204 branch
->insn
= insn
;
2209 /* If BRANCH has a filled delay slot, check if INSN is dependent upon
2210 it. If so, undo the delay slot fill. Returns the next insn, if
2211 we patch out the branch. Returns the branch insn, if we cannot
2212 patch out the branch (due to anti-dependency in the delay slot).
2213 In that case, the caller must insert nops at the branch target. */
2216 ms1_check_delay_slot (rtx branch
, rtx insn
)
2223 gcc_assert (GET_CODE (PATTERN (branch
)) == SEQUENCE
);
2224 if (INSN_DELETED_P (branch
))
2226 slot
= XVECEXP (PATTERN (branch
), 0, 1);
2228 tmp
= PATTERN (insn
);
2229 note_stores (PATTERN (slot
), insn_dependent_p_1
, &tmp
);
2231 /* Not dependent. */
2234 /* Undo the delay slot. */
2235 jmp
= XVECEXP (PATTERN (branch
), 0, 0);
2237 tmp
= PATTERN (jmp
);
2238 note_stores (PATTERN (slot
), insn_dependent_p_1
, &tmp
);
2240 /* Anti dependent. */
2243 p
= PREV_INSN (branch
);
2244 NEXT_INSN (p
) = slot
;
2245 PREV_INSN (slot
) = p
;
2246 NEXT_INSN (slot
) = jmp
;
2247 PREV_INSN (jmp
) = slot
;
2248 NEXT_INSN (jmp
) = branch
;
2249 PREV_INSN (branch
) = jmp
;
2250 XVECEXP (PATTERN (branch
), 0, 0) = NULL_RTX
;
2251 XVECEXP (PATTERN (branch
), 0, 1) = NULL_RTX
;
2252 delete_insn (branch
);
2256 /* Insert nops to satisfy pipeline constraints. We only deal with ms2
2257 constraints here. Earlier CPUs are dealt with by inserting nops with
2258 final_prescan (but that can lead to inferior code, and is
2259 impractical with ms2's JAL hazard).
2261 ms2 dynamic constraints
2262 1) a load and a following use must be separated by one insn
2263 2) an insn and a following dependent call must be separated by two insns
2265 only arith insns are placed in delay slots so #1 cannot happen with
2266 a load in a delay slot. #2 can happen with an arith insn in the
2270 ms1_reorg_hazard (void)
2274 /* Find all the branches */
2275 for (insn
= get_insns ();
2277 insn
= NEXT_INSN (insn
))
2284 jmp
= PATTERN (insn
);
2286 if (GET_CODE (jmp
) != SEQUENCE
)
2287 /* If it's not got a filled delay slot, then it can't
2291 jmp
= XVECEXP (jmp
, 0, 0);
2293 if (recog_memoized (jmp
) == CODE_FOR_tablejump
)
2294 for (jmp
= XEXP (XEXP (XVECEXP (PATTERN (jmp
), 0, 1), 0), 0);
2295 !JUMP_TABLE_DATA_P (jmp
);
2296 jmp
= NEXT_INSN (jmp
))
2299 for_each_rtx (&PATTERN (jmp
), ms1_add_branches
, insn
);
2302 /* Now scan for dependencies. */
2303 for (insn
= get_insns ();
2304 insn
&& !INSN_P (insn
);
2305 insn
= NEXT_INSN (insn
))
2313 enum attr_type attr
;
2315 gcc_assert (INSN_P (insn
) && !INSN_DELETED_P (insn
));
2316 for (next
= NEXT_INSN (insn
);
2317 next
&& !INSN_P (next
);
2318 next
= NEXT_INSN (next
))
2322 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
2323 jmp
= XVECEXP (PATTERN (insn
), 0, 0);
2325 attr
= recog_memoized (jmp
) >= 0 ? get_attr_type (jmp
) : TYPE_UNKNOWN
;
2327 if (next
&& attr
== TYPE_LOAD
)
2329 /* A load. See if NEXT is dependent, and if so insert a
2332 tmp
= PATTERN (next
);
2333 if (GET_CODE (tmp
) == SEQUENCE
)
2334 tmp
= PATTERN (XVECEXP (tmp
, 0, 0));
2335 note_stores (PATTERN (insn
), insn_dependent_p_1
, &tmp
);
2337 emit_insn_after (gen_nop (), insn
);
2340 if (attr
== TYPE_CALL
)
2342 /* A call. Make sure we're not dependent on either of the
2343 previous two dynamic instructions. */
2347 rtx rescan
= NULL_RTX
;
2349 for (count
= 2; count
&& !nops
;)
2353 prev
= PREV_INSN (prev
);
2356 /* If we reach the start of the function, we must
2357 presume the caller set the address in the delay
2358 slot of the call instruction. */
2363 if (BARRIER_P (prev
))
2367 /* Look at branches to this label. */
2369 branch_info
*branch
;
2371 for (label
= ms1_labels
;
2373 label
= label
->next
)
2374 if (label
->label
== prev
)
2376 for (branch
= label
->branches
;
2378 branch
= branch
->next
)
2380 tmp
= ms1_check_delay_slot (branch
->insn
, jmp
);
2382 if (tmp
== branch
->insn
)
2388 if (tmp
&& branch
->insn
== next
)
2398 if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
2400 /* Look at the delay slot. */
2401 tmp
= ms1_check_delay_slot (prev
, jmp
);
2407 type
= (INSN_CODE (prev
) >= 0 ? get_attr_type (prev
)
2409 if (type
== TYPE_CALL
|| type
== TYPE_BRANCH
)
2412 if (type
== TYPE_LOAD
2413 || type
== TYPE_ARITH
2414 || type
== TYPE_COMPLEX
)
2416 tmp
= PATTERN (jmp
);
2417 note_stores (PATTERN (prev
), insn_dependent_p_1
, &tmp
);
2425 if (INSN_CODE (prev
) >= 0)
2427 rtx set
= single_set (prev
);
2429 /* A noop set will get deleted in a later split pass,
2430 so we can't count on it for hazard avoidance. */
2431 if (!set
|| !set_noop_p (set
))
2437 for (next
= NEXT_INSN (rescan
);
2438 next
&& !INSN_P (next
);
2439 next
= NEXT_INSN (next
))
2442 emit_insn_before (gen_nop (), insn
);
2446 /* Free the data structures. */
2449 label_info
*label
= ms1_labels
;
2450 branch_info
*branch
, *next
;
2452 ms1_labels
= label
->next
;
2453 for (branch
= label
->branches
; branch
; branch
= next
)
2455 next
= branch
->next
;
2462 /* Fixup the looping instructions, do delayed branch scheduling, fixup
2463 scheduling hazards. */
2466 ms1_machine_reorg (void)
2468 if (cfun
->machine
->has_loops
)
2469 ms1_reorg_loops (dump_file
);
2471 if (ms1_flag_delayed_branch
)
2472 dbr_schedule (get_insns (), dump_file
);
2474 if (ms1_cpu
== PROCESSOR_MS2
)
2475 ms1_reorg_hazard ();
2478 /* Initialize the GCC target structure. */
2479 const struct attribute_spec ms1_attribute_table
[];
2481 #undef TARGET_ATTRIBUTE_TABLE
2482 #define TARGET_ATTRIBUTE_TABLE ms1_attribute_table
2483 #undef TARGET_STRUCT_VALUE_RTX
2484 #define TARGET_STRUCT_VALUE_RTX ms1_struct_value_rtx
2485 #undef TARGET_PROMOTE_PROTOTYPES
2486 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
2487 #undef TARGET_PASS_BY_REFERENCE
2488 #define TARGET_PASS_BY_REFERENCE ms1_pass_by_reference
2489 #undef TARGET_MUST_PASS_IN_STACK
2490 #define TARGET_MUST_PASS_IN_STACK ms1_pass_in_stack
2491 #undef TARGET_ARG_PARTIAL_BYTES
2492 #define TARGET_ARG_PARTIAL_BYTES ms1_arg_partial_bytes
2493 #undef TARGET_MACHINE_DEPENDENT_REORG
2494 #define TARGET_MACHINE_DEPENDENT_REORG ms1_machine_reorg
2496 struct gcc_target targetm
= TARGET_INITIALIZER
;