xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/m32r/m32r.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg /* Subroutines used for code generation on the Renesas M32R cpu.
2*8feb0f0bSmrg    Copyright (C) 1996-2020 Free Software Foundation, Inc.
336ac495dSmrg 
436ac495dSmrg    This file is part of GCC.
536ac495dSmrg 
636ac495dSmrg    GCC is free software; you can redistribute it and/or modify it
736ac495dSmrg    under the terms of the GNU General Public License as published
836ac495dSmrg    by the Free Software Foundation; either version 3, or (at your
936ac495dSmrg    option) any later version.
1036ac495dSmrg 
1136ac495dSmrg    GCC is distributed in the hope that it will be useful, but WITHOUT
1236ac495dSmrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1336ac495dSmrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1436ac495dSmrg    License for more details.
1536ac495dSmrg 
1636ac495dSmrg    You should have received a copy of the GNU General Public License
1736ac495dSmrg    along with GCC; see the file COPYING3.  If not see
1836ac495dSmrg    <http://www.gnu.org/licenses/>.  */
1936ac495dSmrg 
20a2dc1f3fSmrg #define IN_TARGET_CODE 1
21a2dc1f3fSmrg 
2236ac495dSmrg #include "config.h"
2336ac495dSmrg #include "system.h"
2436ac495dSmrg #include "coretypes.h"
2536ac495dSmrg #include "backend.h"
2636ac495dSmrg #include "target.h"
2736ac495dSmrg #include "rtl.h"
2836ac495dSmrg #include "tree.h"
2936ac495dSmrg #include "df.h"
3036ac495dSmrg #include "memmodel.h"
3136ac495dSmrg #include "tm_p.h"
3236ac495dSmrg #include "stringpool.h"
33a2dc1f3fSmrg #include "attribs.h"
3436ac495dSmrg #include "insn-config.h"
3536ac495dSmrg #include "emit-rtl.h"
3636ac495dSmrg #include "recog.h"
3736ac495dSmrg #include "diagnostic-core.h"
3836ac495dSmrg #include "alias.h"
3936ac495dSmrg #include "stor-layout.h"
4036ac495dSmrg #include "varasm.h"
4136ac495dSmrg #include "calls.h"
4236ac495dSmrg #include "output.h"
4336ac495dSmrg #include "insn-attr.h"
4436ac495dSmrg #include "explow.h"
4536ac495dSmrg #include "expr.h"
4636ac495dSmrg #include "tm-constrs.h"
4736ac495dSmrg #include "builtins.h"
4836ac495dSmrg 
4936ac495dSmrg /* This file should be included last.  */
5036ac495dSmrg #include "target-def.h"
5136ac495dSmrg 
5236ac495dSmrg /* Array of valid operand punctuation characters.  */
5336ac495dSmrg static char m32r_punct_chars[256];
5436ac495dSmrg 
5536ac495dSmrg /* Machine-specific symbol_ref flags.  */
5636ac495dSmrg #define SYMBOL_FLAG_MODEL_SHIFT		SYMBOL_FLAG_MACH_DEP_SHIFT
5736ac495dSmrg #define SYMBOL_REF_MODEL(X) \
5836ac495dSmrg   ((enum m32r_model) ((SYMBOL_REF_FLAGS (X) >> SYMBOL_FLAG_MODEL_SHIFT) & 3))
5936ac495dSmrg 
6036ac495dSmrg /* For string literals, etc.  */
6136ac495dSmrg #define LIT_NAME_P(NAME) ((NAME)[0] == '*' && (NAME)[1] == '.')
6236ac495dSmrg 
6336ac495dSmrg /* Forward declaration.  */
6436ac495dSmrg static void  m32r_option_override (void);
6536ac495dSmrg static void  init_reg_tables (void);
6636ac495dSmrg static void  block_move_call (rtx, rtx, rtx);
6736ac495dSmrg static int   m32r_is_insn (rtx);
6836ac495dSmrg static bool  m32r_legitimate_address_p (machine_mode, rtx, bool);
6936ac495dSmrg static rtx   m32r_legitimize_address (rtx, rtx, machine_mode);
7036ac495dSmrg static bool  m32r_mode_dependent_address_p (const_rtx, addr_space_t);
7136ac495dSmrg static tree  m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
7236ac495dSmrg static void  m32r_print_operand (FILE *, rtx, int);
7336ac495dSmrg static void  m32r_print_operand_address (FILE *, machine_mode, rtx);
7436ac495dSmrg static bool  m32r_print_operand_punct_valid_p (unsigned char code);
75a2dc1f3fSmrg static void  m32r_output_function_prologue (FILE *);
76a2dc1f3fSmrg static void  m32r_output_function_epilogue (FILE *);
7736ac495dSmrg 
7836ac495dSmrg static void  m32r_file_start (void);
7936ac495dSmrg 
8036ac495dSmrg static int    m32r_adjust_priority (rtx_insn *, int);
8136ac495dSmrg static int    m32r_issue_rate (void);
8236ac495dSmrg 
8336ac495dSmrg static void m32r_encode_section_info (tree, rtx, int);
8436ac495dSmrg static bool m32r_in_small_data_p (const_tree);
8536ac495dSmrg static bool m32r_return_in_memory (const_tree, const_tree);
8636ac495dSmrg static rtx m32r_function_value (const_tree, const_tree, bool);
8736ac495dSmrg static rtx m32r_libcall_value (machine_mode, const_rtx);
8836ac495dSmrg static bool m32r_function_value_regno_p (const unsigned int);
89*8feb0f0bSmrg static void m32r_setup_incoming_varargs (cumulative_args_t,
90*8feb0f0bSmrg 					 const function_arg_info &,
91*8feb0f0bSmrg 					 int *, int);
9236ac495dSmrg static void init_idents (void);
9336ac495dSmrg static bool m32r_rtx_costs (rtx, machine_mode, int, int, int *, bool speed);
9436ac495dSmrg static int m32r_memory_move_cost (machine_mode, reg_class_t, bool);
95*8feb0f0bSmrg static bool m32r_pass_by_reference (cumulative_args_t,
96*8feb0f0bSmrg 				    const function_arg_info &arg);
97*8feb0f0bSmrg static int m32r_arg_partial_bytes (cumulative_args_t,
98*8feb0f0bSmrg 				   const function_arg_info &);
99*8feb0f0bSmrg static rtx m32r_function_arg (cumulative_args_t, const function_arg_info &);
100*8feb0f0bSmrg static void m32r_function_arg_advance (cumulative_args_t,
101*8feb0f0bSmrg 				       const function_arg_info &);
10236ac495dSmrg static bool m32r_can_eliminate (const int, const int);
10336ac495dSmrg static void m32r_conditional_register_usage (void);
10436ac495dSmrg static void m32r_trampoline_init (rtx, tree, rtx);
10536ac495dSmrg static bool m32r_legitimate_constant_p (machine_mode, rtx);
10636ac495dSmrg static bool m32r_attribute_identifier (const_tree);
107a2dc1f3fSmrg static bool m32r_hard_regno_mode_ok (unsigned int, machine_mode);
108a2dc1f3fSmrg static bool m32r_modes_tieable_p (machine_mode, machine_mode);
109a2dc1f3fSmrg static HOST_WIDE_INT m32r_starting_frame_offset (void);
11036ac495dSmrg 
11136ac495dSmrg /* M32R specific attributes.  */
11236ac495dSmrg 
11336ac495dSmrg static const struct attribute_spec m32r_attribute_table[] =
11436ac495dSmrg {
115a2dc1f3fSmrg   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
116a2dc1f3fSmrg        affects_type_identity, handler, exclude } */
117a2dc1f3fSmrg   { "interrupt", 0, 0, true,  false, false, false, NULL, NULL },
118a2dc1f3fSmrg   { "model",     1, 1, true,  false, false, false, m32r_handle_model_attribute,
119a2dc1f3fSmrg     NULL },
120a2dc1f3fSmrg   { NULL,        0, 0, false, false, false, false, NULL, NULL }
12136ac495dSmrg };
12236ac495dSmrg 
12336ac495dSmrg /* Initialize the GCC target structure.  */
12436ac495dSmrg #undef  TARGET_ATTRIBUTE_TABLE
12536ac495dSmrg #define TARGET_ATTRIBUTE_TABLE m32r_attribute_table
12636ac495dSmrg #undef  TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P
12736ac495dSmrg #define TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P m32r_attribute_identifier
12836ac495dSmrg 
12936ac495dSmrg #undef TARGET_LRA_P
13036ac495dSmrg #define TARGET_LRA_P hook_bool_void_false
13136ac495dSmrg 
13236ac495dSmrg #undef TARGET_LEGITIMATE_ADDRESS_P
13336ac495dSmrg #define TARGET_LEGITIMATE_ADDRESS_P m32r_legitimate_address_p
13436ac495dSmrg #undef TARGET_LEGITIMIZE_ADDRESS
13536ac495dSmrg #define TARGET_LEGITIMIZE_ADDRESS m32r_legitimize_address
13636ac495dSmrg #undef TARGET_MODE_DEPENDENT_ADDRESS_P
13736ac495dSmrg #define TARGET_MODE_DEPENDENT_ADDRESS_P m32r_mode_dependent_address_p
13836ac495dSmrg 
13936ac495dSmrg #undef  TARGET_ASM_ALIGNED_HI_OP
14036ac495dSmrg #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
14136ac495dSmrg #undef  TARGET_ASM_ALIGNED_SI_OP
14236ac495dSmrg #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
14336ac495dSmrg 
14436ac495dSmrg #undef  TARGET_PRINT_OPERAND
14536ac495dSmrg #define TARGET_PRINT_OPERAND m32r_print_operand
14636ac495dSmrg #undef  TARGET_PRINT_OPERAND_ADDRESS
14736ac495dSmrg #define TARGET_PRINT_OPERAND_ADDRESS m32r_print_operand_address
14836ac495dSmrg #undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
14936ac495dSmrg #define TARGET_PRINT_OPERAND_PUNCT_VALID_P m32r_print_operand_punct_valid_p
15036ac495dSmrg 
15136ac495dSmrg #undef  TARGET_ASM_FUNCTION_PROLOGUE
15236ac495dSmrg #define TARGET_ASM_FUNCTION_PROLOGUE m32r_output_function_prologue
15336ac495dSmrg #undef  TARGET_ASM_FUNCTION_EPILOGUE
15436ac495dSmrg #define TARGET_ASM_FUNCTION_EPILOGUE m32r_output_function_epilogue
15536ac495dSmrg 
15636ac495dSmrg #undef  TARGET_ASM_FILE_START
15736ac495dSmrg #define TARGET_ASM_FILE_START m32r_file_start
15836ac495dSmrg 
15936ac495dSmrg #undef  TARGET_SCHED_ADJUST_PRIORITY
16036ac495dSmrg #define TARGET_SCHED_ADJUST_PRIORITY m32r_adjust_priority
16136ac495dSmrg #undef  TARGET_SCHED_ISSUE_RATE
16236ac495dSmrg #define TARGET_SCHED_ISSUE_RATE m32r_issue_rate
16336ac495dSmrg 
16436ac495dSmrg #undef  TARGET_OPTION_OVERRIDE
16536ac495dSmrg #define TARGET_OPTION_OVERRIDE m32r_option_override
16636ac495dSmrg 
16736ac495dSmrg #undef  TARGET_ENCODE_SECTION_INFO
16836ac495dSmrg #define TARGET_ENCODE_SECTION_INFO m32r_encode_section_info
16936ac495dSmrg #undef  TARGET_IN_SMALL_DATA_P
17036ac495dSmrg #define TARGET_IN_SMALL_DATA_P m32r_in_small_data_p
17136ac495dSmrg 
17236ac495dSmrg 
17336ac495dSmrg #undef  TARGET_MEMORY_MOVE_COST
17436ac495dSmrg #define TARGET_MEMORY_MOVE_COST m32r_memory_move_cost
17536ac495dSmrg #undef  TARGET_RTX_COSTS
17636ac495dSmrg #define TARGET_RTX_COSTS m32r_rtx_costs
17736ac495dSmrg #undef  TARGET_ADDRESS_COST
17836ac495dSmrg #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
17936ac495dSmrg 
18036ac495dSmrg #undef  TARGET_PROMOTE_PROTOTYPES
18136ac495dSmrg #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
18236ac495dSmrg #undef  TARGET_RETURN_IN_MEMORY
18336ac495dSmrg #define TARGET_RETURN_IN_MEMORY m32r_return_in_memory
18436ac495dSmrg 
18536ac495dSmrg #undef TARGET_FUNCTION_VALUE
18636ac495dSmrg #define TARGET_FUNCTION_VALUE m32r_function_value
18736ac495dSmrg #undef TARGET_LIBCALL_VALUE
18836ac495dSmrg #define TARGET_LIBCALL_VALUE m32r_libcall_value
18936ac495dSmrg #undef TARGET_FUNCTION_VALUE_REGNO_P
19036ac495dSmrg #define TARGET_FUNCTION_VALUE_REGNO_P m32r_function_value_regno_p
19136ac495dSmrg 
19236ac495dSmrg #undef  TARGET_SETUP_INCOMING_VARARGS
19336ac495dSmrg #define TARGET_SETUP_INCOMING_VARARGS m32r_setup_incoming_varargs
19436ac495dSmrg #undef  TARGET_MUST_PASS_IN_STACK
19536ac495dSmrg #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
19636ac495dSmrg #undef  TARGET_PASS_BY_REFERENCE
19736ac495dSmrg #define TARGET_PASS_BY_REFERENCE m32r_pass_by_reference
19836ac495dSmrg #undef  TARGET_ARG_PARTIAL_BYTES
19936ac495dSmrg #define TARGET_ARG_PARTIAL_BYTES m32r_arg_partial_bytes
20036ac495dSmrg #undef  TARGET_FUNCTION_ARG
20136ac495dSmrg #define TARGET_FUNCTION_ARG m32r_function_arg
20236ac495dSmrg #undef  TARGET_FUNCTION_ARG_ADVANCE
20336ac495dSmrg #define TARGET_FUNCTION_ARG_ADVANCE m32r_function_arg_advance
20436ac495dSmrg 
20536ac495dSmrg #undef TARGET_CAN_ELIMINATE
20636ac495dSmrg #define TARGET_CAN_ELIMINATE m32r_can_eliminate
20736ac495dSmrg 
20836ac495dSmrg #undef TARGET_CONDITIONAL_REGISTER_USAGE
20936ac495dSmrg #define TARGET_CONDITIONAL_REGISTER_USAGE m32r_conditional_register_usage
21036ac495dSmrg 
21136ac495dSmrg #undef TARGET_TRAMPOLINE_INIT
21236ac495dSmrg #define TARGET_TRAMPOLINE_INIT m32r_trampoline_init
21336ac495dSmrg 
21436ac495dSmrg #undef TARGET_LEGITIMATE_CONSTANT_P
21536ac495dSmrg #define TARGET_LEGITIMATE_CONSTANT_P m32r_legitimate_constant_p
21636ac495dSmrg 
217a2dc1f3fSmrg #undef TARGET_HARD_REGNO_MODE_OK
218a2dc1f3fSmrg #define TARGET_HARD_REGNO_MODE_OK m32r_hard_regno_mode_ok
219a2dc1f3fSmrg 
220a2dc1f3fSmrg #undef TARGET_MODES_TIEABLE_P
221a2dc1f3fSmrg #define TARGET_MODES_TIEABLE_P m32r_modes_tieable_p
222a2dc1f3fSmrg 
223a2dc1f3fSmrg #undef TARGET_CONSTANT_ALIGNMENT
224a2dc1f3fSmrg #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
225a2dc1f3fSmrg 
226a2dc1f3fSmrg #undef TARGET_STARTING_FRAME_OFFSET
227a2dc1f3fSmrg #define TARGET_STARTING_FRAME_OFFSET m32r_starting_frame_offset
228a2dc1f3fSmrg 
229c0a68be4Smrg #undef  TARGET_HAVE_SPECULATION_SAFE_VALUE
230c0a68be4Smrg #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
231c0a68be4Smrg 
23236ac495dSmrg struct gcc_target targetm = TARGET_INITIALIZER;
23336ac495dSmrg 
23436ac495dSmrg /* Called by m32r_option_override to initialize various things.  */
23536ac495dSmrg 
23636ac495dSmrg void
m32r_init(void)23736ac495dSmrg m32r_init (void)
23836ac495dSmrg {
23936ac495dSmrg   init_reg_tables ();
24036ac495dSmrg 
24136ac495dSmrg   /* Initialize array for TARGET_PRINT_OPERAND_PUNCT_VALID_P.  */
24236ac495dSmrg   memset (m32r_punct_chars, 0, sizeof (m32r_punct_chars));
24336ac495dSmrg   m32r_punct_chars['#'] = 1;
24436ac495dSmrg   m32r_punct_chars['@'] = 1; /* ??? no longer used */
24536ac495dSmrg 
24636ac495dSmrg   /* Provide default value if not specified.  */
24736ac495dSmrg   if (!global_options_set.x_g_switch_value)
24836ac495dSmrg     g_switch_value = SDATA_DEFAULT_SIZE;
24936ac495dSmrg }
25036ac495dSmrg 
25136ac495dSmrg static void
m32r_option_override(void)25236ac495dSmrg m32r_option_override (void)
25336ac495dSmrg {
25436ac495dSmrg   /* These need to be done at start up.
25536ac495dSmrg      It's convenient to do them here.  */
25636ac495dSmrg   m32r_init ();
25736ac495dSmrg   SUBTARGET_OVERRIDE_OPTIONS;
25836ac495dSmrg }
25936ac495dSmrg 
26036ac495dSmrg /* Vectors to keep interesting information about registers where it can easily
26136ac495dSmrg    be got.  We use to use the actual mode value as the bit number, but there
26236ac495dSmrg    is (or may be) more than 32 modes now.  Instead we use two tables: one
26336ac495dSmrg    indexed by hard register number, and one indexed by mode.  */
26436ac495dSmrg 
26536ac495dSmrg /* The purpose of m32r_mode_class is to shrink the range of modes so that
26636ac495dSmrg    they all fit (as bit numbers) in a 32-bit word (again).  Each real mode is
26736ac495dSmrg    mapped into one m32r_mode_class mode.  */
26836ac495dSmrg 
26936ac495dSmrg enum m32r_mode_class
27036ac495dSmrg {
27136ac495dSmrg   C_MODE,
27236ac495dSmrg   S_MODE, D_MODE, T_MODE, O_MODE,
27336ac495dSmrg   SF_MODE, DF_MODE, TF_MODE, OF_MODE, A_MODE
27436ac495dSmrg };
27536ac495dSmrg 
27636ac495dSmrg /* Modes for condition codes.  */
27736ac495dSmrg #define C_MODES (1 << (int) C_MODE)
27836ac495dSmrg 
27936ac495dSmrg /* Modes for single-word and smaller quantities.  */
28036ac495dSmrg #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
28136ac495dSmrg 
28236ac495dSmrg /* Modes for double-word and smaller quantities.  */
28336ac495dSmrg #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
28436ac495dSmrg 
28536ac495dSmrg /* Modes for quad-word and smaller quantities.  */
28636ac495dSmrg #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
28736ac495dSmrg 
28836ac495dSmrg /* Modes for accumulators.  */
28936ac495dSmrg #define A_MODES (1 << (int) A_MODE)
29036ac495dSmrg 
29136ac495dSmrg /* Value is 1 if register/mode pair is acceptable on arc.  */
29236ac495dSmrg 
293a2dc1f3fSmrg static const unsigned int m32r_hard_regno_modes[FIRST_PSEUDO_REGISTER] =
29436ac495dSmrg {
29536ac495dSmrg   T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
29636ac495dSmrg   T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, S_MODES, S_MODES, S_MODES,
29736ac495dSmrg   S_MODES, C_MODES, A_MODES, A_MODES
29836ac495dSmrg };
29936ac495dSmrg 
300a2dc1f3fSmrg static unsigned int m32r_mode_class [NUM_MACHINE_MODES];
30136ac495dSmrg 
30236ac495dSmrg enum reg_class m32r_regno_reg_class[FIRST_PSEUDO_REGISTER];
30336ac495dSmrg 
30436ac495dSmrg static void
init_reg_tables(void)30536ac495dSmrg init_reg_tables (void)
30636ac495dSmrg {
30736ac495dSmrg   int i;
30836ac495dSmrg 
30936ac495dSmrg   for (i = 0; i < NUM_MACHINE_MODES; i++)
31036ac495dSmrg     {
31136ac495dSmrg       machine_mode m = (machine_mode) i;
31236ac495dSmrg 
31336ac495dSmrg       switch (GET_MODE_CLASS (m))
31436ac495dSmrg 	{
31536ac495dSmrg 	case MODE_INT:
31636ac495dSmrg 	case MODE_PARTIAL_INT:
31736ac495dSmrg 	case MODE_COMPLEX_INT:
31836ac495dSmrg 	  if (GET_MODE_SIZE (m) <= 4)
31936ac495dSmrg 	    m32r_mode_class[i] = 1 << (int) S_MODE;
32036ac495dSmrg 	  else if (GET_MODE_SIZE (m) == 8)
32136ac495dSmrg 	    m32r_mode_class[i] = 1 << (int) D_MODE;
32236ac495dSmrg 	  else if (GET_MODE_SIZE (m) == 16)
32336ac495dSmrg 	    m32r_mode_class[i] = 1 << (int) T_MODE;
32436ac495dSmrg 	  else if (GET_MODE_SIZE (m) == 32)
32536ac495dSmrg 	    m32r_mode_class[i] = 1 << (int) O_MODE;
32636ac495dSmrg 	  else
32736ac495dSmrg 	    m32r_mode_class[i] = 0;
32836ac495dSmrg 	  break;
32936ac495dSmrg 	case MODE_FLOAT:
33036ac495dSmrg 	case MODE_COMPLEX_FLOAT:
33136ac495dSmrg 	  if (GET_MODE_SIZE (m) <= 4)
33236ac495dSmrg 	    m32r_mode_class[i] = 1 << (int) SF_MODE;
33336ac495dSmrg 	  else if (GET_MODE_SIZE (m) == 8)
33436ac495dSmrg 	    m32r_mode_class[i] = 1 << (int) DF_MODE;
33536ac495dSmrg 	  else if (GET_MODE_SIZE (m) == 16)
33636ac495dSmrg 	    m32r_mode_class[i] = 1 << (int) TF_MODE;
33736ac495dSmrg 	  else if (GET_MODE_SIZE (m) == 32)
33836ac495dSmrg 	    m32r_mode_class[i] = 1 << (int) OF_MODE;
33936ac495dSmrg 	  else
34036ac495dSmrg 	    m32r_mode_class[i] = 0;
34136ac495dSmrg 	  break;
34236ac495dSmrg 	case MODE_CC:
34336ac495dSmrg 	  m32r_mode_class[i] = 1 << (int) C_MODE;
34436ac495dSmrg 	  break;
34536ac495dSmrg 	default:
34636ac495dSmrg 	  m32r_mode_class[i] = 0;
34736ac495dSmrg 	  break;
34836ac495dSmrg 	}
34936ac495dSmrg     }
35036ac495dSmrg 
35136ac495dSmrg   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
35236ac495dSmrg     {
35336ac495dSmrg       if (GPR_P (i))
35436ac495dSmrg 	m32r_regno_reg_class[i] = GENERAL_REGS;
35536ac495dSmrg       else if (i == ARG_POINTER_REGNUM)
35636ac495dSmrg 	m32r_regno_reg_class[i] = GENERAL_REGS;
35736ac495dSmrg       else
35836ac495dSmrg 	m32r_regno_reg_class[i] = NO_REGS;
35936ac495dSmrg     }
36036ac495dSmrg }
36136ac495dSmrg 
36236ac495dSmrg /* M32R specific attribute support.
36336ac495dSmrg 
36436ac495dSmrg    interrupt - for interrupt functions
36536ac495dSmrg 
36636ac495dSmrg    model - select code model used to access object
36736ac495dSmrg 
36836ac495dSmrg 	small: addresses use 24 bits, use bl to make calls
36936ac495dSmrg 	medium: addresses use 32 bits, use bl to make calls
37036ac495dSmrg 	large: addresses use 32 bits, use seth/add3/jl to make calls
37136ac495dSmrg 
37236ac495dSmrg 	Grep for MODEL in m32r.h for more info.  */
37336ac495dSmrg 
37436ac495dSmrg static tree small_ident1;
37536ac495dSmrg static tree small_ident2;
37636ac495dSmrg static tree medium_ident1;
37736ac495dSmrg static tree medium_ident2;
37836ac495dSmrg static tree large_ident1;
37936ac495dSmrg static tree large_ident2;
38036ac495dSmrg 
38136ac495dSmrg static void
init_idents(void)38236ac495dSmrg init_idents (void)
38336ac495dSmrg {
38436ac495dSmrg   if (small_ident1 == 0)
38536ac495dSmrg     {
38636ac495dSmrg       small_ident1 = get_identifier ("small");
38736ac495dSmrg       small_ident2 = get_identifier ("__small__");
38836ac495dSmrg       medium_ident1 = get_identifier ("medium");
38936ac495dSmrg       medium_ident2 = get_identifier ("__medium__");
39036ac495dSmrg       large_ident1 = get_identifier ("large");
39136ac495dSmrg       large_ident2 = get_identifier ("__large__");
39236ac495dSmrg     }
39336ac495dSmrg }
39436ac495dSmrg 
39536ac495dSmrg /* Handle an "model" attribute; arguments as in
39636ac495dSmrg    struct attribute_spec.handler.  */
39736ac495dSmrg static tree
m32r_handle_model_attribute(tree * node ATTRIBUTE_UNUSED,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)39836ac495dSmrg m32r_handle_model_attribute (tree *node ATTRIBUTE_UNUSED, tree name,
39936ac495dSmrg 			     tree args, int flags ATTRIBUTE_UNUSED,
40036ac495dSmrg 			     bool *no_add_attrs)
40136ac495dSmrg {
40236ac495dSmrg   tree arg;
40336ac495dSmrg 
40436ac495dSmrg   init_idents ();
40536ac495dSmrg   arg = TREE_VALUE (args);
40636ac495dSmrg 
40736ac495dSmrg   if (arg != small_ident1
40836ac495dSmrg       && arg != small_ident2
40936ac495dSmrg       && arg != medium_ident1
41036ac495dSmrg       && arg != medium_ident2
41136ac495dSmrg       && arg != large_ident1
41236ac495dSmrg       && arg != large_ident2)
41336ac495dSmrg     {
41436ac495dSmrg       warning (OPT_Wattributes, "invalid argument of %qs attribute",
41536ac495dSmrg 	       IDENTIFIER_POINTER (name));
41636ac495dSmrg       *no_add_attrs = true;
41736ac495dSmrg     }
41836ac495dSmrg 
41936ac495dSmrg   return NULL_TREE;
42036ac495dSmrg }
42136ac495dSmrg 
42236ac495dSmrg static bool
m32r_attribute_identifier(const_tree name)42336ac495dSmrg m32r_attribute_identifier (const_tree name)
42436ac495dSmrg {
42536ac495dSmrg   return strcmp (IDENTIFIER_POINTER (name), "model") == 0
42636ac495dSmrg     ||   strcmp (IDENTIFIER_POINTER (name), "__model__") == 0;
42736ac495dSmrg }
42836ac495dSmrg 
42936ac495dSmrg /* Encode section information of DECL, which is either a VAR_DECL,
43036ac495dSmrg    FUNCTION_DECL, STRING_CST, CONSTRUCTOR, or ???.
43136ac495dSmrg 
43236ac495dSmrg    For the M32R we want to record:
43336ac495dSmrg 
43436ac495dSmrg    - whether the object lives in .sdata/.sbss.
43536ac495dSmrg    - what code model should be used to access the object
43636ac495dSmrg */
43736ac495dSmrg 
43836ac495dSmrg static void
m32r_encode_section_info(tree decl,rtx rtl,int first)43936ac495dSmrg m32r_encode_section_info (tree decl, rtx rtl, int first)
44036ac495dSmrg {
44136ac495dSmrg   int extra_flags = 0;
44236ac495dSmrg   tree model_attr;
44336ac495dSmrg   enum m32r_model model;
44436ac495dSmrg 
44536ac495dSmrg   default_encode_section_info (decl, rtl, first);
44636ac495dSmrg 
44736ac495dSmrg   if (!DECL_P (decl))
44836ac495dSmrg     return;
44936ac495dSmrg 
45036ac495dSmrg   model_attr = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
45136ac495dSmrg   if (model_attr)
45236ac495dSmrg     {
45336ac495dSmrg       tree id;
45436ac495dSmrg 
45536ac495dSmrg       init_idents ();
45636ac495dSmrg 
45736ac495dSmrg       id = TREE_VALUE (TREE_VALUE (model_attr));
45836ac495dSmrg 
45936ac495dSmrg       if (id == small_ident1 || id == small_ident2)
46036ac495dSmrg 	model = M32R_MODEL_SMALL;
46136ac495dSmrg       else if (id == medium_ident1 || id == medium_ident2)
46236ac495dSmrg 	model = M32R_MODEL_MEDIUM;
46336ac495dSmrg       else if (id == large_ident1 || id == large_ident2)
46436ac495dSmrg 	model = M32R_MODEL_LARGE;
46536ac495dSmrg       else
46636ac495dSmrg 	gcc_unreachable (); /* shouldn't happen */
46736ac495dSmrg     }
46836ac495dSmrg   else
46936ac495dSmrg     {
47036ac495dSmrg       if (TARGET_MODEL_SMALL)
47136ac495dSmrg 	model = M32R_MODEL_SMALL;
47236ac495dSmrg       else if (TARGET_MODEL_MEDIUM)
47336ac495dSmrg 	model = M32R_MODEL_MEDIUM;
47436ac495dSmrg       else if (TARGET_MODEL_LARGE)
47536ac495dSmrg 	model = M32R_MODEL_LARGE;
47636ac495dSmrg       else
47736ac495dSmrg 	gcc_unreachable (); /* shouldn't happen */
47836ac495dSmrg     }
47936ac495dSmrg   extra_flags |= model << SYMBOL_FLAG_MODEL_SHIFT;
48036ac495dSmrg 
48136ac495dSmrg   if (extra_flags)
48236ac495dSmrg     SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
48336ac495dSmrg }
48436ac495dSmrg 
48536ac495dSmrg /* Only mark the object as being small data area addressable if
48636ac495dSmrg    it hasn't been explicitly marked with a code model.
48736ac495dSmrg 
48836ac495dSmrg    The user can explicitly put an object in the small data area with the
48936ac495dSmrg    section attribute.  If the object is in sdata/sbss and marked with a
49036ac495dSmrg    code model do both [put the object in .sdata and mark it as being
49136ac495dSmrg    addressed with a specific code model - don't mark it as being addressed
49236ac495dSmrg    with an SDA reloc though].  This is ok and might be useful at times.  If
49336ac495dSmrg    the object doesn't fit the linker will give an error.  */
49436ac495dSmrg 
49536ac495dSmrg static bool
m32r_in_small_data_p(const_tree decl)49636ac495dSmrg m32r_in_small_data_p (const_tree decl)
49736ac495dSmrg {
49836ac495dSmrg   const char *section;
49936ac495dSmrg 
50036ac495dSmrg   if (TREE_CODE (decl) != VAR_DECL)
50136ac495dSmrg     return false;
50236ac495dSmrg 
50336ac495dSmrg   if (lookup_attribute ("model", DECL_ATTRIBUTES (decl)))
50436ac495dSmrg     return false;
50536ac495dSmrg 
50636ac495dSmrg   section = DECL_SECTION_NAME (decl);
50736ac495dSmrg   if (section)
50836ac495dSmrg     {
50936ac495dSmrg       if (strcmp (section, ".sdata") == 0 || strcmp (section, ".sbss") == 0)
51036ac495dSmrg 	return true;
51136ac495dSmrg     }
51236ac495dSmrg   else
51336ac495dSmrg     {
51436ac495dSmrg       if (! TREE_READONLY (decl) && ! TARGET_SDATA_NONE)
51536ac495dSmrg 	{
51636ac495dSmrg 	  int size = int_size_in_bytes (TREE_TYPE (decl));
51736ac495dSmrg 
51836ac495dSmrg 	  if (size > 0 && size <= g_switch_value)
51936ac495dSmrg 	    return true;
52036ac495dSmrg 	}
52136ac495dSmrg     }
52236ac495dSmrg 
52336ac495dSmrg   return false;
52436ac495dSmrg }
52536ac495dSmrg 
52636ac495dSmrg /* Do anything needed before RTL is emitted for each function.  */
52736ac495dSmrg 
52836ac495dSmrg void
m32r_init_expanders(void)52936ac495dSmrg m32r_init_expanders (void)
53036ac495dSmrg {
53136ac495dSmrg   /* ??? At one point there was code here.  The function is left in
53236ac495dSmrg      to make it easy to experiment.  */
53336ac495dSmrg }
53436ac495dSmrg 
53536ac495dSmrg int
call_operand(rtx op,machine_mode mode)53636ac495dSmrg call_operand (rtx op, machine_mode mode)
53736ac495dSmrg {
53836ac495dSmrg   if (!MEM_P (op))
53936ac495dSmrg     return 0;
54036ac495dSmrg   op = XEXP (op, 0);
54136ac495dSmrg   return call_address_operand (op, mode);
54236ac495dSmrg }
54336ac495dSmrg 
54436ac495dSmrg /* Return 1 if OP is a reference to an object in .sdata/.sbss.  */
54536ac495dSmrg 
54636ac495dSmrg int
small_data_operand(rtx op,machine_mode mode ATTRIBUTE_UNUSED)54736ac495dSmrg small_data_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
54836ac495dSmrg {
54936ac495dSmrg   if (! TARGET_SDATA_USE)
55036ac495dSmrg     return 0;
55136ac495dSmrg 
55236ac495dSmrg   if (GET_CODE (op) == SYMBOL_REF)
55336ac495dSmrg     return SYMBOL_REF_SMALL_P (op);
55436ac495dSmrg 
55536ac495dSmrg   if (GET_CODE (op) == CONST
55636ac495dSmrg       && GET_CODE (XEXP (op, 0)) == PLUS
55736ac495dSmrg       && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
55836ac495dSmrg       && satisfies_constraint_J (XEXP (XEXP (op, 0), 1)))
55936ac495dSmrg     return SYMBOL_REF_SMALL_P (XEXP (XEXP (op, 0), 0));
56036ac495dSmrg 
56136ac495dSmrg   return 0;
56236ac495dSmrg }
56336ac495dSmrg 
56436ac495dSmrg /* Return 1 if OP is a symbol that can use 24-bit addressing.  */
56536ac495dSmrg 
56636ac495dSmrg int
addr24_operand(rtx op,machine_mode mode ATTRIBUTE_UNUSED)56736ac495dSmrg addr24_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
56836ac495dSmrg {
56936ac495dSmrg   rtx sym;
57036ac495dSmrg 
57136ac495dSmrg   if (flag_pic)
57236ac495dSmrg     return 0;
57336ac495dSmrg 
57436ac495dSmrg   if (GET_CODE (op) == LABEL_REF)
57536ac495dSmrg     return TARGET_ADDR24;
57636ac495dSmrg 
57736ac495dSmrg   if (GET_CODE (op) == SYMBOL_REF)
57836ac495dSmrg     sym = op;
57936ac495dSmrg   else if (GET_CODE (op) == CONST
58036ac495dSmrg 	   && GET_CODE (XEXP (op, 0)) == PLUS
58136ac495dSmrg 	   && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
58236ac495dSmrg 	   && satisfies_constraint_M (XEXP (XEXP (op, 0), 1)))
58336ac495dSmrg     sym = XEXP (XEXP (op, 0), 0);
58436ac495dSmrg   else
58536ac495dSmrg     return 0;
58636ac495dSmrg 
58736ac495dSmrg   if (SYMBOL_REF_MODEL (sym) == M32R_MODEL_SMALL)
58836ac495dSmrg     return 1;
58936ac495dSmrg 
59036ac495dSmrg   if (TARGET_ADDR24
59136ac495dSmrg       && (CONSTANT_POOL_ADDRESS_P (sym)
59236ac495dSmrg 	  || LIT_NAME_P (XSTR (sym, 0))))
59336ac495dSmrg     return 1;
59436ac495dSmrg 
59536ac495dSmrg   return 0;
59636ac495dSmrg }
59736ac495dSmrg 
59836ac495dSmrg /* Return 1 if OP is a symbol that needs 32-bit addressing.  */
59936ac495dSmrg 
60036ac495dSmrg int
addr32_operand(rtx op,machine_mode mode)60136ac495dSmrg addr32_operand (rtx op, machine_mode mode)
60236ac495dSmrg {
60336ac495dSmrg   rtx sym;
60436ac495dSmrg 
60536ac495dSmrg   if (GET_CODE (op) == LABEL_REF)
60636ac495dSmrg     return TARGET_ADDR32;
60736ac495dSmrg 
60836ac495dSmrg   if (GET_CODE (op) == SYMBOL_REF)
60936ac495dSmrg     sym = op;
61036ac495dSmrg   else if (GET_CODE (op) == CONST
61136ac495dSmrg 	   && GET_CODE (XEXP (op, 0)) == PLUS
61236ac495dSmrg 	   && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
61336ac495dSmrg 	   && CONST_INT_P (XEXP (XEXP (op, 0), 1))
61436ac495dSmrg 	   && ! flag_pic)
61536ac495dSmrg     sym = XEXP (XEXP (op, 0), 0);
61636ac495dSmrg   else
61736ac495dSmrg     return 0;
61836ac495dSmrg 
61936ac495dSmrg   return (! addr24_operand (sym, mode)
62036ac495dSmrg 	  && ! small_data_operand (sym, mode));
62136ac495dSmrg }
62236ac495dSmrg 
62336ac495dSmrg /* Return 1 if OP is a function that can be called with the `bl' insn.  */
62436ac495dSmrg 
62536ac495dSmrg int
call26_operand(rtx op,machine_mode mode ATTRIBUTE_UNUSED)62636ac495dSmrg call26_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
62736ac495dSmrg {
62836ac495dSmrg   if (flag_pic)
62936ac495dSmrg     return 1;
63036ac495dSmrg 
63136ac495dSmrg   if (GET_CODE (op) == SYMBOL_REF)
63236ac495dSmrg     return SYMBOL_REF_MODEL (op) != M32R_MODEL_LARGE;
63336ac495dSmrg 
63436ac495dSmrg   return TARGET_CALL26;
63536ac495dSmrg }
63636ac495dSmrg 
63736ac495dSmrg /* Return 1 if OP is a DImode const we want to handle inline.
63836ac495dSmrg    This must match the code in the movdi pattern.
63936ac495dSmrg    It is used by the 'G' constraint.  */
64036ac495dSmrg 
64136ac495dSmrg int
easy_di_const(rtx op)64236ac495dSmrg easy_di_const (rtx op)
64336ac495dSmrg {
64436ac495dSmrg   rtx high_rtx, low_rtx;
64536ac495dSmrg   HOST_WIDE_INT high, low;
64636ac495dSmrg 
64736ac495dSmrg   split_double (op, &high_rtx, &low_rtx);
64836ac495dSmrg   high = INTVAL (high_rtx);
64936ac495dSmrg   low = INTVAL (low_rtx);
65036ac495dSmrg   /* Pick constants loadable with 2 16-bit `ldi' insns.  */
65136ac495dSmrg   if (high >= -128 && high <= 127
65236ac495dSmrg       && low >= -128 && low <= 127)
65336ac495dSmrg     return 1;
65436ac495dSmrg   return 0;
65536ac495dSmrg }
65636ac495dSmrg 
65736ac495dSmrg /* Return 1 if OP is a DFmode const we want to handle inline.
65836ac495dSmrg    This must match the code in the movdf pattern.
65936ac495dSmrg    It is used by the 'H' constraint.  */
66036ac495dSmrg 
66136ac495dSmrg int
easy_df_const(rtx op)66236ac495dSmrg easy_df_const (rtx op)
66336ac495dSmrg {
66436ac495dSmrg   long l[2];
66536ac495dSmrg 
66636ac495dSmrg   REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l);
66736ac495dSmrg   if (l[0] == 0 && l[1] == 0)
66836ac495dSmrg     return 1;
66936ac495dSmrg   if ((l[0] & 0xffff) == 0 && l[1] == 0)
67036ac495dSmrg     return 1;
67136ac495dSmrg   return 0;
67236ac495dSmrg }
67336ac495dSmrg 
67436ac495dSmrg /* Return 1 if OP is (mem (reg ...)).
67536ac495dSmrg    This is used in insn length calcs.  */
67636ac495dSmrg 
67736ac495dSmrg int
memreg_operand(rtx op,machine_mode mode ATTRIBUTE_UNUSED)67836ac495dSmrg memreg_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
67936ac495dSmrg {
68036ac495dSmrg   return MEM_P (op) && REG_P (XEXP (op, 0));
68136ac495dSmrg }
68236ac495dSmrg 
683*8feb0f0bSmrg /* Return nonzero if ARG must be passed by indirect reference.  */
68436ac495dSmrg 
68536ac495dSmrg static bool
m32r_pass_by_reference(cumulative_args_t,const function_arg_info & arg)686*8feb0f0bSmrg m32r_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
68736ac495dSmrg {
688*8feb0f0bSmrg   int size = arg.type_size_in_bytes ();
68936ac495dSmrg   return (size < 0 || size > 8);
69036ac495dSmrg }
69136ac495dSmrg 
69236ac495dSmrg /* Comparisons.  */
69336ac495dSmrg 
69436ac495dSmrg /* X and Y are two things to compare using CODE.  Emit the compare insn and
69536ac495dSmrg    return the rtx for compare [arg0 of the if_then_else].
69636ac495dSmrg    If need_compare is true then the comparison insn must be generated, rather
69736ac495dSmrg    than being subsumed into the following branch instruction.  */
69836ac495dSmrg 
69936ac495dSmrg rtx
gen_compare(enum rtx_code code,rtx x,rtx y,int need_compare)70036ac495dSmrg gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
70136ac495dSmrg {
70236ac495dSmrg   enum rtx_code compare_code;
70336ac495dSmrg   enum rtx_code branch_code;
70436ac495dSmrg   rtx cc_reg = gen_rtx_REG (CCmode, CARRY_REGNUM);
70536ac495dSmrg   int must_swap = 0;
70636ac495dSmrg 
70736ac495dSmrg   switch (code)
70836ac495dSmrg     {
70936ac495dSmrg     case EQ:  compare_code = EQ;  branch_code = NE; break;
71036ac495dSmrg     case NE:  compare_code = EQ;  branch_code = EQ; break;
71136ac495dSmrg     case LT:  compare_code = LT;  branch_code = NE; break;
71236ac495dSmrg     case LE:  compare_code = LT;  branch_code = EQ; must_swap = 1; break;
71336ac495dSmrg     case GT:  compare_code = LT;  branch_code = NE; must_swap = 1; break;
71436ac495dSmrg     case GE:  compare_code = LT;  branch_code = EQ; break;
71536ac495dSmrg     case LTU: compare_code = LTU; branch_code = NE; break;
71636ac495dSmrg     case LEU: compare_code = LTU; branch_code = EQ; must_swap = 1; break;
71736ac495dSmrg     case GTU: compare_code = LTU; branch_code = NE; must_swap = 1; break;
71836ac495dSmrg     case GEU: compare_code = LTU; branch_code = EQ; break;
71936ac495dSmrg 
72036ac495dSmrg     default:
72136ac495dSmrg       gcc_unreachable ();
72236ac495dSmrg     }
72336ac495dSmrg 
72436ac495dSmrg   if (need_compare)
72536ac495dSmrg     {
72636ac495dSmrg       switch (compare_code)
72736ac495dSmrg 	{
72836ac495dSmrg 	case EQ:
72936ac495dSmrg 	  if (satisfies_constraint_P (y)		/* Reg equal to small const.  */
73036ac495dSmrg 	      && y != const0_rtx)
73136ac495dSmrg 	    {
73236ac495dSmrg 	      rtx tmp = gen_reg_rtx (SImode);
73336ac495dSmrg 
73436ac495dSmrg 	      emit_insn (gen_addsi3 (tmp, x, GEN_INT (-INTVAL (y))));
73536ac495dSmrg 	      x = tmp;
73636ac495dSmrg 	      y = const0_rtx;
73736ac495dSmrg 	    }
73836ac495dSmrg 	  else if (CONSTANT_P (y))			/* Reg equal to const.  */
73936ac495dSmrg 	    {
74036ac495dSmrg 	      rtx tmp = force_reg (GET_MODE (x), y);
74136ac495dSmrg 	      y = tmp;
74236ac495dSmrg 	    }
74336ac495dSmrg 
74436ac495dSmrg 	  if (register_operand (y, SImode) 		/* Reg equal to reg.  */
74536ac495dSmrg 	      || y == const0_rtx) 	   		/* Reg equal to zero.  */
74636ac495dSmrg 	    {
74736ac495dSmrg 	      emit_insn (gen_cmp_eqsi_insn (x, y));
74836ac495dSmrg 
74936ac495dSmrg 	      return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
75036ac495dSmrg 	    }
75136ac495dSmrg 	  break;
75236ac495dSmrg 
75336ac495dSmrg 	case LT:
75436ac495dSmrg 	  if (register_operand (y, SImode)
75536ac495dSmrg 	      || satisfies_constraint_P (y))
75636ac495dSmrg 	    {
75736ac495dSmrg 	      rtx tmp = gen_reg_rtx (SImode);	      /* Reg compared to reg.  */
75836ac495dSmrg 
75936ac495dSmrg 	      switch (code)
76036ac495dSmrg 		{
76136ac495dSmrg 		case LT:
76236ac495dSmrg 		  emit_insn (gen_cmp_ltsi_insn (x, y));
76336ac495dSmrg 		  code = EQ;
76436ac495dSmrg 		  break;
76536ac495dSmrg 		case LE:
76636ac495dSmrg 		  if (y == const0_rtx)
76736ac495dSmrg 		    tmp = const1_rtx;
76836ac495dSmrg 		  else
76936ac495dSmrg 		    emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
77036ac495dSmrg 		  emit_insn (gen_cmp_ltsi_insn (x, tmp));
77136ac495dSmrg 		  code = EQ;
77236ac495dSmrg 		  break;
77336ac495dSmrg 		case GT:
77436ac495dSmrg 		  if (CONST_INT_P (y))
77536ac495dSmrg 		    tmp = gen_rtx_PLUS (SImode, y, const1_rtx);
77636ac495dSmrg 		  else
77736ac495dSmrg 		    emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
77836ac495dSmrg 		  emit_insn (gen_cmp_ltsi_insn (x, tmp));
77936ac495dSmrg 		  code = NE;
78036ac495dSmrg 		  break;
78136ac495dSmrg 		case GE:
78236ac495dSmrg 		  emit_insn (gen_cmp_ltsi_insn (x, y));
78336ac495dSmrg 		  code = NE;
78436ac495dSmrg 		  break;
78536ac495dSmrg 		default:
78636ac495dSmrg 		  gcc_unreachable ();
78736ac495dSmrg 		}
78836ac495dSmrg 
78936ac495dSmrg 	      return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
79036ac495dSmrg 	    }
79136ac495dSmrg 	  break;
79236ac495dSmrg 
79336ac495dSmrg 	case LTU:
79436ac495dSmrg 	  if (register_operand (y, SImode)
79536ac495dSmrg 	      || satisfies_constraint_P (y))
79636ac495dSmrg 	    {
79736ac495dSmrg 	      rtx tmp = gen_reg_rtx (SImode);	      /* Reg (unsigned) compared to reg.  */
79836ac495dSmrg 
79936ac495dSmrg 	      switch (code)
80036ac495dSmrg 		{
80136ac495dSmrg 		case LTU:
80236ac495dSmrg 		  emit_insn (gen_cmp_ltusi_insn (x, y));
80336ac495dSmrg 		  code = EQ;
80436ac495dSmrg 		  break;
80536ac495dSmrg 		case LEU:
80636ac495dSmrg 		  if (y == const0_rtx)
80736ac495dSmrg 		    tmp = const1_rtx;
80836ac495dSmrg 		  else
80936ac495dSmrg 		    emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
81036ac495dSmrg 		  emit_insn (gen_cmp_ltusi_insn (x, tmp));
81136ac495dSmrg 		  code = EQ;
81236ac495dSmrg 		  break;
81336ac495dSmrg 		case GTU:
81436ac495dSmrg 		  if (CONST_INT_P (y))
81536ac495dSmrg 		    tmp = gen_rtx_PLUS (SImode, y, const1_rtx);
81636ac495dSmrg 		  else
81736ac495dSmrg 		    emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
81836ac495dSmrg 		  emit_insn (gen_cmp_ltusi_insn (x, tmp));
81936ac495dSmrg 		  code = NE;
82036ac495dSmrg 		  break;
82136ac495dSmrg 		case GEU:
82236ac495dSmrg 		  emit_insn (gen_cmp_ltusi_insn (x, y));
82336ac495dSmrg 		  code = NE;
82436ac495dSmrg 		  break;
82536ac495dSmrg 		default:
82636ac495dSmrg 		  gcc_unreachable ();
82736ac495dSmrg 		}
82836ac495dSmrg 
82936ac495dSmrg 	      return gen_rtx_fmt_ee (code, CCmode, cc_reg, const0_rtx);
83036ac495dSmrg 	    }
83136ac495dSmrg 	  break;
83236ac495dSmrg 
83336ac495dSmrg 	default:
83436ac495dSmrg 	  gcc_unreachable ();
83536ac495dSmrg 	}
83636ac495dSmrg     }
83736ac495dSmrg   else
83836ac495dSmrg     {
83936ac495dSmrg       /* Reg/reg equal comparison.  */
84036ac495dSmrg       if (compare_code == EQ
84136ac495dSmrg 	  && register_operand (y, SImode))
84236ac495dSmrg 	return gen_rtx_fmt_ee (code, CCmode, x, y);
84336ac495dSmrg 
84436ac495dSmrg       /* Reg/zero signed comparison.  */
84536ac495dSmrg       if ((compare_code == EQ || compare_code == LT)
84636ac495dSmrg 	  && y == const0_rtx)
84736ac495dSmrg 	return gen_rtx_fmt_ee (code, CCmode, x, y);
84836ac495dSmrg 
84936ac495dSmrg       /* Reg/smallconst equal comparison.  */
85036ac495dSmrg       if (compare_code == EQ
85136ac495dSmrg 	  && satisfies_constraint_P (y))
85236ac495dSmrg 	{
85336ac495dSmrg 	  rtx tmp = gen_reg_rtx (SImode);
85436ac495dSmrg 
85536ac495dSmrg 	  emit_insn (gen_addsi3 (tmp, x, GEN_INT (-INTVAL (y))));
85636ac495dSmrg 	  return gen_rtx_fmt_ee (code, CCmode, tmp, const0_rtx);
85736ac495dSmrg 	}
85836ac495dSmrg 
85936ac495dSmrg       /* Reg/const equal comparison.  */
86036ac495dSmrg       if (compare_code == EQ
86136ac495dSmrg 	  && CONSTANT_P (y))
86236ac495dSmrg 	{
86336ac495dSmrg 	  rtx tmp = force_reg (GET_MODE (x), y);
86436ac495dSmrg 
86536ac495dSmrg 	  return gen_rtx_fmt_ee (code, CCmode, x, tmp);
86636ac495dSmrg 	}
86736ac495dSmrg     }
86836ac495dSmrg 
86936ac495dSmrg   if (CONSTANT_P (y))
87036ac495dSmrg     {
87136ac495dSmrg       if (must_swap)
87236ac495dSmrg 	y = force_reg (GET_MODE (x), y);
87336ac495dSmrg       else
87436ac495dSmrg 	{
87536ac495dSmrg 	  int ok_const = reg_or_int16_operand (y, GET_MODE (y));
87636ac495dSmrg 
87736ac495dSmrg 	  if (! ok_const)
87836ac495dSmrg 	    y = force_reg (GET_MODE (x), y);
87936ac495dSmrg 	}
88036ac495dSmrg     }
88136ac495dSmrg 
88236ac495dSmrg   switch (compare_code)
88336ac495dSmrg     {
88436ac495dSmrg     case EQ :
88536ac495dSmrg       emit_insn (gen_cmp_eqsi_insn (must_swap ? y : x, must_swap ? x : y));
88636ac495dSmrg       break;
88736ac495dSmrg     case LT :
88836ac495dSmrg       emit_insn (gen_cmp_ltsi_insn (must_swap ? y : x, must_swap ? x : y));
88936ac495dSmrg       break;
89036ac495dSmrg     case LTU :
89136ac495dSmrg       emit_insn (gen_cmp_ltusi_insn (must_swap ? y : x, must_swap ? x : y));
89236ac495dSmrg       break;
89336ac495dSmrg 
89436ac495dSmrg     default:
89536ac495dSmrg       gcc_unreachable ();
89636ac495dSmrg     }
89736ac495dSmrg 
89836ac495dSmrg   return gen_rtx_fmt_ee (branch_code, VOIDmode, cc_reg, CONST0_RTX (CCmode));
89936ac495dSmrg }
90036ac495dSmrg 
90136ac495dSmrg bool
gen_cond_store(enum rtx_code code,rtx op0,rtx op1,rtx op2)90236ac495dSmrg gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2)
90336ac495dSmrg {
90436ac495dSmrg   machine_mode mode = GET_MODE (op0);
90536ac495dSmrg 
90636ac495dSmrg   gcc_assert (mode == SImode);
90736ac495dSmrg   switch (code)
90836ac495dSmrg     {
90936ac495dSmrg     case EQ:
91036ac495dSmrg       if (!register_operand (op1, mode))
91136ac495dSmrg 	op1 = force_reg (mode, op1);
91236ac495dSmrg 
91336ac495dSmrg       if (TARGET_M32RX || TARGET_M32R2)
91436ac495dSmrg 	{
91536ac495dSmrg 	  if (!reg_or_zero_operand (op2, mode))
91636ac495dSmrg 	    op2 = force_reg (mode, op2);
91736ac495dSmrg 
91836ac495dSmrg 	  emit_insn (gen_seq_insn_m32rx (op0, op1, op2));
91936ac495dSmrg 	  return true;
92036ac495dSmrg 	}
92136ac495dSmrg       if (CONST_INT_P (op2) && INTVAL (op2) == 0)
92236ac495dSmrg 	{
92336ac495dSmrg 	  emit_insn (gen_seq_zero_insn (op0, op1));
92436ac495dSmrg 	  return true;
92536ac495dSmrg 	}
92636ac495dSmrg 
92736ac495dSmrg       if (!reg_or_eq_int16_operand (op2, mode))
92836ac495dSmrg 	op2 = force_reg (mode, op2);
92936ac495dSmrg 
93036ac495dSmrg       emit_insn (gen_seq_insn (op0, op1, op2));
93136ac495dSmrg       return true;
93236ac495dSmrg 
93336ac495dSmrg     case NE:
93436ac495dSmrg       if (!CONST_INT_P (op2)
93536ac495dSmrg 	  || (INTVAL (op2) != 0 && satisfies_constraint_K (op2)))
93636ac495dSmrg 	{
93736ac495dSmrg 	  rtx reg;
93836ac495dSmrg 
93936ac495dSmrg 	  if (reload_completed || reload_in_progress)
94036ac495dSmrg 	    return false;
94136ac495dSmrg 
94236ac495dSmrg 	  reg = gen_reg_rtx (SImode);
94336ac495dSmrg 	  emit_insn (gen_xorsi3 (reg, op1, op2));
94436ac495dSmrg 	  op1 = reg;
94536ac495dSmrg 
94636ac495dSmrg 	  if (!register_operand (op1, mode))
94736ac495dSmrg 	    op1 = force_reg (mode, op1);
94836ac495dSmrg 
94936ac495dSmrg 	  emit_insn (gen_sne_zero_insn (op0, op1));
95036ac495dSmrg 	  return true;
95136ac495dSmrg 	}
95236ac495dSmrg       return false;
95336ac495dSmrg 
95436ac495dSmrg     case LT:
95536ac495dSmrg     case GT:
95636ac495dSmrg       if (code == GT)
95736ac495dSmrg 	{
95836ac495dSmrg 	  rtx tmp = op2;
95936ac495dSmrg 	  op2 = op1;
96036ac495dSmrg 	  op1 = tmp;
96136ac495dSmrg 	  code = LT;
96236ac495dSmrg 	}
96336ac495dSmrg 
96436ac495dSmrg       if (!register_operand (op1, mode))
96536ac495dSmrg 	op1 = force_reg (mode, op1);
96636ac495dSmrg 
96736ac495dSmrg       if (!reg_or_int16_operand (op2, mode))
96836ac495dSmrg 	op2 = force_reg (mode, op2);
96936ac495dSmrg 
97036ac495dSmrg       emit_insn (gen_slt_insn (op0, op1, op2));
97136ac495dSmrg       return true;
97236ac495dSmrg 
97336ac495dSmrg     case LTU:
97436ac495dSmrg     case GTU:
97536ac495dSmrg       if (code == GTU)
97636ac495dSmrg 	{
97736ac495dSmrg 	  rtx tmp = op2;
97836ac495dSmrg 	  op2 = op1;
97936ac495dSmrg 	  op1 = tmp;
98036ac495dSmrg 	  code = LTU;
98136ac495dSmrg 	}
98236ac495dSmrg 
98336ac495dSmrg       if (!register_operand (op1, mode))
98436ac495dSmrg 	op1 = force_reg (mode, op1);
98536ac495dSmrg 
98636ac495dSmrg       if (!reg_or_int16_operand (op2, mode))
98736ac495dSmrg 	op2 = force_reg (mode, op2);
98836ac495dSmrg 
98936ac495dSmrg       emit_insn (gen_sltu_insn (op0, op1, op2));
99036ac495dSmrg       return true;
99136ac495dSmrg 
99236ac495dSmrg     case GE:
99336ac495dSmrg     case GEU:
99436ac495dSmrg       if (!register_operand (op1, mode))
99536ac495dSmrg 	op1 = force_reg (mode, op1);
99636ac495dSmrg 
99736ac495dSmrg       if (!reg_or_int16_operand (op2, mode))
99836ac495dSmrg 	op2 = force_reg (mode, op2);
99936ac495dSmrg 
100036ac495dSmrg       if (code == GE)
100136ac495dSmrg 	emit_insn (gen_sge_insn (op0, op1, op2));
100236ac495dSmrg       else
100336ac495dSmrg 	emit_insn (gen_sgeu_insn (op0, op1, op2));
100436ac495dSmrg       return true;
100536ac495dSmrg 
100636ac495dSmrg     case LE:
100736ac495dSmrg     case LEU:
100836ac495dSmrg       if (!register_operand (op1, mode))
100936ac495dSmrg 	op1 = force_reg (mode, op1);
101036ac495dSmrg 
101136ac495dSmrg       if (CONST_INT_P (op2))
101236ac495dSmrg 	{
101336ac495dSmrg 	  HOST_WIDE_INT value = INTVAL (op2);
101436ac495dSmrg 	  if (value >= 2147483647)
101536ac495dSmrg 	    {
101636ac495dSmrg 	      emit_move_insn (op0, const1_rtx);
101736ac495dSmrg 	      return true;
101836ac495dSmrg 	    }
101936ac495dSmrg 
102036ac495dSmrg 	  op2 = GEN_INT (value + 1);
102136ac495dSmrg 	  if (value < -32768 || value >= 32767)
102236ac495dSmrg 	    op2 = force_reg (mode, op2);
102336ac495dSmrg 
102436ac495dSmrg           if (code == LEU)
102536ac495dSmrg 	    emit_insn (gen_sltu_insn (op0, op1, op2));
102636ac495dSmrg 	  else
102736ac495dSmrg 	    emit_insn (gen_slt_insn (op0, op1, op2));
102836ac495dSmrg 	  return true;
102936ac495dSmrg 	}
103036ac495dSmrg 
103136ac495dSmrg       if (!register_operand (op2, mode))
103236ac495dSmrg 	op2 = force_reg (mode, op2);
103336ac495dSmrg 
103436ac495dSmrg       if (code == LEU)
103536ac495dSmrg         emit_insn (gen_sleu_insn (op0, op1, op2));
103636ac495dSmrg       else
103736ac495dSmrg         emit_insn (gen_sle_insn (op0, op1, op2));
103836ac495dSmrg       return true;
103936ac495dSmrg 
104036ac495dSmrg     default:
104136ac495dSmrg       gcc_unreachable ();
104236ac495dSmrg     }
104336ac495dSmrg }
104436ac495dSmrg 
104536ac495dSmrg 
104636ac495dSmrg /* Split a 2 word move (DI or DF) into component parts.  */
104736ac495dSmrg 
104836ac495dSmrg rtx
gen_split_move_double(rtx operands[])104936ac495dSmrg gen_split_move_double (rtx operands[])
105036ac495dSmrg {
105136ac495dSmrg   machine_mode mode = GET_MODE (operands[0]);
105236ac495dSmrg   rtx dest = operands[0];
105336ac495dSmrg   rtx src  = operands[1];
105436ac495dSmrg   rtx val;
105536ac495dSmrg 
105636ac495dSmrg   /* We might have (SUBREG (MEM)) here, so just get rid of the
105736ac495dSmrg      subregs to make this code simpler.  It is safe to call
105836ac495dSmrg      alter_subreg any time after reload.  */
105936ac495dSmrg   if (GET_CODE (dest) == SUBREG)
106036ac495dSmrg     alter_subreg (&dest, true);
106136ac495dSmrg   if (GET_CODE (src) == SUBREG)
106236ac495dSmrg     alter_subreg (&src, true);
106336ac495dSmrg 
106436ac495dSmrg   start_sequence ();
106536ac495dSmrg   if (REG_P (dest))
106636ac495dSmrg     {
106736ac495dSmrg       int dregno = REGNO (dest);
106836ac495dSmrg 
106936ac495dSmrg       /* Reg = reg.  */
107036ac495dSmrg       if (REG_P (src))
107136ac495dSmrg 	{
107236ac495dSmrg 	  int sregno = REGNO (src);
107336ac495dSmrg 
107436ac495dSmrg 	  int reverse = (dregno == sregno + 1);
107536ac495dSmrg 
107636ac495dSmrg 	  /* We normally copy the low-numbered register first.  However, if
107736ac495dSmrg 	     the first register operand 0 is the same as the second register of
107836ac495dSmrg 	     operand 1, we must copy in the opposite order.  */
107936ac495dSmrg 	  emit_insn (gen_rtx_SET (operand_subword (dest, reverse, TRUE, mode),
108036ac495dSmrg 				  operand_subword (src,  reverse, TRUE, mode)));
108136ac495dSmrg 
108236ac495dSmrg 	  emit_insn (gen_rtx_SET (operand_subword (dest, !reverse, TRUE, mode),
108336ac495dSmrg 				  operand_subword (src,  !reverse, TRUE, mode)));
108436ac495dSmrg 	}
108536ac495dSmrg 
108636ac495dSmrg       /* Reg = constant.  */
108736ac495dSmrg       else if (CONST_INT_P (src) || GET_CODE (src) == CONST_DOUBLE)
108836ac495dSmrg 	{
108936ac495dSmrg 	  rtx words[2];
109036ac495dSmrg 	  split_double (src, &words[0], &words[1]);
109136ac495dSmrg 	  emit_insn (gen_rtx_SET (operand_subword (dest, 0, TRUE, mode),
109236ac495dSmrg 				  words[0]));
109336ac495dSmrg 
109436ac495dSmrg 	  emit_insn (gen_rtx_SET (operand_subword (dest, 1, TRUE, mode),
109536ac495dSmrg 				  words[1]));
109636ac495dSmrg 	}
109736ac495dSmrg 
109836ac495dSmrg       /* Reg = mem.  */
109936ac495dSmrg       else if (MEM_P (src))
110036ac495dSmrg 	{
110136ac495dSmrg 	  /* If the high-address word is used in the address, we must load it
110236ac495dSmrg 	     last.  Otherwise, load it first.  */
110336ac495dSmrg 	  int reverse = refers_to_regno_p (dregno, XEXP (src, 0));
110436ac495dSmrg 
110536ac495dSmrg 	  /* We used to optimize loads from single registers as
110636ac495dSmrg 
110736ac495dSmrg 		ld r1,r3+; ld r2,r3
110836ac495dSmrg 
110936ac495dSmrg 	     if r3 were not used subsequently.  However, the REG_NOTES aren't
111036ac495dSmrg 	     propagated correctly by the reload phase, and it can cause bad
111136ac495dSmrg 	     code to be generated.  We could still try:
111236ac495dSmrg 
111336ac495dSmrg 		ld r1,r3+; ld r2,r3; addi r3,-4
111436ac495dSmrg 
111536ac495dSmrg 	     which saves 2 bytes and doesn't force longword alignment.  */
111636ac495dSmrg 	  emit_insn (gen_rtx_SET (operand_subword (dest, reverse, TRUE, mode),
111736ac495dSmrg 				  adjust_address (src, SImode,
111836ac495dSmrg 						  reverse * UNITS_PER_WORD)));
111936ac495dSmrg 
112036ac495dSmrg 	  emit_insn (gen_rtx_SET (operand_subword (dest, !reverse, TRUE, mode),
112136ac495dSmrg 				  adjust_address (src, SImode,
112236ac495dSmrg 						  !reverse * UNITS_PER_WORD)));
112336ac495dSmrg 	}
112436ac495dSmrg       else
112536ac495dSmrg 	gcc_unreachable ();
112636ac495dSmrg     }
112736ac495dSmrg 
112836ac495dSmrg   /* Mem = reg.  */
112936ac495dSmrg   /* We used to optimize loads from single registers as
113036ac495dSmrg 
113136ac495dSmrg 	st r1,r3; st r2,+r3
113236ac495dSmrg 
113336ac495dSmrg      if r3 were not used subsequently.  However, the REG_NOTES aren't
113436ac495dSmrg      propagated correctly by the reload phase, and it can cause bad
113536ac495dSmrg      code to be generated.  We could still try:
113636ac495dSmrg 
113736ac495dSmrg 	st r1,r3; st r2,+r3; addi r3,-4
113836ac495dSmrg 
113936ac495dSmrg      which saves 2 bytes and doesn't force longword alignment.  */
114036ac495dSmrg   else if (MEM_P (dest) && REG_P (src))
114136ac495dSmrg     {
114236ac495dSmrg       emit_insn (gen_rtx_SET (adjust_address (dest, SImode, 0),
114336ac495dSmrg 			      operand_subword (src, 0, TRUE, mode)));
114436ac495dSmrg 
114536ac495dSmrg       emit_insn (gen_rtx_SET (adjust_address (dest, SImode, UNITS_PER_WORD),
114636ac495dSmrg 			      operand_subword (src, 1, TRUE, mode)));
114736ac495dSmrg     }
114836ac495dSmrg 
114936ac495dSmrg   else
115036ac495dSmrg     gcc_unreachable ();
115136ac495dSmrg 
115236ac495dSmrg   val = get_insns ();
115336ac495dSmrg   end_sequence ();
115436ac495dSmrg   return val;
115536ac495dSmrg }
115636ac495dSmrg 
115736ac495dSmrg 
115836ac495dSmrg static int
m32r_arg_partial_bytes(cumulative_args_t cum_v,const function_arg_info & arg)1159*8feb0f0bSmrg m32r_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg)
116036ac495dSmrg {
116136ac495dSmrg   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
116236ac495dSmrg 
116336ac495dSmrg   int words;
116436ac495dSmrg   unsigned int size =
1165*8feb0f0bSmrg     (arg.promoted_size_in_bytes () + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
116636ac495dSmrg 
116736ac495dSmrg   if (*cum >= M32R_MAX_PARM_REGS)
116836ac495dSmrg     words = 0;
116936ac495dSmrg   else if (*cum + size > M32R_MAX_PARM_REGS)
117036ac495dSmrg     words = (*cum + size) - M32R_MAX_PARM_REGS;
117136ac495dSmrg   else
117236ac495dSmrg     words = 0;
117336ac495dSmrg 
117436ac495dSmrg   return words * UNITS_PER_WORD;
117536ac495dSmrg }
117636ac495dSmrg 
117736ac495dSmrg /* The ROUND_ADVANCE* macros are local to this file.  */
117836ac495dSmrg /* Round SIZE up to a word boundary.  */
117936ac495dSmrg #define ROUND_ADVANCE(SIZE) \
118036ac495dSmrg   (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
118136ac495dSmrg 
118236ac495dSmrg /* Round arg MODE/TYPE up to the next word boundary.  */
118336ac495dSmrg #define ROUND_ADVANCE_ARG(MODE, TYPE) \
118436ac495dSmrg   ((MODE) == BLKmode				\
118536ac495dSmrg    ? ROUND_ADVANCE ((unsigned int) int_size_in_bytes (TYPE))	\
118636ac495dSmrg    : ROUND_ADVANCE ((unsigned int) GET_MODE_SIZE (MODE)))
118736ac495dSmrg 
118836ac495dSmrg /* Round CUM up to the necessary point for argument MODE/TYPE.  */
118936ac495dSmrg #define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) (CUM)
119036ac495dSmrg 
119136ac495dSmrg /* Return boolean indicating arg of type TYPE and mode MODE will be passed in
119236ac495dSmrg    a reg.  This includes arguments that have to be passed by reference as the
119336ac495dSmrg    pointer to them is passed in a reg if one is available (and that is what
119436ac495dSmrg    we're given).
119536ac495dSmrg    This macro is only used in this file.  */
119636ac495dSmrg #define PASS_IN_REG_P(CUM, MODE, TYPE) \
119736ac495dSmrg   (ROUND_ADVANCE_CUM ((CUM), (MODE), (TYPE)) < M32R_MAX_PARM_REGS)
119836ac495dSmrg 
119936ac495dSmrg /* Determine where to put an argument to a function.
120036ac495dSmrg    Value is zero to push the argument on the stack,
120136ac495dSmrg    or a hard register in which to store the argument.
120236ac495dSmrg 
120336ac495dSmrg    CUM is a variable of type CUMULATIVE_ARGS which gives info about
120436ac495dSmrg     the preceding args and about the function being called.
1205*8feb0f0bSmrg    ARG is a description of the argument.  */
120636ac495dSmrg /* On the M32R the first M32R_MAX_PARM_REGS args are normally in registers
120736ac495dSmrg    and the rest are pushed.  */
120836ac495dSmrg 
120936ac495dSmrg static rtx
m32r_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)1210*8feb0f0bSmrg m32r_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
121136ac495dSmrg {
121236ac495dSmrg   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
121336ac495dSmrg 
1214*8feb0f0bSmrg   return (PASS_IN_REG_P (*cum, arg.mode, arg.type)
1215*8feb0f0bSmrg 	  ? gen_rtx_REG (arg.mode,
1216*8feb0f0bSmrg 			 ROUND_ADVANCE_CUM (*cum, arg.mode, arg.type))
121736ac495dSmrg 	  : NULL_RTX);
121836ac495dSmrg }
121936ac495dSmrg 
1220*8feb0f0bSmrg /* Update the data in CUM to advance over argument ARG.  */
122136ac495dSmrg 
122236ac495dSmrg static void
m32r_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)1223*8feb0f0bSmrg m32r_function_arg_advance (cumulative_args_t cum_v,
1224*8feb0f0bSmrg 			   const function_arg_info &arg)
122536ac495dSmrg {
122636ac495dSmrg   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
122736ac495dSmrg 
1228*8feb0f0bSmrg   *cum = (ROUND_ADVANCE_CUM (*cum, arg.mode, arg.type)
1229*8feb0f0bSmrg 	  + ROUND_ADVANCE_ARG (arg.mode, arg.type));
123036ac495dSmrg }
123136ac495dSmrg 
123236ac495dSmrg /* Worker function for TARGET_RETURN_IN_MEMORY.  */
123336ac495dSmrg 
123436ac495dSmrg static bool
m32r_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)123536ac495dSmrg m32r_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
123636ac495dSmrg {
123736ac495dSmrg   cumulative_args_t dummy = pack_cumulative_args (NULL);
1238*8feb0f0bSmrg   function_arg_info arg (const_cast<tree> (type), /*named=*/false);
1239*8feb0f0bSmrg   return m32r_pass_by_reference (dummy, arg);
124036ac495dSmrg }
124136ac495dSmrg 
124236ac495dSmrg /* Worker function for TARGET_FUNCTION_VALUE.  */
124336ac495dSmrg 
124436ac495dSmrg static rtx
m32r_function_value(const_tree valtype,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)124536ac495dSmrg m32r_function_value (const_tree valtype,
124636ac495dSmrg 		const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
124736ac495dSmrg 		bool outgoing ATTRIBUTE_UNUSED)
124836ac495dSmrg {
124936ac495dSmrg   return gen_rtx_REG (TYPE_MODE (valtype), 0);
125036ac495dSmrg }
125136ac495dSmrg 
125236ac495dSmrg /* Worker function for TARGET_LIBCALL_VALUE.  */
125336ac495dSmrg 
125436ac495dSmrg static rtx
m32r_libcall_value(machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)125536ac495dSmrg m32r_libcall_value (machine_mode mode,
125636ac495dSmrg 		const_rtx fun ATTRIBUTE_UNUSED)
125736ac495dSmrg {
125836ac495dSmrg   return gen_rtx_REG (mode, 0);
125936ac495dSmrg }
126036ac495dSmrg 
126136ac495dSmrg /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P.
126236ac495dSmrg 
126336ac495dSmrg   ??? What about r1 in DI/DF values.  */
126436ac495dSmrg 
126536ac495dSmrg static bool
m32r_function_value_regno_p(const unsigned int regno)126636ac495dSmrg m32r_function_value_regno_p (const unsigned int regno)
126736ac495dSmrg {
126836ac495dSmrg   return (regno == 0);
126936ac495dSmrg }
127036ac495dSmrg 
127136ac495dSmrg /* Do any needed setup for a variadic function.  For the M32R, we must
127236ac495dSmrg    create a register parameter block, and then copy any anonymous arguments
127336ac495dSmrg    in registers to memory.
127436ac495dSmrg 
1275*8feb0f0bSmrg    CUM has not been updated for the last named argument (which is given
1276*8feb0f0bSmrg    by ARG), and we rely on this fact.  */
127736ac495dSmrg 
127836ac495dSmrg static void
m32r_setup_incoming_varargs(cumulative_args_t cum,const function_arg_info & arg,int * pretend_size,int no_rtl)1279*8feb0f0bSmrg m32r_setup_incoming_varargs (cumulative_args_t cum,
1280*8feb0f0bSmrg 			     const function_arg_info &arg,
1281*8feb0f0bSmrg 			     int *pretend_size, int no_rtl)
128236ac495dSmrg {
128336ac495dSmrg   int first_anon_arg;
128436ac495dSmrg 
128536ac495dSmrg   if (no_rtl)
128636ac495dSmrg     return;
128736ac495dSmrg 
128836ac495dSmrg   /* All BLKmode values are passed by reference.  */
1289*8feb0f0bSmrg   gcc_assert (arg.mode != BLKmode);
129036ac495dSmrg 
1291*8feb0f0bSmrg   first_anon_arg = (ROUND_ADVANCE_CUM (*get_cumulative_args (cum),
1292*8feb0f0bSmrg 				       arg.mode, arg.type)
1293*8feb0f0bSmrg 		    + ROUND_ADVANCE_ARG (arg.mode, arg.type));
129436ac495dSmrg 
129536ac495dSmrg   if (first_anon_arg < M32R_MAX_PARM_REGS)
129636ac495dSmrg     {
129736ac495dSmrg       /* Note that first_reg_offset < M32R_MAX_PARM_REGS.  */
129836ac495dSmrg       int first_reg_offset = first_anon_arg;
129936ac495dSmrg       /* Size in words to "pretend" allocate.  */
130036ac495dSmrg       int size = M32R_MAX_PARM_REGS - first_reg_offset;
130136ac495dSmrg       rtx regblock;
130236ac495dSmrg 
130336ac495dSmrg       regblock = gen_frame_mem (BLKmode,
130436ac495dSmrg 				plus_constant (Pmode, arg_pointer_rtx,
130536ac495dSmrg 					       FIRST_PARM_OFFSET (0)));
130636ac495dSmrg       set_mem_alias_set (regblock, get_varargs_alias_set ());
130736ac495dSmrg       move_block_from_reg (first_reg_offset, regblock, size);
130836ac495dSmrg 
130936ac495dSmrg       *pretend_size = (size * UNITS_PER_WORD);
131036ac495dSmrg     }
131136ac495dSmrg }
131236ac495dSmrg 
131336ac495dSmrg 
131436ac495dSmrg /* Return true if INSN is real instruction bearing insn.  */
131536ac495dSmrg 
131636ac495dSmrg static int
m32r_is_insn(rtx insn)131736ac495dSmrg m32r_is_insn (rtx insn)
131836ac495dSmrg {
131936ac495dSmrg   return (NONDEBUG_INSN_P (insn)
132036ac495dSmrg 	  && GET_CODE (PATTERN (insn)) != USE
132136ac495dSmrg 	  && GET_CODE (PATTERN (insn)) != CLOBBER);
132236ac495dSmrg }
132336ac495dSmrg 
132436ac495dSmrg /* Increase the priority of long instructions so that the
132536ac495dSmrg    short instructions are scheduled ahead of the long ones.  */
132636ac495dSmrg 
132736ac495dSmrg static int
m32r_adjust_priority(rtx_insn * insn,int priority)132836ac495dSmrg m32r_adjust_priority (rtx_insn *insn, int priority)
132936ac495dSmrg {
133036ac495dSmrg   if (m32r_is_insn (insn)
133136ac495dSmrg       && get_attr_insn_size (insn) != INSN_SIZE_SHORT)
133236ac495dSmrg     priority <<= 3;
133336ac495dSmrg 
133436ac495dSmrg   return priority;
133536ac495dSmrg }
133636ac495dSmrg 
133736ac495dSmrg 
133836ac495dSmrg /* Indicate how many instructions can be issued at the same time.
133936ac495dSmrg    This is sort of a lie.  The m32r can issue only 1 long insn at
134036ac495dSmrg    once, but it can issue 2 short insns.  The default therefore is
134136ac495dSmrg    set at 2, but this can be overridden by the command line option
134236ac495dSmrg    -missue-rate=1.  */
134336ac495dSmrg 
134436ac495dSmrg static int
m32r_issue_rate(void)134536ac495dSmrg m32r_issue_rate (void)
134636ac495dSmrg {
134736ac495dSmrg   return ((TARGET_LOW_ISSUE_RATE) ? 1 : 2);
134836ac495dSmrg }
134936ac495dSmrg 
135036ac495dSmrg /* Cost functions.  */
135136ac495dSmrg /* Memory is 3 times as expensive as registers.
135236ac495dSmrg    ??? Is that the right way to look at it?  */
135336ac495dSmrg 
135436ac495dSmrg static int
m32r_memory_move_cost(machine_mode mode,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)135536ac495dSmrg m32r_memory_move_cost (machine_mode mode,
135636ac495dSmrg 		       reg_class_t rclass ATTRIBUTE_UNUSED,
135736ac495dSmrg 		       bool in ATTRIBUTE_UNUSED)
135836ac495dSmrg {
135936ac495dSmrg   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
136036ac495dSmrg     return 6;
136136ac495dSmrg   else
136236ac495dSmrg     return 12;
136336ac495dSmrg }
136436ac495dSmrg 
136536ac495dSmrg static bool
m32r_rtx_costs(rtx x,machine_mode mode ATTRIBUTE_UNUSED,int outer_code ATTRIBUTE_UNUSED,int opno ATTRIBUTE_UNUSED,int * total,bool speed ATTRIBUTE_UNUSED)136636ac495dSmrg m32r_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
136736ac495dSmrg 		int outer_code ATTRIBUTE_UNUSED,
136836ac495dSmrg 		int opno ATTRIBUTE_UNUSED, int *total,
136936ac495dSmrg 		bool speed ATTRIBUTE_UNUSED)
137036ac495dSmrg {
137136ac495dSmrg   int code = GET_CODE (x);
137236ac495dSmrg 
137336ac495dSmrg   switch (code)
137436ac495dSmrg     {
137536ac495dSmrg       /* Small integers are as cheap as registers.  4 byte values can be
137636ac495dSmrg          fetched as immediate constants - let's give that the cost of an
137736ac495dSmrg          extra insn.  */
137836ac495dSmrg     case CONST_INT:
137936ac495dSmrg       if (INT16_P (INTVAL (x)))
138036ac495dSmrg 	{
138136ac495dSmrg 	  *total = 0;
138236ac495dSmrg 	  return true;
138336ac495dSmrg 	}
138436ac495dSmrg       /* FALLTHRU */
138536ac495dSmrg 
138636ac495dSmrg     case CONST:
138736ac495dSmrg     case LABEL_REF:
138836ac495dSmrg     case SYMBOL_REF:
138936ac495dSmrg       *total = COSTS_N_INSNS (1);
139036ac495dSmrg       return true;
139136ac495dSmrg 
139236ac495dSmrg     case CONST_DOUBLE:
139336ac495dSmrg       {
139436ac495dSmrg 	rtx high, low;
139536ac495dSmrg 
139636ac495dSmrg 	split_double (x, &high, &low);
139736ac495dSmrg 	*total = COSTS_N_INSNS (!INT16_P (INTVAL (high))
139836ac495dSmrg 			        + !INT16_P (INTVAL (low)));
139936ac495dSmrg 	return true;
140036ac495dSmrg       }
140136ac495dSmrg 
140236ac495dSmrg     case MULT:
140336ac495dSmrg       *total = COSTS_N_INSNS (3);
140436ac495dSmrg       return true;
140536ac495dSmrg 
140636ac495dSmrg     case DIV:
140736ac495dSmrg     case UDIV:
140836ac495dSmrg     case MOD:
140936ac495dSmrg     case UMOD:
141036ac495dSmrg       *total = COSTS_N_INSNS (10);
141136ac495dSmrg       return true;
141236ac495dSmrg 
141336ac495dSmrg     default:
141436ac495dSmrg       return false;
141536ac495dSmrg     }
141636ac495dSmrg }
141736ac495dSmrg 
141836ac495dSmrg /* Type of function DECL.
141936ac495dSmrg 
142036ac495dSmrg    The result is cached.  To reset the cache at the end of a function,
142136ac495dSmrg    call with DECL = NULL_TREE.  */
142236ac495dSmrg 
142336ac495dSmrg enum m32r_function_type
m32r_compute_function_type(tree decl)142436ac495dSmrg m32r_compute_function_type (tree decl)
142536ac495dSmrg {
142636ac495dSmrg   /* Cached value.  */
142736ac495dSmrg   static enum m32r_function_type fn_type = M32R_FUNCTION_UNKNOWN;
142836ac495dSmrg   /* Last function we were called for.  */
142936ac495dSmrg   static tree last_fn = NULL_TREE;
143036ac495dSmrg 
143136ac495dSmrg   /* Resetting the cached value?  */
143236ac495dSmrg   if (decl == NULL_TREE)
143336ac495dSmrg     {
143436ac495dSmrg       fn_type = M32R_FUNCTION_UNKNOWN;
143536ac495dSmrg       last_fn = NULL_TREE;
143636ac495dSmrg       return fn_type;
143736ac495dSmrg     }
143836ac495dSmrg 
143936ac495dSmrg   if (decl == last_fn && fn_type != M32R_FUNCTION_UNKNOWN)
144036ac495dSmrg     return fn_type;
144136ac495dSmrg 
144236ac495dSmrg   /* Compute function type.  */
144336ac495dSmrg   fn_type = (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE
144436ac495dSmrg 	     ? M32R_FUNCTION_INTERRUPT
144536ac495dSmrg 	     : M32R_FUNCTION_NORMAL);
144636ac495dSmrg 
144736ac495dSmrg   last_fn = decl;
144836ac495dSmrg   return fn_type;
144936ac495dSmrg }
145036ac495dSmrg /* Function prologue/epilogue handlers.  */
145136ac495dSmrg 
145236ac495dSmrg /* M32R stack frames look like:
145336ac495dSmrg 
145436ac495dSmrg              Before call                       After call
145536ac495dSmrg         +-----------------------+       +-----------------------+
145636ac495dSmrg         |                       |       |                       |
145736ac495dSmrg    high |  local variables,     |       |  local variables,     |
145836ac495dSmrg    mem  |  reg save area, etc.  |       |  reg save area, etc.  |
145936ac495dSmrg         |                       |       |                       |
146036ac495dSmrg         +-----------------------+       +-----------------------+
146136ac495dSmrg         |                       |       |                       |
146236ac495dSmrg         |  arguments on stack.  |       |  arguments on stack.  |
146336ac495dSmrg         |                       |       |                       |
146436ac495dSmrg   SP+0->+-----------------------+       +-----------------------+
146536ac495dSmrg                                         |  reg parm save area,  |
146636ac495dSmrg                                         |  only created for     |
146736ac495dSmrg                                         |  variable argument    |
146836ac495dSmrg                                         |  functions            |
146936ac495dSmrg 					+-----------------------+
147036ac495dSmrg                                         |   previous frame ptr  |
147136ac495dSmrg                                         +-----------------------+
147236ac495dSmrg                                         |                       |
147336ac495dSmrg                                         |  register save area   |
147436ac495dSmrg                                         |                       |
147536ac495dSmrg 					+-----------------------+
147636ac495dSmrg                                         |    return address     |
147736ac495dSmrg                                         +-----------------------+
147836ac495dSmrg                                         |                       |
147936ac495dSmrg                                         |  local variables      |
148036ac495dSmrg                                         |                       |
148136ac495dSmrg                                         +-----------------------+
148236ac495dSmrg                                         |                       |
148336ac495dSmrg                                         |  alloca allocations   |
148436ac495dSmrg                                         |                       |
148536ac495dSmrg                                         +-----------------------+
148636ac495dSmrg                                         |                       |
148736ac495dSmrg    low                                  |  arguments on stack   |
148836ac495dSmrg    memory                               |                       |
148936ac495dSmrg                                   SP+0->+-----------------------+
149036ac495dSmrg 
149136ac495dSmrg Notes:
149236ac495dSmrg 1) The "reg parm save area" does not exist for non variable argument fns.
149336ac495dSmrg 2) The "reg parm save area" can be eliminated completely if we saved regs
149436ac495dSmrg    containing anonymous args separately but that complicates things too
149536ac495dSmrg    much (so it's not done).
149636ac495dSmrg 3) The return address is saved after the register save area so as to have as
149736ac495dSmrg    many insns as possible between the restoration of `lr' and the `jmp lr'.  */
149836ac495dSmrg 
149936ac495dSmrg /* Structure to be filled in by m32r_compute_frame_size with register
150036ac495dSmrg    save masks, and offsets for the current function.  */
150136ac495dSmrg struct m32r_frame_info
150236ac495dSmrg {
150336ac495dSmrg   unsigned int total_size;	/* # bytes that the entire frame takes up.  */
150436ac495dSmrg   unsigned int extra_size;	/* # bytes of extra stuff.  */
150536ac495dSmrg   unsigned int pretend_size;	/* # bytes we push and pretend caller did.  */
150636ac495dSmrg   unsigned int args_size;	/* # bytes that outgoing arguments take up.  */
150736ac495dSmrg   unsigned int reg_size;	/* # bytes needed to store regs.  */
150836ac495dSmrg   unsigned int var_size;	/* # bytes that variables take up.  */
150936ac495dSmrg   unsigned int gmask;		/* Mask of saved gp registers.  */
151036ac495dSmrg   unsigned int save_fp;		/* Nonzero if fp must be saved.  */
151136ac495dSmrg   unsigned int save_lr;		/* Nonzero if lr (return addr) must be saved.  */
151236ac495dSmrg   int          initialized;	/* Nonzero if frame size already calculated.  */
151336ac495dSmrg };
151436ac495dSmrg 
151536ac495dSmrg /* Current frame information calculated by m32r_compute_frame_size.  */
151636ac495dSmrg static struct m32r_frame_info current_frame_info;
151736ac495dSmrg 
151836ac495dSmrg /* Zero structure to initialize current_frame_info.  */
151936ac495dSmrg static struct m32r_frame_info zero_frame_info;
152036ac495dSmrg 
152136ac495dSmrg #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
152236ac495dSmrg #define RETURN_ADDR_MASK   (1 << (RETURN_ADDR_REGNUM))
152336ac495dSmrg 
152436ac495dSmrg /* Tell prologue and epilogue if register REGNO should be saved / restored.
152536ac495dSmrg    The return address and frame pointer are treated separately.
152636ac495dSmrg    Don't consider them here.  */
152736ac495dSmrg #define MUST_SAVE_REGISTER(regno, interrupt_p) \
152836ac495dSmrg   ((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1529*8feb0f0bSmrg    && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p)))
153036ac495dSmrg 
153136ac495dSmrg #define MUST_SAVE_FRAME_POINTER (df_regs_ever_live_p (FRAME_POINTER_REGNUM))
153236ac495dSmrg #define MUST_SAVE_RETURN_ADDR   (df_regs_ever_live_p (RETURN_ADDR_REGNUM) || crtl->profile)
153336ac495dSmrg 
153436ac495dSmrg #define SHORT_INSN_SIZE 2	/* Size of small instructions.  */
153536ac495dSmrg #define LONG_INSN_SIZE 4	/* Size of long instructions.  */
153636ac495dSmrg 
153736ac495dSmrg /* Return the bytes needed to compute the frame pointer from the current
153836ac495dSmrg    stack pointer.
153936ac495dSmrg 
154036ac495dSmrg    SIZE is the size needed for local variables.  */
154136ac495dSmrg 
154236ac495dSmrg unsigned int
m32r_compute_frame_size(poly_int64 size)1543a2dc1f3fSmrg m32r_compute_frame_size (poly_int64 size)   /* # of var. bytes allocated.  */
154436ac495dSmrg {
154536ac495dSmrg   unsigned int regno;
154636ac495dSmrg   unsigned int total_size, var_size, args_size, pretend_size, extra_size;
154736ac495dSmrg   unsigned int reg_size;
154836ac495dSmrg   unsigned int gmask;
154936ac495dSmrg   enum m32r_function_type fn_type;
155036ac495dSmrg   int interrupt_p;
155136ac495dSmrg   int pic_reg_used = flag_pic && (crtl->uses_pic_offset_table
155236ac495dSmrg                                   | crtl->profile);
155336ac495dSmrg 
155436ac495dSmrg   var_size	= M32R_STACK_ALIGN (size);
155536ac495dSmrg   args_size	= M32R_STACK_ALIGN (crtl->outgoing_args_size);
155636ac495dSmrg   pretend_size	= crtl->args.pretend_args_size;
155736ac495dSmrg   extra_size	= FIRST_PARM_OFFSET (0);
155836ac495dSmrg   total_size	= extra_size + pretend_size + args_size + var_size;
155936ac495dSmrg   reg_size	= 0;
156036ac495dSmrg   gmask		= 0;
156136ac495dSmrg 
156236ac495dSmrg   /* See if this is an interrupt handler.  Call used registers must be saved
156336ac495dSmrg      for them too.  */
156436ac495dSmrg   fn_type = m32r_compute_function_type (current_function_decl);
156536ac495dSmrg   interrupt_p = M32R_INTERRUPT_P (fn_type);
156636ac495dSmrg 
156736ac495dSmrg   /* Calculate space needed for registers.  */
156836ac495dSmrg   for (regno = 0; regno < M32R_MAX_INT_REGS; regno++)
156936ac495dSmrg     {
157036ac495dSmrg       if (MUST_SAVE_REGISTER (regno, interrupt_p)
157136ac495dSmrg           || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
157236ac495dSmrg 	{
157336ac495dSmrg 	  reg_size += UNITS_PER_WORD;
157436ac495dSmrg 	  gmask |= 1 << regno;
157536ac495dSmrg 	}
157636ac495dSmrg     }
157736ac495dSmrg 
157836ac495dSmrg   current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
157936ac495dSmrg   current_frame_info.save_lr = MUST_SAVE_RETURN_ADDR || pic_reg_used;
158036ac495dSmrg 
158136ac495dSmrg   reg_size += ((current_frame_info.save_fp + current_frame_info.save_lr)
158236ac495dSmrg 	       * UNITS_PER_WORD);
158336ac495dSmrg   total_size += reg_size;
158436ac495dSmrg 
158536ac495dSmrg   /* ??? Not sure this is necessary, and I don't think the epilogue
158636ac495dSmrg      handler will do the right thing if this changes total_size.  */
158736ac495dSmrg   total_size = M32R_STACK_ALIGN (total_size);
158836ac495dSmrg 
158936ac495dSmrg   /* frame_size = total_size - (pretend_size + reg_size); */
159036ac495dSmrg 
159136ac495dSmrg   /* Save computed information.  */
159236ac495dSmrg   current_frame_info.total_size   = total_size;
159336ac495dSmrg   current_frame_info.extra_size   = extra_size;
159436ac495dSmrg   current_frame_info.pretend_size = pretend_size;
159536ac495dSmrg   current_frame_info.var_size     = var_size;
159636ac495dSmrg   current_frame_info.args_size    = args_size;
159736ac495dSmrg   current_frame_info.reg_size	  = reg_size;
159836ac495dSmrg   current_frame_info.gmask	  = gmask;
159936ac495dSmrg   current_frame_info.initialized  = reload_completed;
160036ac495dSmrg 
160136ac495dSmrg   /* Ok, we're done.  */
160236ac495dSmrg   return total_size;
160336ac495dSmrg }
160436ac495dSmrg 
160536ac495dSmrg /* Worker function for TARGET_CAN_ELIMINATE.  */
160636ac495dSmrg 
160736ac495dSmrg bool
m32r_can_eliminate(const int from,const int to)160836ac495dSmrg m32r_can_eliminate (const int from, const int to)
160936ac495dSmrg {
161036ac495dSmrg   return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM
161136ac495dSmrg           ? ! frame_pointer_needed
161236ac495dSmrg           : true);
161336ac495dSmrg }
161436ac495dSmrg 
161536ac495dSmrg 
161636ac495dSmrg /* The table we use to reference PIC data.  */
161736ac495dSmrg static rtx global_offset_table;
161836ac495dSmrg 
161936ac495dSmrg static void
m32r_reload_lr(rtx sp,int size)162036ac495dSmrg m32r_reload_lr (rtx sp, int size)
162136ac495dSmrg {
162236ac495dSmrg   rtx lr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
162336ac495dSmrg 
162436ac495dSmrg   if (size == 0)
162536ac495dSmrg     emit_insn (gen_movsi (lr, gen_frame_mem (Pmode, sp)));
162636ac495dSmrg   else if (size < 32768)
162736ac495dSmrg     emit_insn (gen_movsi (lr, gen_frame_mem (Pmode,
162836ac495dSmrg 					     gen_rtx_PLUS (Pmode, sp,
162936ac495dSmrg 							   GEN_INT (size)))));
163036ac495dSmrg   else
163136ac495dSmrg     {
163236ac495dSmrg       rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
163336ac495dSmrg 
163436ac495dSmrg       emit_insn (gen_movsi (tmp, GEN_INT (size)));
163536ac495dSmrg       emit_insn (gen_addsi3 (tmp, tmp, sp));
163636ac495dSmrg       emit_insn (gen_movsi (lr, gen_frame_mem (Pmode, tmp)));
163736ac495dSmrg     }
163836ac495dSmrg 
163936ac495dSmrg   emit_use (lr);
164036ac495dSmrg }
164136ac495dSmrg 
164236ac495dSmrg void
m32r_load_pic_register(void)164336ac495dSmrg m32r_load_pic_register (void)
164436ac495dSmrg {
164536ac495dSmrg   global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
164636ac495dSmrg   emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
164736ac495dSmrg                          GEN_INT (TARGET_MODEL_SMALL)));
164836ac495dSmrg 
164936ac495dSmrg   /* Need to emit this whether or not we obey regdecls,
165036ac495dSmrg      since setjmp/longjmp can cause life info to screw up.  */
165136ac495dSmrg   emit_use (pic_offset_table_rtx);
165236ac495dSmrg }
165336ac495dSmrg 
165436ac495dSmrg /* Expand the m32r prologue as a series of insns.  */
165536ac495dSmrg 
165636ac495dSmrg void
m32r_expand_prologue(void)165736ac495dSmrg m32r_expand_prologue (void)
165836ac495dSmrg {
165936ac495dSmrg   int regno;
166036ac495dSmrg   int frame_size;
166136ac495dSmrg   unsigned int gmask;
166236ac495dSmrg   int pic_reg_used = flag_pic && (crtl->uses_pic_offset_table
166336ac495dSmrg                                   | crtl->profile);
166436ac495dSmrg 
166536ac495dSmrg   if (! current_frame_info.initialized)
166636ac495dSmrg     m32r_compute_frame_size (get_frame_size ());
166736ac495dSmrg 
166836ac495dSmrg   if (flag_stack_usage_info)
166936ac495dSmrg     current_function_static_stack_size = current_frame_info.total_size;
167036ac495dSmrg 
167136ac495dSmrg   gmask = current_frame_info.gmask;
167236ac495dSmrg 
167336ac495dSmrg   /* These cases shouldn't happen.  Catch them now.  */
167436ac495dSmrg   gcc_assert (current_frame_info.total_size || !gmask);
167536ac495dSmrg 
167636ac495dSmrg   /* Allocate space for register arguments if this is a variadic function.  */
167736ac495dSmrg   if (current_frame_info.pretend_size != 0)
167836ac495dSmrg     {
167936ac495dSmrg       /* Use a HOST_WIDE_INT temporary, since negating an unsigned int gives
168036ac495dSmrg 	 the wrong result on a 64-bit host.  */
168136ac495dSmrg       HOST_WIDE_INT pretend_size = current_frame_info.pretend_size;
168236ac495dSmrg       emit_insn (gen_addsi3 (stack_pointer_rtx,
168336ac495dSmrg 			     stack_pointer_rtx,
168436ac495dSmrg 			     GEN_INT (-pretend_size)));
168536ac495dSmrg     }
168636ac495dSmrg 
168736ac495dSmrg   /* Save any registers we need to and set up fp.  */
168836ac495dSmrg   if (current_frame_info.save_fp)
168936ac495dSmrg     emit_insn (gen_movsi_push (stack_pointer_rtx, frame_pointer_rtx));
169036ac495dSmrg 
169136ac495dSmrg   gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);
169236ac495dSmrg 
169336ac495dSmrg   /* Save any needed call-saved regs (and call-used if this is an
169436ac495dSmrg      interrupt handler).  */
169536ac495dSmrg   for (regno = 0; regno <= M32R_MAX_INT_REGS; ++regno)
169636ac495dSmrg     {
169736ac495dSmrg       if ((gmask & (1 << regno)) != 0)
169836ac495dSmrg 	emit_insn (gen_movsi_push (stack_pointer_rtx,
169936ac495dSmrg 				   gen_rtx_REG (Pmode, regno)));
170036ac495dSmrg     }
170136ac495dSmrg 
170236ac495dSmrg   if (current_frame_info.save_lr)
170336ac495dSmrg     emit_insn (gen_movsi_push (stack_pointer_rtx,
170436ac495dSmrg 			       gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));
170536ac495dSmrg 
170636ac495dSmrg   /* Allocate the stack frame.  */
170736ac495dSmrg   frame_size = (current_frame_info.total_size
170836ac495dSmrg 		- (current_frame_info.pretend_size
170936ac495dSmrg 		   + current_frame_info.reg_size));
171036ac495dSmrg 
171136ac495dSmrg   if (frame_size == 0)
171236ac495dSmrg     ; /* Nothing to do.  */
171336ac495dSmrg   else if (frame_size <= 32768)
171436ac495dSmrg     emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
171536ac495dSmrg 			   GEN_INT (-frame_size)));
171636ac495dSmrg   else
171736ac495dSmrg     {
171836ac495dSmrg       rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
171936ac495dSmrg 
172036ac495dSmrg       emit_insn (gen_movsi (tmp, GEN_INT (frame_size)));
172136ac495dSmrg       emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
172236ac495dSmrg     }
172336ac495dSmrg 
172436ac495dSmrg   if (frame_pointer_needed)
172536ac495dSmrg     emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
172636ac495dSmrg 
172736ac495dSmrg   if (crtl->profile)
172836ac495dSmrg     /* Push lr for mcount (form_pc, x).  */
172936ac495dSmrg     emit_insn (gen_movsi_push (stack_pointer_rtx,
173036ac495dSmrg                                gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM)));
173136ac495dSmrg 
173236ac495dSmrg   if (pic_reg_used)
173336ac495dSmrg     {
173436ac495dSmrg       m32r_load_pic_register ();
173536ac495dSmrg       m32r_reload_lr (stack_pointer_rtx,
173636ac495dSmrg                       (crtl->profile ? 0 : frame_size));
173736ac495dSmrg     }
173836ac495dSmrg 
173936ac495dSmrg   if (crtl->profile && !pic_reg_used)
174036ac495dSmrg     emit_insn (gen_blockage ());
174136ac495dSmrg }
174236ac495dSmrg 
174336ac495dSmrg 
174436ac495dSmrg /* Set up the stack and frame pointer (if desired) for the function.
174536ac495dSmrg    Note, if this is changed, you need to mirror the changes in
174636ac495dSmrg    m32r_compute_frame_size which calculates the prolog size.  */
174736ac495dSmrg 
174836ac495dSmrg static void
m32r_output_function_prologue(FILE * file)1749a2dc1f3fSmrg m32r_output_function_prologue (FILE * file)
175036ac495dSmrg {
175136ac495dSmrg   enum m32r_function_type fn_type = m32r_compute_function_type (current_function_decl);
175236ac495dSmrg 
175336ac495dSmrg   /* If this is an interrupt handler, mark it as such.  */
175436ac495dSmrg   if (M32R_INTERRUPT_P (fn_type))
175536ac495dSmrg     fprintf (file, "\t%s interrupt handler\n", ASM_COMMENT_START);
175636ac495dSmrg 
175736ac495dSmrg   if (! current_frame_info.initialized)
1758a2dc1f3fSmrg     m32r_compute_frame_size (get_frame_size ());
175936ac495dSmrg 
176036ac495dSmrg   /* This is only for the human reader.  */
176136ac495dSmrg   fprintf (file,
176236ac495dSmrg 	   "\t%s PROLOGUE, vars= %d, regs= %d, args= %d, extra= %d\n",
176336ac495dSmrg 	   ASM_COMMENT_START,
176436ac495dSmrg 	   current_frame_info.var_size,
176536ac495dSmrg 	   current_frame_info.reg_size / 4,
176636ac495dSmrg 	   current_frame_info.args_size,
176736ac495dSmrg 	   current_frame_info.extra_size);
176836ac495dSmrg }
176936ac495dSmrg 
177036ac495dSmrg /* Output RTL to pop register REGNO from the stack.  */
177136ac495dSmrg 
177236ac495dSmrg static void
pop(int regno)177336ac495dSmrg pop (int regno)
177436ac495dSmrg {
177536ac495dSmrg   rtx x;
177636ac495dSmrg 
177736ac495dSmrg   x = emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno),
177836ac495dSmrg 				stack_pointer_rtx));
177936ac495dSmrg   add_reg_note (x, REG_INC, stack_pointer_rtx);
178036ac495dSmrg }
178136ac495dSmrg 
178236ac495dSmrg /* Expand the m32r epilogue as a series of insns.  */
178336ac495dSmrg 
178436ac495dSmrg void
m32r_expand_epilogue(void)178536ac495dSmrg m32r_expand_epilogue (void)
178636ac495dSmrg {
178736ac495dSmrg   int regno;
178836ac495dSmrg   int noepilogue = FALSE;
178936ac495dSmrg   int total_size;
179036ac495dSmrg 
179136ac495dSmrg   gcc_assert (current_frame_info.initialized);
179236ac495dSmrg   total_size = current_frame_info.total_size;
179336ac495dSmrg 
179436ac495dSmrg   if (total_size == 0)
179536ac495dSmrg     {
179636ac495dSmrg       rtx_insn *insn = get_last_insn ();
179736ac495dSmrg 
179836ac495dSmrg       /* If the last insn was a BARRIER, we don't have to write any code
179936ac495dSmrg 	 because a jump (aka return) was put there.  */
180036ac495dSmrg       if (insn && NOTE_P (insn))
180136ac495dSmrg 	insn = prev_nonnote_insn (insn);
180236ac495dSmrg       if (insn && BARRIER_P (insn))
180336ac495dSmrg 	noepilogue = TRUE;
180436ac495dSmrg     }
180536ac495dSmrg 
180636ac495dSmrg   if (!noepilogue)
180736ac495dSmrg     {
180836ac495dSmrg       unsigned int var_size = current_frame_info.var_size;
180936ac495dSmrg       unsigned int args_size = current_frame_info.args_size;
181036ac495dSmrg       unsigned int gmask = current_frame_info.gmask;
181136ac495dSmrg       int can_trust_sp_p = !cfun->calls_alloca;
181236ac495dSmrg 
181336ac495dSmrg       if (flag_exceptions)
181436ac495dSmrg         emit_insn (gen_blockage ());
181536ac495dSmrg 
181636ac495dSmrg       /* The first thing to do is point the sp at the bottom of the register
181736ac495dSmrg 	 save area.  */
181836ac495dSmrg       if (can_trust_sp_p)
181936ac495dSmrg 	{
182036ac495dSmrg 	  unsigned int reg_offset = var_size + args_size;
182136ac495dSmrg 
182236ac495dSmrg 	  if (reg_offset == 0)
182336ac495dSmrg 	    ; /* Nothing to do.  */
182436ac495dSmrg 	  else if (reg_offset < 32768)
182536ac495dSmrg 	    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
182636ac495dSmrg 			   GEN_INT (reg_offset)));
182736ac495dSmrg 	  else
182836ac495dSmrg 	    {
182936ac495dSmrg 	      rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
183036ac495dSmrg 
183136ac495dSmrg 	      emit_insn (gen_movsi (tmp, GEN_INT (reg_offset)));
183236ac495dSmrg 	      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
183336ac495dSmrg 				     tmp));
183436ac495dSmrg 	    }
183536ac495dSmrg 	}
183636ac495dSmrg       else if (frame_pointer_needed)
183736ac495dSmrg 	{
183836ac495dSmrg 	  unsigned int reg_offset = var_size + args_size;
183936ac495dSmrg 
184036ac495dSmrg 	  if (reg_offset == 0)
184136ac495dSmrg 	    emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
184236ac495dSmrg 	  else if (reg_offset < 32768)
184336ac495dSmrg 	    emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
184436ac495dSmrg 			   GEN_INT (reg_offset)));
184536ac495dSmrg 	  else
184636ac495dSmrg 	    {
184736ac495dSmrg 	      rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
184836ac495dSmrg 
184936ac495dSmrg 	      emit_insn (gen_movsi (tmp, GEN_INT (reg_offset)));
185036ac495dSmrg 	      emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
185136ac495dSmrg 	      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
185236ac495dSmrg 				     tmp));
185336ac495dSmrg 	    }
185436ac495dSmrg 	}
185536ac495dSmrg       else
185636ac495dSmrg 	gcc_unreachable ();
185736ac495dSmrg 
185836ac495dSmrg       if (current_frame_info.save_lr)
185936ac495dSmrg 	pop (RETURN_ADDR_REGNUM);
186036ac495dSmrg 
186136ac495dSmrg       /* Restore any saved registers, in reverse order of course.  */
186236ac495dSmrg       gmask &= ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK);
186336ac495dSmrg       for (regno = M32R_MAX_INT_REGS - 1; regno >= 0; --regno)
186436ac495dSmrg 	{
186536ac495dSmrg 	  if ((gmask & (1L << regno)) != 0)
186636ac495dSmrg 	    pop (regno);
186736ac495dSmrg 	}
186836ac495dSmrg 
186936ac495dSmrg       if (current_frame_info.save_fp)
187036ac495dSmrg 	pop (FRAME_POINTER_REGNUM);
187136ac495dSmrg 
187236ac495dSmrg       /* Remove varargs area if present.  */
187336ac495dSmrg       if (current_frame_info.pretend_size != 0)
187436ac495dSmrg 	emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
187536ac495dSmrg 			       GEN_INT (current_frame_info.pretend_size)));
187636ac495dSmrg 
187736ac495dSmrg       emit_insn (gen_blockage ());
187836ac495dSmrg     }
187936ac495dSmrg }
188036ac495dSmrg 
188136ac495dSmrg /* Do any necessary cleanup after a function to restore stack, frame,
188236ac495dSmrg    and regs.  */
188336ac495dSmrg 
188436ac495dSmrg static void
m32r_output_function_epilogue(FILE *)1885a2dc1f3fSmrg m32r_output_function_epilogue (FILE *)
188636ac495dSmrg {
188736ac495dSmrg   /* Reset state info for each function.  */
188836ac495dSmrg   current_frame_info = zero_frame_info;
188936ac495dSmrg   m32r_compute_function_type (NULL_TREE);
189036ac495dSmrg }
189136ac495dSmrg 
189236ac495dSmrg /* Return nonzero if this function is known to have a null or 1 instruction
189336ac495dSmrg    epilogue.  */
189436ac495dSmrg 
189536ac495dSmrg int
direct_return(void)189636ac495dSmrg direct_return (void)
189736ac495dSmrg {
189836ac495dSmrg   if (!reload_completed)
189936ac495dSmrg     return FALSE;
190036ac495dSmrg 
190136ac495dSmrg   if (M32R_INTERRUPT_P (m32r_compute_function_type (current_function_decl)))
190236ac495dSmrg     return FALSE;
190336ac495dSmrg 
190436ac495dSmrg   if (! current_frame_info.initialized)
190536ac495dSmrg     m32r_compute_frame_size (get_frame_size ());
190636ac495dSmrg 
190736ac495dSmrg   return current_frame_info.total_size == 0;
190836ac495dSmrg }
190936ac495dSmrg 
191036ac495dSmrg 
191136ac495dSmrg /* PIC.  */
191236ac495dSmrg 
191336ac495dSmrg int
m32r_legitimate_pic_operand_p(rtx x)191436ac495dSmrg m32r_legitimate_pic_operand_p (rtx x)
191536ac495dSmrg {
191636ac495dSmrg   if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
191736ac495dSmrg     return 0;
191836ac495dSmrg 
191936ac495dSmrg   if (GET_CODE (x) == CONST
192036ac495dSmrg       && GET_CODE (XEXP (x, 0)) == PLUS
192136ac495dSmrg       && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
192236ac495dSmrg           || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
192336ac495dSmrg       && (CONST_INT_P (XEXP (XEXP (x, 0), 1))))
192436ac495dSmrg     return 0;
192536ac495dSmrg 
192636ac495dSmrg   return 1;
192736ac495dSmrg }
192836ac495dSmrg 
192936ac495dSmrg rtx
m32r_legitimize_pic_address(rtx orig,rtx reg)193036ac495dSmrg m32r_legitimize_pic_address (rtx orig, rtx reg)
193136ac495dSmrg {
193236ac495dSmrg #ifdef DEBUG_PIC
193336ac495dSmrg   printf("m32r_legitimize_pic_address()\n");
193436ac495dSmrg #endif
193536ac495dSmrg 
193636ac495dSmrg   if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
193736ac495dSmrg     {
193836ac495dSmrg       rtx pic_ref, address;
193936ac495dSmrg       int subregs = 0;
194036ac495dSmrg 
194136ac495dSmrg       if (reg == 0)
194236ac495dSmrg         {
194336ac495dSmrg           gcc_assert (!reload_in_progress && !reload_completed);
194436ac495dSmrg 	  reg = gen_reg_rtx (Pmode);
194536ac495dSmrg 
194636ac495dSmrg           subregs = 1;
194736ac495dSmrg         }
194836ac495dSmrg 
194936ac495dSmrg       if (subregs)
195036ac495dSmrg         address = gen_reg_rtx (Pmode);
195136ac495dSmrg       else
195236ac495dSmrg         address = reg;
195336ac495dSmrg 
195436ac495dSmrg       crtl->uses_pic_offset_table = 1;
195536ac495dSmrg 
195636ac495dSmrg       if (GET_CODE (orig) == LABEL_REF
195736ac495dSmrg           || (GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (orig)))
195836ac495dSmrg         {
195936ac495dSmrg           emit_insn (gen_gotoff_load_addr (reg, orig));
196036ac495dSmrg           emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
196136ac495dSmrg           return reg;
196236ac495dSmrg         }
196336ac495dSmrg 
196436ac495dSmrg       emit_insn (gen_pic_load_addr (address, orig));
196536ac495dSmrg 
196636ac495dSmrg       emit_insn (gen_addsi3 (address, address, pic_offset_table_rtx));
196736ac495dSmrg       pic_ref = gen_const_mem (Pmode, address);
196836ac495dSmrg       emit_move_insn (reg, pic_ref);
196936ac495dSmrg       return reg;
197036ac495dSmrg     }
197136ac495dSmrg   else if (GET_CODE (orig) == CONST)
197236ac495dSmrg     {
197336ac495dSmrg       rtx base, offset;
197436ac495dSmrg 
197536ac495dSmrg       if (GET_CODE (XEXP (orig, 0)) == PLUS
197636ac495dSmrg           && XEXP (XEXP (orig, 0), 1) == pic_offset_table_rtx)
197736ac495dSmrg         return orig;
197836ac495dSmrg 
197936ac495dSmrg       if (reg == 0)
198036ac495dSmrg         {
198136ac495dSmrg           gcc_assert (!reload_in_progress && !reload_completed);
198236ac495dSmrg 	  reg = gen_reg_rtx (Pmode);
198336ac495dSmrg         }
198436ac495dSmrg 
198536ac495dSmrg       if (GET_CODE (XEXP (orig, 0)) == PLUS)
198636ac495dSmrg         {
198736ac495dSmrg           base = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);
198836ac495dSmrg           if (base == reg)
198936ac495dSmrg             offset = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), NULL_RTX);
199036ac495dSmrg           else
199136ac495dSmrg             offset = m32r_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), reg);
199236ac495dSmrg         }
199336ac495dSmrg       else
199436ac495dSmrg         return orig;
199536ac495dSmrg 
199636ac495dSmrg       if (CONST_INT_P (offset))
199736ac495dSmrg         {
199836ac495dSmrg           if (INT16_P (INTVAL (offset)))
199936ac495dSmrg             return plus_constant (Pmode, base, INTVAL (offset));
200036ac495dSmrg           else
200136ac495dSmrg 	    {
200236ac495dSmrg 	      gcc_assert (! reload_in_progress && ! reload_completed);
200336ac495dSmrg 	      offset = force_reg (Pmode, offset);
200436ac495dSmrg 	    }
200536ac495dSmrg         }
200636ac495dSmrg 
200736ac495dSmrg       return gen_rtx_PLUS (Pmode, base, offset);
200836ac495dSmrg     }
200936ac495dSmrg 
201036ac495dSmrg   return orig;
201136ac495dSmrg }
201236ac495dSmrg 
201336ac495dSmrg static rtx
m32r_legitimize_address(rtx x,rtx orig_x ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED)201436ac495dSmrg m32r_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED,
201536ac495dSmrg 			 machine_mode mode ATTRIBUTE_UNUSED)
201636ac495dSmrg {
201736ac495dSmrg   if (flag_pic)
201836ac495dSmrg     return m32r_legitimize_pic_address (x, NULL_RTX);
201936ac495dSmrg   else
202036ac495dSmrg     return x;
202136ac495dSmrg }
202236ac495dSmrg 
202336ac495dSmrg /* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P.  */
202436ac495dSmrg 
202536ac495dSmrg static bool
m32r_mode_dependent_address_p(const_rtx addr,addr_space_t as ATTRIBUTE_UNUSED)202636ac495dSmrg m32r_mode_dependent_address_p (const_rtx addr, addr_space_t as ATTRIBUTE_UNUSED)
202736ac495dSmrg {
202836ac495dSmrg   if (GET_CODE (addr) == LO_SUM)
202936ac495dSmrg     return true;
203036ac495dSmrg 
203136ac495dSmrg   return false;
203236ac495dSmrg }
203336ac495dSmrg 
203436ac495dSmrg /* Nested function support.  */
203536ac495dSmrg 
203636ac495dSmrg /* Emit RTL insns to initialize the variable parts of a trampoline.
203736ac495dSmrg    FNADDR is an RTX for the address of the function's pure code.
203836ac495dSmrg    CXT is an RTX for the static chain value for the function.  */
203936ac495dSmrg 
204036ac495dSmrg void
m32r_initialize_trampoline(rtx tramp ATTRIBUTE_UNUSED,rtx fnaddr ATTRIBUTE_UNUSED,rtx cxt ATTRIBUTE_UNUSED)204136ac495dSmrg m32r_initialize_trampoline (rtx tramp ATTRIBUTE_UNUSED,
204236ac495dSmrg 			    rtx fnaddr ATTRIBUTE_UNUSED,
204336ac495dSmrg 			    rtx cxt ATTRIBUTE_UNUSED)
204436ac495dSmrg {
204536ac495dSmrg }
204636ac495dSmrg 
204736ac495dSmrg static void
m32r_file_start(void)204836ac495dSmrg m32r_file_start (void)
204936ac495dSmrg {
205036ac495dSmrg   default_file_start ();
205136ac495dSmrg 
205236ac495dSmrg   if (flag_verbose_asm)
205336ac495dSmrg     fprintf (asm_out_file,
205436ac495dSmrg 	     "%s M32R/D special options: -G %d\n",
205536ac495dSmrg 	     ASM_COMMENT_START, g_switch_value);
205636ac495dSmrg 
205736ac495dSmrg   if (TARGET_LITTLE_ENDIAN)
205836ac495dSmrg     fprintf (asm_out_file, "\t.little\n");
205936ac495dSmrg }
206036ac495dSmrg 
206136ac495dSmrg /* Print operand X (an rtx) in assembler syntax to file FILE.
206236ac495dSmrg    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
206336ac495dSmrg    For `%' followed by punctuation, CODE is the punctuation and X is null.  */
206436ac495dSmrg 
206536ac495dSmrg static void
m32r_print_operand(FILE * file,rtx x,int code)206636ac495dSmrg m32r_print_operand (FILE * file, rtx x, int code)
206736ac495dSmrg {
206836ac495dSmrg   rtx addr;
206936ac495dSmrg 
207036ac495dSmrg   switch (code)
207136ac495dSmrg     {
207236ac495dSmrg       /* The 's' and 'p' codes are used by output_block_move() to
207336ac495dSmrg 	 indicate post-increment 's'tores and 'p're-increment loads.  */
207436ac495dSmrg     case 's':
207536ac495dSmrg       if (REG_P (x))
207636ac495dSmrg 	fprintf (file, "@+%s", reg_names [REGNO (x)]);
207736ac495dSmrg       else
207836ac495dSmrg 	output_operand_lossage ("invalid operand to %%s code");
207936ac495dSmrg       return;
208036ac495dSmrg 
208136ac495dSmrg     case 'p':
208236ac495dSmrg       if (REG_P (x))
208336ac495dSmrg 	fprintf (file, "@%s+", reg_names [REGNO (x)]);
208436ac495dSmrg       else
208536ac495dSmrg 	output_operand_lossage ("invalid operand to %%p code");
208636ac495dSmrg       return;
208736ac495dSmrg 
208836ac495dSmrg     case 'R' :
208936ac495dSmrg       /* Write second word of DImode or DFmode reference,
209036ac495dSmrg 	 register or memory.  */
209136ac495dSmrg       if (REG_P (x))
209236ac495dSmrg 	fputs (reg_names[REGNO (x)+1], file);
209336ac495dSmrg       else if (MEM_P (x))
209436ac495dSmrg 	{
209536ac495dSmrg 	  machine_mode mode = GET_MODE (x);
209636ac495dSmrg 
209736ac495dSmrg 	  fprintf (file, "@(");
209836ac495dSmrg 	  /* Handle possible auto-increment.  Since it is pre-increment and
209936ac495dSmrg 	     we have already done it, we can just use an offset of four.  */
210036ac495dSmrg 	  /* ??? This is taken from rs6000.c I think.  I don't think it is
210136ac495dSmrg 	     currently necessary, but keep it around.  */
210236ac495dSmrg 	  if (GET_CODE (XEXP (x, 0)) == PRE_INC
210336ac495dSmrg 	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)
210436ac495dSmrg 	    output_address (mode, plus_constant (Pmode,
210536ac495dSmrg 						 XEXP (XEXP (x, 0), 0), 4));
210636ac495dSmrg 	  else
210736ac495dSmrg 	    output_address (mode, plus_constant (Pmode, XEXP (x, 0), 4));
210836ac495dSmrg 	  fputc (')', file);
210936ac495dSmrg 	}
211036ac495dSmrg       else
211136ac495dSmrg 	output_operand_lossage ("invalid operand to %%R code");
211236ac495dSmrg       return;
211336ac495dSmrg 
211436ac495dSmrg     case 'H' : /* High word.  */
211536ac495dSmrg     case 'L' : /* Low word.  */
211636ac495dSmrg       if (REG_P (x))
211736ac495dSmrg 	{
211836ac495dSmrg 	  /* L = least significant word, H = most significant word.  */
211936ac495dSmrg 	  if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))
212036ac495dSmrg 	    fputs (reg_names[REGNO (x)], file);
212136ac495dSmrg 	  else
212236ac495dSmrg 	    fputs (reg_names[REGNO (x)+1], file);
212336ac495dSmrg 	}
212436ac495dSmrg       else if (CONST_INT_P (x)
212536ac495dSmrg 	       || GET_CODE (x) == CONST_DOUBLE)
212636ac495dSmrg 	{
212736ac495dSmrg 	  rtx first, second;
212836ac495dSmrg 
212936ac495dSmrg 	  split_double (x, &first, &second);
213036ac495dSmrg 	  fprintf (file, HOST_WIDE_INT_PRINT_HEX,
213136ac495dSmrg 		   code == 'L' ? INTVAL (first) : INTVAL (second));
213236ac495dSmrg 	}
213336ac495dSmrg       else
213436ac495dSmrg 	output_operand_lossage ("invalid operand to %%H/%%L code");
213536ac495dSmrg       return;
213636ac495dSmrg 
213736ac495dSmrg     case 'A' :
213836ac495dSmrg       {
213936ac495dSmrg 	char str[30];
214036ac495dSmrg 
214136ac495dSmrg 	if (GET_CODE (x) != CONST_DOUBLE
214236ac495dSmrg 	    || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT)
214336ac495dSmrg 	  fatal_insn ("bad insn for 'A'", x);
214436ac495dSmrg 
214536ac495dSmrg 	real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
214636ac495dSmrg 	fprintf (file, "%s", str);
214736ac495dSmrg 	return;
214836ac495dSmrg       }
214936ac495dSmrg 
215036ac495dSmrg     case 'B' : /* Bottom half.  */
215136ac495dSmrg     case 'T' : /* Top half.  */
215236ac495dSmrg       /* Output the argument to a `seth' insn (sets the Top half-word).
215336ac495dSmrg 	 For constants output arguments to a seth/or3 pair to set Top and
215436ac495dSmrg 	 Bottom halves.  For symbols output arguments to a seth/add3 pair to
215536ac495dSmrg 	 set Top and Bottom halves.  The difference exists because for
215636ac495dSmrg 	 constants seth/or3 is more readable but for symbols we need to use
215736ac495dSmrg 	 the same scheme as `ld' and `st' insns (16-bit addend is signed).  */
215836ac495dSmrg       switch (GET_CODE (x))
215936ac495dSmrg 	{
216036ac495dSmrg 	case CONST_INT :
216136ac495dSmrg 	case CONST_DOUBLE :
216236ac495dSmrg 	  {
216336ac495dSmrg 	    rtx first, second;
216436ac495dSmrg 
216536ac495dSmrg 	    split_double (x, &first, &second);
216636ac495dSmrg 	    x = WORDS_BIG_ENDIAN ? second : first;
216736ac495dSmrg 	    fprintf (file, HOST_WIDE_INT_PRINT_HEX,
216836ac495dSmrg 		     (code == 'B'
216936ac495dSmrg 		      ? INTVAL (x) & 0xffff
217036ac495dSmrg 		      : (INTVAL (x) >> 16) & 0xffff));
217136ac495dSmrg 	  }
217236ac495dSmrg 	  return;
217336ac495dSmrg 	case CONST :
217436ac495dSmrg 	case SYMBOL_REF :
217536ac495dSmrg 	  if (code == 'B'
217636ac495dSmrg 	      && small_data_operand (x, VOIDmode))
217736ac495dSmrg 	    {
217836ac495dSmrg 	      fputs ("sda(", file);
217936ac495dSmrg 	      output_addr_const (file, x);
218036ac495dSmrg 	      fputc (')', file);
218136ac495dSmrg 	      return;
218236ac495dSmrg 	    }
218336ac495dSmrg 	  /* fall through */
218436ac495dSmrg 	case LABEL_REF :
218536ac495dSmrg 	  fputs (code == 'T' ? "shigh(" : "low(", file);
218636ac495dSmrg 	  output_addr_const (file, x);
218736ac495dSmrg 	  fputc (')', file);
218836ac495dSmrg 	  return;
218936ac495dSmrg 	default :
219036ac495dSmrg 	  output_operand_lossage ("invalid operand to %%T/%%B code");
219136ac495dSmrg 	  return;
219236ac495dSmrg 	}
219336ac495dSmrg       break;
219436ac495dSmrg 
219536ac495dSmrg     case 'U' :
219636ac495dSmrg       /* ??? wip */
219736ac495dSmrg       /* Output a load/store with update indicator if appropriate.  */
219836ac495dSmrg       if (MEM_P (x))
219936ac495dSmrg 	{
220036ac495dSmrg 	  if (GET_CODE (XEXP (x, 0)) == PRE_INC
220136ac495dSmrg 	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)
220236ac495dSmrg 	    fputs (".a", file);
220336ac495dSmrg 	}
220436ac495dSmrg       else
220536ac495dSmrg 	output_operand_lossage ("invalid operand to %%U code");
220636ac495dSmrg       return;
220736ac495dSmrg 
220836ac495dSmrg     case 'N' :
220936ac495dSmrg       /* Print a constant value negated.  */
221036ac495dSmrg       if (CONST_INT_P (x))
221136ac495dSmrg 	output_addr_const (file, GEN_INT (- INTVAL (x)));
221236ac495dSmrg       else
221336ac495dSmrg 	output_operand_lossage ("invalid operand to %%N code");
221436ac495dSmrg       return;
221536ac495dSmrg 
221636ac495dSmrg     case 'X' :
221736ac495dSmrg       /* Print a const_int in hex.  Used in comments.  */
221836ac495dSmrg       if (CONST_INT_P (x))
221936ac495dSmrg 	fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
222036ac495dSmrg       return;
222136ac495dSmrg 
222236ac495dSmrg     case '#' :
222336ac495dSmrg       fputs (IMMEDIATE_PREFIX, file);
222436ac495dSmrg       return;
222536ac495dSmrg 
222636ac495dSmrg     case 0 :
222736ac495dSmrg       /* Do nothing special.  */
222836ac495dSmrg       break;
222936ac495dSmrg 
223036ac495dSmrg     default :
223136ac495dSmrg       /* Unknown flag.  */
223236ac495dSmrg       output_operand_lossage ("invalid operand output code");
223336ac495dSmrg     }
223436ac495dSmrg 
223536ac495dSmrg   switch (GET_CODE (x))
223636ac495dSmrg     {
223736ac495dSmrg     case REG :
223836ac495dSmrg       fputs (reg_names[REGNO (x)], file);
223936ac495dSmrg       break;
224036ac495dSmrg 
224136ac495dSmrg     case MEM :
224236ac495dSmrg       addr = XEXP (x, 0);
224336ac495dSmrg       if (GET_CODE (addr) == PRE_INC)
224436ac495dSmrg 	{
224536ac495dSmrg 	  if (!REG_P (XEXP (addr, 0)))
224636ac495dSmrg 	    fatal_insn ("pre-increment address is not a register", x);
224736ac495dSmrg 
224836ac495dSmrg 	  fprintf (file, "@+%s", reg_names[REGNO (XEXP (addr, 0))]);
224936ac495dSmrg 	}
225036ac495dSmrg       else if (GET_CODE (addr) == PRE_DEC)
225136ac495dSmrg 	{
225236ac495dSmrg 	  if (!REG_P (XEXP (addr, 0)))
225336ac495dSmrg 	    fatal_insn ("pre-decrement address is not a register", x);
225436ac495dSmrg 
225536ac495dSmrg 	  fprintf (file, "@-%s", reg_names[REGNO (XEXP (addr, 0))]);
225636ac495dSmrg 	}
225736ac495dSmrg       else if (GET_CODE (addr) == POST_INC)
225836ac495dSmrg 	{
225936ac495dSmrg 	  if (!REG_P (XEXP (addr, 0)))
226036ac495dSmrg 	    fatal_insn ("post-increment address is not a register", x);
226136ac495dSmrg 
226236ac495dSmrg 	  fprintf (file, "@%s+", reg_names[REGNO (XEXP (addr, 0))]);
226336ac495dSmrg 	}
226436ac495dSmrg       else
226536ac495dSmrg 	{
226636ac495dSmrg 	  fputs ("@(", file);
226736ac495dSmrg 	  output_address (GET_MODE (x), addr);
226836ac495dSmrg 	  fputc (')', file);
226936ac495dSmrg 	}
227036ac495dSmrg       break;
227136ac495dSmrg 
227236ac495dSmrg     case CONST_DOUBLE :
227336ac495dSmrg       /* We handle SFmode constants here as output_addr_const doesn't.  */
227436ac495dSmrg       if (GET_MODE (x) == SFmode)
227536ac495dSmrg 	{
227636ac495dSmrg 	  long l;
227736ac495dSmrg 
227836ac495dSmrg 	  REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l);
227936ac495dSmrg 	  fprintf (file, "0x%08lx", l);
228036ac495dSmrg 	  break;
228136ac495dSmrg 	}
228236ac495dSmrg 
228336ac495dSmrg       /* FALLTHRU */
228436ac495dSmrg       /* Let output_addr_const deal with it.  */
228536ac495dSmrg 
228636ac495dSmrg     default :
228736ac495dSmrg       output_addr_const (file, x);
228836ac495dSmrg       break;
228936ac495dSmrg     }
229036ac495dSmrg }
229136ac495dSmrg 
229236ac495dSmrg /* Print a memory address as an operand to reference that memory location.  */
229336ac495dSmrg 
229436ac495dSmrg static void
m32r_print_operand_address(FILE * file,machine_mode,rtx addr)229536ac495dSmrg m32r_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr)
229636ac495dSmrg {
229736ac495dSmrg   rtx base;
229836ac495dSmrg   rtx index = 0;
229936ac495dSmrg   int offset = 0;
230036ac495dSmrg 
230136ac495dSmrg   switch (GET_CODE (addr))
230236ac495dSmrg     {
230336ac495dSmrg     case REG :
230436ac495dSmrg       fputs (reg_names[REGNO (addr)], file);
230536ac495dSmrg       break;
230636ac495dSmrg 
230736ac495dSmrg     case PLUS :
230836ac495dSmrg       if (CONST_INT_P (XEXP (addr, 0)))
230936ac495dSmrg 	offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);
231036ac495dSmrg       else if (CONST_INT_P (XEXP (addr, 1)))
231136ac495dSmrg 	offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);
231236ac495dSmrg       else
231336ac495dSmrg 	base = XEXP (addr, 0), index = XEXP (addr, 1);
231436ac495dSmrg       if (REG_P (base))
231536ac495dSmrg 	{
231636ac495dSmrg 	  /* Print the offset first (if present) to conform to the manual.  */
231736ac495dSmrg 	  if (index == 0)
231836ac495dSmrg 	    {
231936ac495dSmrg 	      if (offset != 0)
232036ac495dSmrg 		fprintf (file, "%d,", offset);
232136ac495dSmrg 	      fputs (reg_names[REGNO (base)], file);
232236ac495dSmrg 	    }
232336ac495dSmrg 	  /* The chip doesn't support this, but left in for generality.  */
232436ac495dSmrg 	  else if (REG_P (index))
232536ac495dSmrg 	    fprintf (file, "%s,%s",
232636ac495dSmrg 		     reg_names[REGNO (base)], reg_names[REGNO (index)]);
232736ac495dSmrg 	  /* Not sure this can happen, but leave in for now.  */
232836ac495dSmrg 	  else if (GET_CODE (index) == SYMBOL_REF)
232936ac495dSmrg 	    {
233036ac495dSmrg 	      output_addr_const (file, index);
233136ac495dSmrg 	      fputc (',', file);
233236ac495dSmrg 	      fputs (reg_names[REGNO (base)], file);
233336ac495dSmrg 	    }
233436ac495dSmrg 	  else
233536ac495dSmrg 	    fatal_insn ("bad address", addr);
233636ac495dSmrg 	}
233736ac495dSmrg       else if (GET_CODE (base) == LO_SUM)
233836ac495dSmrg 	{
233936ac495dSmrg 	  gcc_assert (!index && REG_P (XEXP (base, 0)));
234036ac495dSmrg 	  if (small_data_operand (XEXP (base, 1), VOIDmode))
234136ac495dSmrg 	    fputs ("sda(", file);
234236ac495dSmrg 	  else
234336ac495dSmrg 	    fputs ("low(", file);
234436ac495dSmrg 	  output_addr_const (file, plus_constant (Pmode, XEXP (base, 1),
234536ac495dSmrg 						  offset));
234636ac495dSmrg 	  fputs ("),", file);
234736ac495dSmrg 	  fputs (reg_names[REGNO (XEXP (base, 0))], file);
234836ac495dSmrg 	}
234936ac495dSmrg       else
235036ac495dSmrg 	fatal_insn ("bad address", addr);
235136ac495dSmrg       break;
235236ac495dSmrg 
235336ac495dSmrg     case LO_SUM :
235436ac495dSmrg       if (!REG_P (XEXP (addr, 0)))
235536ac495dSmrg 	fatal_insn ("lo_sum not of register", addr);
235636ac495dSmrg       if (small_data_operand (XEXP (addr, 1), VOIDmode))
235736ac495dSmrg 	fputs ("sda(", file);
235836ac495dSmrg       else
235936ac495dSmrg 	fputs ("low(", file);
236036ac495dSmrg       output_addr_const (file, XEXP (addr, 1));
236136ac495dSmrg       fputs ("),", file);
236236ac495dSmrg       fputs (reg_names[REGNO (XEXP (addr, 0))], file);
236336ac495dSmrg       break;
236436ac495dSmrg 
236536ac495dSmrg     case PRE_INC :	/* Assume SImode.  */
236636ac495dSmrg       fprintf (file, "+%s", reg_names[REGNO (XEXP (addr, 0))]);
236736ac495dSmrg       break;
236836ac495dSmrg 
236936ac495dSmrg     case PRE_DEC :	/* Assume SImode.  */
237036ac495dSmrg       fprintf (file, "-%s", reg_names[REGNO (XEXP (addr, 0))]);
237136ac495dSmrg       break;
237236ac495dSmrg 
237336ac495dSmrg     case POST_INC :	/* Assume SImode.  */
237436ac495dSmrg       fprintf (file, "%s+", reg_names[REGNO (XEXP (addr, 0))]);
237536ac495dSmrg       break;
237636ac495dSmrg 
237736ac495dSmrg     default :
237836ac495dSmrg       output_addr_const (file, addr);
237936ac495dSmrg       break;
238036ac495dSmrg     }
238136ac495dSmrg }
238236ac495dSmrg 
238336ac495dSmrg static bool
m32r_print_operand_punct_valid_p(unsigned char code)238436ac495dSmrg m32r_print_operand_punct_valid_p (unsigned char code)
238536ac495dSmrg {
238636ac495dSmrg   return m32r_punct_chars[code];
238736ac495dSmrg }
238836ac495dSmrg 
238936ac495dSmrg /* Return true if the operands are the constants 0 and 1.  */
239036ac495dSmrg 
239136ac495dSmrg int
zero_and_one(rtx operand1,rtx operand2)239236ac495dSmrg zero_and_one (rtx operand1, rtx operand2)
239336ac495dSmrg {
239436ac495dSmrg   return
239536ac495dSmrg        CONST_INT_P (operand1)
239636ac495dSmrg     && CONST_INT_P (operand2)
239736ac495dSmrg     && (  ((INTVAL (operand1) == 0) && (INTVAL (operand2) == 1))
239836ac495dSmrg 	||((INTVAL (operand1) == 1) && (INTVAL (operand2) == 0)));
239936ac495dSmrg }
240036ac495dSmrg 
240136ac495dSmrg /* Generate the correct assembler code to handle the conditional loading of a
240236ac495dSmrg    value into a register.  It is known that the operands satisfy the
240336ac495dSmrg    conditional_move_operand() function above.  The destination is operand[0].
240436ac495dSmrg    The condition is operand [1].  The 'true' value is operand [2] and the
240536ac495dSmrg    'false' value is operand [3].  */
240636ac495dSmrg 
240736ac495dSmrg char *
emit_cond_move(rtx * operands,rtx insn ATTRIBUTE_UNUSED)240836ac495dSmrg emit_cond_move (rtx * operands, rtx insn ATTRIBUTE_UNUSED)
240936ac495dSmrg {
241036ac495dSmrg   static char buffer [100];
241136ac495dSmrg   const char * dest = reg_names [REGNO (operands [0])];
241236ac495dSmrg 
241336ac495dSmrg   buffer [0] = 0;
241436ac495dSmrg 
241536ac495dSmrg   /* Destination must be a register.  */
241636ac495dSmrg   gcc_assert (REG_P (operands [0]));
241736ac495dSmrg   gcc_assert (conditional_move_operand (operands [2], SImode));
241836ac495dSmrg   gcc_assert (conditional_move_operand (operands [3], SImode));
241936ac495dSmrg 
242036ac495dSmrg   /* Check to see if the test is reversed.  */
242136ac495dSmrg   if (GET_CODE (operands [1]) == NE)
242236ac495dSmrg     {
242336ac495dSmrg       rtx tmp = operands [2];
242436ac495dSmrg       operands [2] = operands [3];
242536ac495dSmrg       operands [3] = tmp;
242636ac495dSmrg     }
242736ac495dSmrg 
242836ac495dSmrg   sprintf (buffer, "mvfc %s, cbr", dest);
242936ac495dSmrg 
243036ac495dSmrg   /* If the true value was '0' then we need to invert the results of the move.  */
243136ac495dSmrg   if (INTVAL (operands [2]) == 0)
243236ac495dSmrg     sprintf (buffer + strlen (buffer), "\n\txor3 %s, %s, #1",
243336ac495dSmrg 	     dest, dest);
243436ac495dSmrg 
243536ac495dSmrg   return buffer;
243636ac495dSmrg }
243736ac495dSmrg 
243836ac495dSmrg /* Returns true if the registers contained in the two
243936ac495dSmrg    rtl expressions are different.  */
244036ac495dSmrg 
244136ac495dSmrg int
m32r_not_same_reg(rtx a,rtx b)244236ac495dSmrg m32r_not_same_reg (rtx a, rtx b)
244336ac495dSmrg {
244436ac495dSmrg   int reg_a = -1;
244536ac495dSmrg   int reg_b = -2;
244636ac495dSmrg 
244736ac495dSmrg   while (GET_CODE (a) == SUBREG)
244836ac495dSmrg     a = SUBREG_REG (a);
244936ac495dSmrg 
245036ac495dSmrg   if (REG_P (a))
245136ac495dSmrg     reg_a = REGNO (a);
245236ac495dSmrg 
245336ac495dSmrg   while (GET_CODE (b) == SUBREG)
245436ac495dSmrg     b = SUBREG_REG (b);
245536ac495dSmrg 
245636ac495dSmrg   if (REG_P (b))
245736ac495dSmrg     reg_b = REGNO (b);
245836ac495dSmrg 
245936ac495dSmrg   return reg_a != reg_b;
246036ac495dSmrg }
246136ac495dSmrg 
246236ac495dSmrg 
246336ac495dSmrg rtx
m32r_function_symbol(const char * name)246436ac495dSmrg m32r_function_symbol (const char *name)
246536ac495dSmrg {
246636ac495dSmrg   int extra_flags = 0;
246736ac495dSmrg   enum m32r_model model;
246836ac495dSmrg   rtx sym = gen_rtx_SYMBOL_REF (Pmode, name);
246936ac495dSmrg 
247036ac495dSmrg   if (TARGET_MODEL_SMALL)
247136ac495dSmrg     model = M32R_MODEL_SMALL;
247236ac495dSmrg   else if (TARGET_MODEL_MEDIUM)
247336ac495dSmrg     model = M32R_MODEL_MEDIUM;
247436ac495dSmrg   else if (TARGET_MODEL_LARGE)
247536ac495dSmrg     model = M32R_MODEL_LARGE;
247636ac495dSmrg   else
247736ac495dSmrg     gcc_unreachable (); /* Shouldn't happen.  */
247836ac495dSmrg   extra_flags |= model << SYMBOL_FLAG_MODEL_SHIFT;
247936ac495dSmrg 
248036ac495dSmrg   if (extra_flags)
248136ac495dSmrg     SYMBOL_REF_FLAGS (sym) |= extra_flags;
248236ac495dSmrg 
248336ac495dSmrg   return sym;
248436ac495dSmrg }
248536ac495dSmrg 
248636ac495dSmrg /* Use a library function to move some bytes.  */
248736ac495dSmrg 
248836ac495dSmrg static void
block_move_call(rtx dest_reg,rtx src_reg,rtx bytes_rtx)248936ac495dSmrg block_move_call (rtx dest_reg, rtx src_reg, rtx bytes_rtx)
249036ac495dSmrg {
249136ac495dSmrg   /* We want to pass the size as Pmode, which will normally be SImode
249236ac495dSmrg      but will be DImode if we are using 64-bit longs and pointers.  */
249336ac495dSmrg   if (GET_MODE (bytes_rtx) != VOIDmode
249436ac495dSmrg       && GET_MODE (bytes_rtx) != Pmode)
249536ac495dSmrg     bytes_rtx = convert_to_mode (Pmode, bytes_rtx, 1);
249636ac495dSmrg 
249736ac495dSmrg   emit_library_call (m32r_function_symbol ("memcpy"), LCT_NORMAL,
2498a2dc1f3fSmrg 		     VOIDmode, dest_reg, Pmode, src_reg, Pmode,
249936ac495dSmrg 		     convert_to_mode (TYPE_MODE (sizetype), bytes_rtx,
250036ac495dSmrg 				      TYPE_UNSIGNED (sizetype)),
250136ac495dSmrg 		     TYPE_MODE (sizetype));
250236ac495dSmrg }
250336ac495dSmrg 
250436ac495dSmrg /* Expand string/block move operations.
250536ac495dSmrg 
250636ac495dSmrg    operands[0] is the pointer to the destination.
250736ac495dSmrg    operands[1] is the pointer to the source.
250836ac495dSmrg    operands[2] is the number of bytes to move.
250936ac495dSmrg    operands[3] is the alignment.
251036ac495dSmrg 
251136ac495dSmrg    Returns 1 upon success, 0 otherwise.  */
251236ac495dSmrg 
251336ac495dSmrg int
m32r_expand_block_move(rtx operands[])251436ac495dSmrg m32r_expand_block_move (rtx operands[])
251536ac495dSmrg {
251636ac495dSmrg   rtx           orig_dst  = operands[0];
251736ac495dSmrg   rtx           orig_src  = operands[1];
251836ac495dSmrg   rtx           bytes_rtx = operands[2];
251936ac495dSmrg   rtx           align_rtx = operands[3];
252036ac495dSmrg   int           constp    = CONST_INT_P (bytes_rtx);
252136ac495dSmrg   HOST_WIDE_INT bytes     = constp ? INTVAL (bytes_rtx) : 0;
252236ac495dSmrg   int           align     = INTVAL (align_rtx);
252336ac495dSmrg   int           leftover;
252436ac495dSmrg   rtx           src_reg;
252536ac495dSmrg   rtx           dst_reg;
252636ac495dSmrg 
252736ac495dSmrg   if (constp && bytes <= 0)
252836ac495dSmrg     return 1;
252936ac495dSmrg 
253036ac495dSmrg   /* Move the address into scratch registers.  */
253136ac495dSmrg   dst_reg = copy_addr_to_reg (XEXP (orig_dst, 0));
253236ac495dSmrg   src_reg = copy_addr_to_reg (XEXP (orig_src, 0));
253336ac495dSmrg 
253436ac495dSmrg   if (align > UNITS_PER_WORD)
253536ac495dSmrg     align = UNITS_PER_WORD;
253636ac495dSmrg 
253736ac495dSmrg   /* If we prefer size over speed, always use a function call.
253836ac495dSmrg      If we do not know the size, use a function call.
253936ac495dSmrg      If the blocks are not word aligned, use a function call.  */
254036ac495dSmrg   if (optimize_size || ! constp || align != UNITS_PER_WORD)
254136ac495dSmrg     {
254236ac495dSmrg       block_move_call (dst_reg, src_reg, bytes_rtx);
254336ac495dSmrg       return 0;
254436ac495dSmrg     }
254536ac495dSmrg 
254636ac495dSmrg   leftover = bytes % MAX_MOVE_BYTES;
254736ac495dSmrg   bytes   -= leftover;
254836ac495dSmrg 
254936ac495dSmrg   /* If necessary, generate a loop to handle the bulk of the copy.  */
255036ac495dSmrg   if (bytes)
255136ac495dSmrg     {
255236ac495dSmrg       rtx_code_label *label = NULL;
255336ac495dSmrg       rtx final_src = NULL_RTX;
255436ac495dSmrg       rtx at_a_time = GEN_INT (MAX_MOVE_BYTES);
255536ac495dSmrg       rtx rounded_total = GEN_INT (bytes);
255636ac495dSmrg       rtx new_dst_reg = gen_reg_rtx (SImode);
255736ac495dSmrg       rtx new_src_reg = gen_reg_rtx (SImode);
255836ac495dSmrg 
255936ac495dSmrg       /* If we are going to have to perform this loop more than
256036ac495dSmrg 	 once, then generate a label and compute the address the
256136ac495dSmrg 	 source register will contain upon completion of the final
256236ac495dSmrg 	 iteration.  */
256336ac495dSmrg       if (bytes > MAX_MOVE_BYTES)
256436ac495dSmrg 	{
256536ac495dSmrg 	  final_src = gen_reg_rtx (Pmode);
256636ac495dSmrg 
256736ac495dSmrg 	  if (INT16_P(bytes))
256836ac495dSmrg 	    emit_insn (gen_addsi3 (final_src, src_reg, rounded_total));
256936ac495dSmrg 	  else
257036ac495dSmrg 	    {
257136ac495dSmrg 	      emit_insn (gen_movsi (final_src, rounded_total));
257236ac495dSmrg 	      emit_insn (gen_addsi3 (final_src, final_src, src_reg));
257336ac495dSmrg 	    }
257436ac495dSmrg 
257536ac495dSmrg 	  label = gen_label_rtx ();
257636ac495dSmrg 	  emit_label (label);
257736ac495dSmrg 	}
257836ac495dSmrg 
257936ac495dSmrg       /* It is known that output_block_move() will update src_reg to point
258036ac495dSmrg 	 to the word after the end of the source block, and dst_reg to point
258136ac495dSmrg 	 to the last word of the destination block, provided that the block
258236ac495dSmrg 	 is MAX_MOVE_BYTES long.  */
2583*8feb0f0bSmrg       emit_insn (gen_cpymemsi_internal (dst_reg, src_reg, at_a_time,
258436ac495dSmrg 					new_dst_reg, new_src_reg));
258536ac495dSmrg       emit_move_insn (dst_reg, new_dst_reg);
258636ac495dSmrg       emit_move_insn (src_reg, new_src_reg);
258736ac495dSmrg       emit_insn (gen_addsi3 (dst_reg, dst_reg, GEN_INT (4)));
258836ac495dSmrg 
258936ac495dSmrg       if (bytes > MAX_MOVE_BYTES)
259036ac495dSmrg 	{
259136ac495dSmrg 	  rtx test = gen_rtx_NE (VOIDmode, src_reg, final_src);
259236ac495dSmrg 	  emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label));
259336ac495dSmrg 	}
259436ac495dSmrg     }
259536ac495dSmrg 
259636ac495dSmrg   if (leftover)
2597*8feb0f0bSmrg     emit_insn (gen_cpymemsi_internal (dst_reg, src_reg, GEN_INT (leftover),
259836ac495dSmrg 				      gen_reg_rtx (SImode),
259936ac495dSmrg 				      gen_reg_rtx (SImode)));
260036ac495dSmrg   return 1;
260136ac495dSmrg }
260236ac495dSmrg 
260336ac495dSmrg 
260436ac495dSmrg /* Emit load/stores for a small constant word aligned block_move.
260536ac495dSmrg 
260636ac495dSmrg    operands[0] is the memory address of the destination.
260736ac495dSmrg    operands[1] is the memory address of the source.
260836ac495dSmrg    operands[2] is the number of bytes to move.
260936ac495dSmrg    operands[3] is a temp register.
261036ac495dSmrg    operands[4] is a temp register.  */
261136ac495dSmrg 
261236ac495dSmrg void
m32r_output_block_move(rtx insn ATTRIBUTE_UNUSED,rtx operands[])261336ac495dSmrg m32r_output_block_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[])
261436ac495dSmrg {
261536ac495dSmrg   HOST_WIDE_INT bytes = INTVAL (operands[2]);
261636ac495dSmrg   int		first_time;
261736ac495dSmrg   int		got_extra = 0;
261836ac495dSmrg 
261936ac495dSmrg   gcc_assert (bytes >= 1 && bytes <= MAX_MOVE_BYTES);
262036ac495dSmrg 
262136ac495dSmrg   /* We do not have a post-increment store available, so the first set of
262236ac495dSmrg      stores are done without any increment, then the remaining ones can use
262336ac495dSmrg      the pre-increment addressing mode.
262436ac495dSmrg 
262536ac495dSmrg      Note: expand_block_move() also relies upon this behavior when building
262636ac495dSmrg      loops to copy large blocks.  */
262736ac495dSmrg   first_time = 1;
262836ac495dSmrg 
262936ac495dSmrg   while (bytes > 0)
263036ac495dSmrg     {
263136ac495dSmrg       if (bytes >= 8)
263236ac495dSmrg 	{
263336ac495dSmrg 	  if (first_time)
263436ac495dSmrg 	    {
263536ac495dSmrg 	      output_asm_insn ("ld\t%5, %p1", operands);
263636ac495dSmrg 	      output_asm_insn ("ld\t%6, %p1", operands);
263736ac495dSmrg 	      output_asm_insn ("st\t%5, @%0", operands);
263836ac495dSmrg 	      output_asm_insn ("st\t%6, %s0", operands);
263936ac495dSmrg 	    }
264036ac495dSmrg 	  else
264136ac495dSmrg 	    {
264236ac495dSmrg 	      output_asm_insn ("ld\t%5, %p1", operands);
264336ac495dSmrg 	      output_asm_insn ("ld\t%6, %p1", operands);
264436ac495dSmrg 	      output_asm_insn ("st\t%5, %s0", operands);
264536ac495dSmrg 	      output_asm_insn ("st\t%6, %s0", operands);
264636ac495dSmrg 	    }
264736ac495dSmrg 
264836ac495dSmrg 	  bytes -= 8;
264936ac495dSmrg 	}
265036ac495dSmrg       else if (bytes >= 4)
265136ac495dSmrg 	{
265236ac495dSmrg 	  if (bytes > 4)
265336ac495dSmrg 	    got_extra = 1;
265436ac495dSmrg 
265536ac495dSmrg 	  output_asm_insn ("ld\t%5, %p1", operands);
265636ac495dSmrg 
265736ac495dSmrg 	  if (got_extra)
265836ac495dSmrg 	    output_asm_insn ("ld\t%6, %p1", operands);
265936ac495dSmrg 
266036ac495dSmrg 	  if (first_time)
266136ac495dSmrg 	    output_asm_insn ("st\t%5, @%0", operands);
266236ac495dSmrg 	  else
266336ac495dSmrg 	    output_asm_insn ("st\t%5, %s0", operands);
266436ac495dSmrg 
266536ac495dSmrg 	  bytes -= 4;
266636ac495dSmrg 	}
266736ac495dSmrg       else
266836ac495dSmrg 	{
266936ac495dSmrg 	  /* Get the entire next word, even though we do not want all of it.
267036ac495dSmrg 	     The saves us from doing several smaller loads, and we assume that
267136ac495dSmrg 	     we cannot cause a page fault when at least part of the word is in
267236ac495dSmrg 	     valid memory [since we don't get called if things aren't properly
267336ac495dSmrg 	     aligned].  */
267436ac495dSmrg 	  int dst_offset = first_time ? 0 : 4;
267536ac495dSmrg 	  /* The amount of increment we have to make to the
267636ac495dSmrg 	     destination pointer.  */
267736ac495dSmrg 	  int dst_inc_amount = dst_offset + bytes - 4;
267836ac495dSmrg 	  /* The same for the source pointer.  */
2679*8feb0f0bSmrg 	  int src_inc_amount = bytes - (got_extra ? 4 : 0);
268036ac495dSmrg 	  int last_shift;
268136ac495dSmrg 	  rtx my_operands[3];
268236ac495dSmrg 
268336ac495dSmrg 	  /* If got_extra is true then we have already loaded
268436ac495dSmrg 	     the next word as part of loading and storing the previous word.  */
268536ac495dSmrg 	  if (! got_extra)
268636ac495dSmrg 	    output_asm_insn ("ld\t%6, @%1", operands);
268736ac495dSmrg 
268836ac495dSmrg 	  if (bytes >= 2)
268936ac495dSmrg 	    {
269036ac495dSmrg 	      bytes -= 2;
269136ac495dSmrg 
269236ac495dSmrg 	      output_asm_insn ("sra3\t%5, %6, #16", operands);
269336ac495dSmrg 	      my_operands[0] = operands[5];
269436ac495dSmrg 	      my_operands[1] = GEN_INT (dst_offset);
269536ac495dSmrg 	      my_operands[2] = operands[0];
269636ac495dSmrg 	      output_asm_insn ("sth\t%0, @(%1,%2)", my_operands);
269736ac495dSmrg 
269836ac495dSmrg 	      /* If there is a byte left to store then increment the
269936ac495dSmrg 		 destination address and shift the contents of the source
270036ac495dSmrg 		 register down by 8 bits.  We could not do the address
270136ac495dSmrg 		 increment in the store half word instruction, because it does
270236ac495dSmrg 		 not have an auto increment mode.  */
270336ac495dSmrg 	      if (bytes > 0)  /* assert (bytes == 1) */
270436ac495dSmrg 		{
270536ac495dSmrg 		  dst_offset += 2;
270636ac495dSmrg 		  last_shift = 8;
270736ac495dSmrg 		}
270836ac495dSmrg 	    }
270936ac495dSmrg 	  else
271036ac495dSmrg 	    last_shift = 24;
271136ac495dSmrg 
271236ac495dSmrg 	  if (bytes > 0)
271336ac495dSmrg 	    {
271436ac495dSmrg 	      my_operands[0] = operands[6];
271536ac495dSmrg 	      my_operands[1] = GEN_INT (last_shift);
271636ac495dSmrg 	      output_asm_insn ("srai\t%0, #%1", my_operands);
271736ac495dSmrg 	      my_operands[0] = operands[6];
271836ac495dSmrg 	      my_operands[1] = GEN_INT (dst_offset);
271936ac495dSmrg 	      my_operands[2] = operands[0];
272036ac495dSmrg 	      output_asm_insn ("stb\t%0, @(%1,%2)", my_operands);
272136ac495dSmrg 	    }
272236ac495dSmrg 
272336ac495dSmrg 	  /* Update the destination pointer if needed.  We have to do
272436ac495dSmrg 	     this so that the patterns matches what we output in this
272536ac495dSmrg 	     function.  */
272636ac495dSmrg 	  if (dst_inc_amount
272736ac495dSmrg 	      && !find_reg_note (insn, REG_UNUSED, operands[0]))
272836ac495dSmrg 	    {
272936ac495dSmrg 	      my_operands[0] = operands[0];
273036ac495dSmrg 	      my_operands[1] = GEN_INT (dst_inc_amount);
273136ac495dSmrg 	      output_asm_insn ("addi\t%0, #%1", my_operands);
273236ac495dSmrg 	    }
273336ac495dSmrg 
273436ac495dSmrg 	  /* Update the source pointer if needed.  We have to do this
273536ac495dSmrg 	     so that the patterns matches what we output in this
273636ac495dSmrg 	     function.  */
273736ac495dSmrg 	  if (src_inc_amount
273836ac495dSmrg 	      && !find_reg_note (insn, REG_UNUSED, operands[1]))
273936ac495dSmrg 	    {
274036ac495dSmrg 	      my_operands[0] = operands[1];
274136ac495dSmrg 	      my_operands[1] = GEN_INT (src_inc_amount);
274236ac495dSmrg 	      output_asm_insn ("addi\t%0, #%1", my_operands);
274336ac495dSmrg 	    }
274436ac495dSmrg 
274536ac495dSmrg 	  bytes = 0;
274636ac495dSmrg 	}
274736ac495dSmrg 
274836ac495dSmrg       first_time = 0;
274936ac495dSmrg     }
275036ac495dSmrg }
275136ac495dSmrg 
2752a2dc1f3fSmrg /* Implement TARGET_HARD_REGNO_MODE_OK.  */
2753a2dc1f3fSmrg 
2754a2dc1f3fSmrg static bool
m32r_hard_regno_mode_ok(unsigned int regno,machine_mode mode)2755a2dc1f3fSmrg m32r_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
2756a2dc1f3fSmrg {
2757a2dc1f3fSmrg   return (m32r_hard_regno_modes[regno] & m32r_mode_class[mode]) != 0;
2758a2dc1f3fSmrg }
2759a2dc1f3fSmrg 
2760a2dc1f3fSmrg /* Implement TARGET_MODES_TIEABLE_P.  Tie QI/HI/SI modes together.  */
2761a2dc1f3fSmrg 
2762a2dc1f3fSmrg static bool
m32r_modes_tieable_p(machine_mode mode1,machine_mode mode2)2763a2dc1f3fSmrg m32r_modes_tieable_p (machine_mode mode1, machine_mode mode2)
2764a2dc1f3fSmrg {
2765a2dc1f3fSmrg   return (GET_MODE_CLASS (mode1) == MODE_INT
2766a2dc1f3fSmrg 	  && GET_MODE_CLASS (mode2) == MODE_INT
2767a2dc1f3fSmrg 	  && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
2768a2dc1f3fSmrg 	  && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD);
2769a2dc1f3fSmrg }
2770a2dc1f3fSmrg 
277136ac495dSmrg /* Return true if using NEW_REG in place of OLD_REG is ok.  */
277236ac495dSmrg 
277336ac495dSmrg int
m32r_hard_regno_rename_ok(unsigned int old_reg ATTRIBUTE_UNUSED,unsigned int new_reg)277436ac495dSmrg m32r_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
277536ac495dSmrg 			   unsigned int new_reg)
277636ac495dSmrg {
277736ac495dSmrg   /* Interrupt routines can't clobber any register that isn't already used.  */
277836ac495dSmrg   if (lookup_attribute ("interrupt", DECL_ATTRIBUTES (current_function_decl))
277936ac495dSmrg       && !df_regs_ever_live_p (new_reg))
278036ac495dSmrg     return 0;
278136ac495dSmrg 
278236ac495dSmrg   return 1;
278336ac495dSmrg }
278436ac495dSmrg 
278536ac495dSmrg rtx
m32r_return_addr(int count)278636ac495dSmrg m32r_return_addr (int count)
278736ac495dSmrg {
278836ac495dSmrg   if (count != 0)
278936ac495dSmrg     return const0_rtx;
279036ac495dSmrg 
279136ac495dSmrg   return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);
279236ac495dSmrg }
279336ac495dSmrg 
279436ac495dSmrg static void
m32r_trampoline_init(rtx m_tramp,tree fndecl,rtx chain_value)279536ac495dSmrg m32r_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
279636ac495dSmrg {
279736ac495dSmrg   emit_move_insn (adjust_address (m_tramp, SImode, 0),
279836ac495dSmrg 		  gen_int_mode (TARGET_LITTLE_ENDIAN ?
279936ac495dSmrg 				0x017e8e17 : 0x178e7e01, SImode));
280036ac495dSmrg   emit_move_insn (adjust_address (m_tramp, SImode, 4),
280136ac495dSmrg 		  gen_int_mode (TARGET_LITTLE_ENDIAN ?
280236ac495dSmrg 				0x0c00ae86 : 0x86ae000c, SImode));
280336ac495dSmrg   emit_move_insn (adjust_address (m_tramp, SImode, 8),
280436ac495dSmrg 		  gen_int_mode (TARGET_LITTLE_ENDIAN ?
280536ac495dSmrg 				0xe627871e : 0x1e8727e6, SImode));
280636ac495dSmrg   emit_move_insn (adjust_address (m_tramp, SImode, 12),
280736ac495dSmrg 		  gen_int_mode (TARGET_LITTLE_ENDIAN ?
280836ac495dSmrg 				0xc616c626 : 0x26c61fc6, SImode));
280936ac495dSmrg   emit_move_insn (adjust_address (m_tramp, SImode, 16),
281036ac495dSmrg 		  chain_value);
281136ac495dSmrg   emit_move_insn (adjust_address (m_tramp, SImode, 20),
281236ac495dSmrg 		  XEXP (DECL_RTL (fndecl), 0));
281336ac495dSmrg 
281436ac495dSmrg   if (m32r_cache_flush_trap >= 0)
281536ac495dSmrg     emit_insn (gen_flush_icache
281636ac495dSmrg 	       (validize_mem (adjust_address (m_tramp, SImode, 0)),
281736ac495dSmrg 		gen_int_mode (m32r_cache_flush_trap, SImode)));
281836ac495dSmrg   else if (m32r_cache_flush_func && m32r_cache_flush_func[0])
281936ac495dSmrg     emit_library_call (m32r_function_symbol (m32r_cache_flush_func),
2820a2dc1f3fSmrg 		       LCT_NORMAL, VOIDmode, XEXP (m_tramp, 0), Pmode,
282136ac495dSmrg 		       gen_int_mode (TRAMPOLINE_SIZE, SImode), SImode,
282236ac495dSmrg 		       GEN_INT (3), SImode);
282336ac495dSmrg }
282436ac495dSmrg 
282536ac495dSmrg /* True if X is a reg that can be used as a base reg.  */
282636ac495dSmrg 
282736ac495dSmrg static bool
m32r_rtx_ok_for_base_p(const_rtx x,bool strict)282836ac495dSmrg m32r_rtx_ok_for_base_p (const_rtx x, bool strict)
282936ac495dSmrg {
283036ac495dSmrg   if (! REG_P (x))
283136ac495dSmrg     return false;
283236ac495dSmrg 
283336ac495dSmrg   if (strict)
283436ac495dSmrg     {
283536ac495dSmrg       if (GPR_P (REGNO (x)))
283636ac495dSmrg 	return true;
283736ac495dSmrg     }
283836ac495dSmrg   else
283936ac495dSmrg     {
284036ac495dSmrg       if (GPR_P (REGNO (x))
284136ac495dSmrg 	  || REGNO (x) == ARG_POINTER_REGNUM
284236ac495dSmrg 	  || ! HARD_REGISTER_P (x))
284336ac495dSmrg 	return true;
284436ac495dSmrg     }
284536ac495dSmrg 
284636ac495dSmrg   return false;
284736ac495dSmrg }
284836ac495dSmrg 
284936ac495dSmrg static inline bool
m32r_rtx_ok_for_offset_p(const_rtx x)285036ac495dSmrg m32r_rtx_ok_for_offset_p (const_rtx x)
285136ac495dSmrg {
285236ac495dSmrg   return (CONST_INT_P (x) && INT16_P (INTVAL (x)));
285336ac495dSmrg }
285436ac495dSmrg 
285536ac495dSmrg static inline bool
m32r_legitimate_offset_addres_p(machine_mode mode ATTRIBUTE_UNUSED,const_rtx x,bool strict)285636ac495dSmrg m32r_legitimate_offset_addres_p (machine_mode mode ATTRIBUTE_UNUSED,
285736ac495dSmrg 				 const_rtx x, bool strict)
285836ac495dSmrg {
285936ac495dSmrg   if (GET_CODE (x) == PLUS
286036ac495dSmrg       && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict)
286136ac495dSmrg       && m32r_rtx_ok_for_offset_p (XEXP (x, 1)))
286236ac495dSmrg     return true;
286336ac495dSmrg 
286436ac495dSmrg   return false;
286536ac495dSmrg }
286636ac495dSmrg 
286736ac495dSmrg /* For LO_SUM addresses, do not allow them if the MODE is > 1 word,
286836ac495dSmrg    since more than one instruction will be required.  */
286936ac495dSmrg 
287036ac495dSmrg static inline bool
m32r_legitimate_lo_sum_addres_p(machine_mode mode,const_rtx x,bool strict)287136ac495dSmrg m32r_legitimate_lo_sum_addres_p (machine_mode mode, const_rtx x,
287236ac495dSmrg 				 bool strict)
287336ac495dSmrg {
287436ac495dSmrg   if (GET_CODE (x) == LO_SUM
287536ac495dSmrg       && (mode != BLKmode && GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
287636ac495dSmrg       && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict)
287736ac495dSmrg       && CONSTANT_P (XEXP (x, 1)))
287836ac495dSmrg     return true;
287936ac495dSmrg 
288036ac495dSmrg   return false;
288136ac495dSmrg }
288236ac495dSmrg 
288336ac495dSmrg /* Is this a load and increment operation.  */
288436ac495dSmrg 
288536ac495dSmrg static inline bool
m32r_load_postinc_p(machine_mode mode,const_rtx x,bool strict)288636ac495dSmrg m32r_load_postinc_p (machine_mode mode, const_rtx x, bool strict)
288736ac495dSmrg {
288836ac495dSmrg   if ((mode == SImode || mode == SFmode)
288936ac495dSmrg       && GET_CODE (x) == POST_INC
289036ac495dSmrg       && REG_P (XEXP (x, 0))
289136ac495dSmrg       && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict))
289236ac495dSmrg     return true;
289336ac495dSmrg 
289436ac495dSmrg   return false;
289536ac495dSmrg }
289636ac495dSmrg 
289736ac495dSmrg /* Is this an increment/decrement and store operation.  */
289836ac495dSmrg 
289936ac495dSmrg static inline bool
m32r_store_preinc_predec_p(machine_mode mode,const_rtx x,bool strict)290036ac495dSmrg m32r_store_preinc_predec_p (machine_mode mode, const_rtx x, bool strict)
290136ac495dSmrg {
290236ac495dSmrg   if ((mode == SImode || mode == SFmode)
290336ac495dSmrg       && (GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
290436ac495dSmrg       && REG_P (XEXP (x, 0))                           \
290536ac495dSmrg       && m32r_rtx_ok_for_base_p (XEXP (x, 0), strict))
290636ac495dSmrg     return true;
290736ac495dSmrg 
290836ac495dSmrg   return false;
290936ac495dSmrg }
291036ac495dSmrg 
291136ac495dSmrg /* Implement  TARGET_LEGITIMATE_ADDRESS_P.  */
291236ac495dSmrg 
291336ac495dSmrg static bool
m32r_legitimate_address_p(machine_mode mode,rtx x,bool strict)291436ac495dSmrg m32r_legitimate_address_p (machine_mode mode, rtx x, bool strict)
291536ac495dSmrg {
291636ac495dSmrg   if (m32r_rtx_ok_for_base_p (x, strict)
291736ac495dSmrg       || m32r_legitimate_offset_addres_p (mode, x, strict)
291836ac495dSmrg       || m32r_legitimate_lo_sum_addres_p (mode, x, strict)
291936ac495dSmrg       || m32r_load_postinc_p (mode, x, strict)
292036ac495dSmrg       || m32r_store_preinc_predec_p (mode, x, strict))
292136ac495dSmrg     return true;
292236ac495dSmrg 
292336ac495dSmrg   return false;
292436ac495dSmrg }
292536ac495dSmrg 
292636ac495dSmrg static void
m32r_conditional_register_usage(void)292736ac495dSmrg m32r_conditional_register_usage (void)
292836ac495dSmrg {
292936ac495dSmrg   if (flag_pic)
293036ac495dSmrg     fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
293136ac495dSmrg }
293236ac495dSmrg 
293336ac495dSmrg /* Implement TARGET_LEGITIMATE_CONSTANT_P
293436ac495dSmrg 
293536ac495dSmrg    We don't allow (plus symbol large-constant) as the relocations can't
293636ac495dSmrg    describe it.  INTVAL > 32767 handles both 16-bit and 24-bit relocations.
293736ac495dSmrg    We allow all CONST_DOUBLE's as the md file patterns will force the
293836ac495dSmrg    constant to memory if they can't handle them.  */
293936ac495dSmrg 
294036ac495dSmrg static bool
m32r_legitimate_constant_p(machine_mode mode ATTRIBUTE_UNUSED,rtx x)294136ac495dSmrg m32r_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
294236ac495dSmrg {
294336ac495dSmrg   return !(GET_CODE (x) == CONST
294436ac495dSmrg 	   && GET_CODE (XEXP (x, 0)) == PLUS
294536ac495dSmrg 	   && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
294636ac495dSmrg 	       || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
294736ac495dSmrg 	   && CONST_INT_P (XEXP (XEXP (x, 0), 1))
294836ac495dSmrg 	   && UINTVAL (XEXP (XEXP (x, 0), 1)) > 32767);
294936ac495dSmrg }
2950a2dc1f3fSmrg 
2951a2dc1f3fSmrg /* Implement TARGET_STARTING_FRAME_OFFSET.  The frame pointer points at
2952a2dc1f3fSmrg    the same place as the stack pointer, except if alloca has been called.  */
2953a2dc1f3fSmrg 
2954a2dc1f3fSmrg static HOST_WIDE_INT
m32r_starting_frame_offset(void)2955a2dc1f3fSmrg m32r_starting_frame_offset (void)
2956a2dc1f3fSmrg {
2957a2dc1f3fSmrg   return M32R_STACK_ALIGN (crtl->outgoing_args_size);
2958a2dc1f3fSmrg }
2959