xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/m32c/m32c.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg /* Target Code for R8C/M16C/M32C
2*8feb0f0bSmrg    Copyright (C) 2005-2020 Free Software Foundation, Inc.
336ac495dSmrg    Contributed by Red Hat.
436ac495dSmrg 
536ac495dSmrg    This file is part of GCC.
636ac495dSmrg 
736ac495dSmrg    GCC is free software; you can redistribute it and/or modify it
836ac495dSmrg    under the terms of the GNU General Public License as published
936ac495dSmrg    by the Free Software Foundation; either version 3, or (at your
1036ac495dSmrg    option) any later version.
1136ac495dSmrg 
1236ac495dSmrg    GCC is distributed in the hope that it will be useful, but WITHOUT
1336ac495dSmrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1436ac495dSmrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
1536ac495dSmrg    License for more details.
1636ac495dSmrg 
1736ac495dSmrg    You should have received a copy of the GNU General Public License
1836ac495dSmrg    along with GCC; see the file COPYING3.  If not see
1936ac495dSmrg    <http://www.gnu.org/licenses/>.  */
2036ac495dSmrg 
21a2dc1f3fSmrg #define IN_TARGET_CODE 1
22a2dc1f3fSmrg 
2336ac495dSmrg #include "config.h"
2436ac495dSmrg #include "system.h"
2536ac495dSmrg #include "coretypes.h"
2636ac495dSmrg #include "backend.h"
2736ac495dSmrg #include "target.h"
2836ac495dSmrg #include "rtl.h"
2936ac495dSmrg #include "tree.h"
30a2dc1f3fSmrg #include "stringpool.h"
31a2dc1f3fSmrg #include "attribs.h"
3236ac495dSmrg #include "df.h"
3336ac495dSmrg #include "memmodel.h"
3436ac495dSmrg #include "tm_p.h"
3536ac495dSmrg #include "optabs.h"
3636ac495dSmrg #include "regs.h"
3736ac495dSmrg #include "emit-rtl.h"
3836ac495dSmrg #include "recog.h"
3936ac495dSmrg #include "diagnostic-core.h"
4036ac495dSmrg #include "output.h"
4136ac495dSmrg #include "insn-attr.h"
4236ac495dSmrg #include "flags.h"
4336ac495dSmrg #include "reload.h"
4436ac495dSmrg #include "stor-layout.h"
4536ac495dSmrg #include "varasm.h"
4636ac495dSmrg #include "calls.h"
4736ac495dSmrg #include "explow.h"
4836ac495dSmrg #include "expr.h"
4936ac495dSmrg #include "tm-constrs.h"
5036ac495dSmrg #include "builtins.h"
5136ac495dSmrg 
5236ac495dSmrg /* This file should be included last.  */
5336ac495dSmrg #include "target-def.h"
5436ac495dSmrg 
5536ac495dSmrg /* Prototypes */
5636ac495dSmrg 
5736ac495dSmrg /* Used by m32c_pushm_popm.  */
5836ac495dSmrg typedef enum
5936ac495dSmrg {
6036ac495dSmrg   PP_pushm,
6136ac495dSmrg   PP_popm,
6236ac495dSmrg   PP_justcount
6336ac495dSmrg } Push_Pop_Type;
6436ac495dSmrg 
6536ac495dSmrg static bool m32c_function_needs_enter (void);
6636ac495dSmrg static tree interrupt_handler (tree *, tree, tree, int, bool *);
6736ac495dSmrg static tree function_vector_handler (tree *, tree, tree, int, bool *);
6836ac495dSmrg static int interrupt_p (tree node);
6936ac495dSmrg static int bank_switch_p (tree node);
7036ac495dSmrg static int fast_interrupt_p (tree node);
7136ac495dSmrg static int interrupt_p (tree node);
7236ac495dSmrg static bool m32c_asm_integer (rtx, unsigned int, int);
7336ac495dSmrg static int m32c_comp_type_attributes (const_tree, const_tree);
7436ac495dSmrg static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
7536ac495dSmrg static struct machine_function *m32c_init_machine_status (void);
7636ac495dSmrg static void m32c_insert_attributes (tree, tree *);
7736ac495dSmrg static bool m32c_legitimate_address_p (machine_mode, rtx, bool);
7836ac495dSmrg static bool m32c_addr_space_legitimate_address_p (machine_mode, rtx, bool, addr_space_t);
79*8feb0f0bSmrg static rtx m32c_function_arg (cumulative_args_t, const function_arg_info &);
80*8feb0f0bSmrg static bool m32c_pass_by_reference (cumulative_args_t,
81*8feb0f0bSmrg 				    const function_arg_info &);
82*8feb0f0bSmrg static void m32c_function_arg_advance (cumulative_args_t,
83*8feb0f0bSmrg 				       const function_arg_info &);
8436ac495dSmrg static unsigned int m32c_function_arg_boundary (machine_mode, const_tree);
8536ac495dSmrg static int m32c_pushm_popm (Push_Pop_Type);
8636ac495dSmrg static bool m32c_strict_argument_naming (cumulative_args_t);
8736ac495dSmrg static rtx m32c_struct_value_rtx (tree, int);
8836ac495dSmrg static rtx m32c_subreg (machine_mode, rtx, machine_mode, int);
8936ac495dSmrg static int need_to_save (int);
9036ac495dSmrg static rtx m32c_function_value (const_tree, const_tree, bool);
9136ac495dSmrg static rtx m32c_libcall_value (machine_mode, const_rtx);
9236ac495dSmrg 
9336ac495dSmrg /* Returns true if an address is specified, else false.  */
9436ac495dSmrg static bool m32c_get_pragma_address (const char *varname, unsigned *addr);
9536ac495dSmrg 
96a2dc1f3fSmrg static bool m32c_hard_regno_mode_ok (unsigned int, machine_mode);
97a2dc1f3fSmrg 
9836ac495dSmrg #define SYMBOL_FLAG_FUNCVEC_FUNCTION    (SYMBOL_FLAG_MACH_DEP << 0)
9936ac495dSmrg 
10036ac495dSmrg #define streq(a,b) (strcmp ((a), (b)) == 0)
10136ac495dSmrg 
10236ac495dSmrg /* Internal support routines */
10336ac495dSmrg 
10436ac495dSmrg /* Debugging statements are tagged with DEBUG0 only so that they can
10536ac495dSmrg    be easily enabled individually, by replacing the '0' with '1' as
10636ac495dSmrg    needed.  */
10736ac495dSmrg #define DEBUG0 0
10836ac495dSmrg #define DEBUG1 1
10936ac495dSmrg 
11036ac495dSmrg #if DEBUG0
11136ac495dSmrg #include "print-tree.h"
11236ac495dSmrg /* This is needed by some of the commented-out debug statements
11336ac495dSmrg    below.  */
11436ac495dSmrg static char const *class_names[LIM_REG_CLASSES] = REG_CLASS_NAMES;
11536ac495dSmrg #endif
11636ac495dSmrg static int class_contents[LIM_REG_CLASSES][1] = REG_CLASS_CONTENTS;
11736ac495dSmrg 
11836ac495dSmrg /* These are all to support encode_pattern().  */
11936ac495dSmrg static char pattern[30], *patternp;
12036ac495dSmrg static GTY(()) rtx patternr[30];
12136ac495dSmrg #define RTX_IS(x) (streq (pattern, x))
12236ac495dSmrg 
12336ac495dSmrg /* Some macros to simplify the logic throughout this file.  */
12436ac495dSmrg #define IS_MEM_REGNO(regno) ((regno) >= MEM0_REGNO && (regno) <= MEM7_REGNO)
12536ac495dSmrg #define IS_MEM_REG(rtx) (GET_CODE (rtx) == REG && IS_MEM_REGNO (REGNO (rtx)))
12636ac495dSmrg 
12736ac495dSmrg #define IS_CR_REGNO(regno) ((regno) >= SB_REGNO && (regno) <= PC_REGNO)
12836ac495dSmrg #define IS_CR_REG(rtx) (GET_CODE (rtx) == REG && IS_CR_REGNO (REGNO (rtx)))
12936ac495dSmrg 
13036ac495dSmrg static int
far_addr_space_p(rtx x)13136ac495dSmrg far_addr_space_p (rtx x)
13236ac495dSmrg {
13336ac495dSmrg   if (GET_CODE (x) != MEM)
13436ac495dSmrg     return 0;
13536ac495dSmrg #if DEBUG0
13636ac495dSmrg   fprintf(stderr, "\033[35mfar_addr_space: "); debug_rtx(x);
13736ac495dSmrg   fprintf(stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
13836ac495dSmrg #endif
13936ac495dSmrg   return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
14036ac495dSmrg }
14136ac495dSmrg 
14236ac495dSmrg /* We do most RTX matching by converting the RTX into a string, and
14336ac495dSmrg    using string compares.  This vastly simplifies the logic in many of
14436ac495dSmrg    the functions in this file.
14536ac495dSmrg 
14636ac495dSmrg    On exit, pattern[] has the encoded string (use RTX_IS("...") to
14736ac495dSmrg    compare it) and patternr[] has pointers to the nodes in the RTX
14836ac495dSmrg    corresponding to each character in the encoded string.  The latter
14936ac495dSmrg    is mostly used by print_operand().
15036ac495dSmrg 
15136ac495dSmrg    Unrecognized patterns have '?' in them; this shows up when the
15236ac495dSmrg    assembler complains about syntax errors.
15336ac495dSmrg */
15436ac495dSmrg 
15536ac495dSmrg static void
encode_pattern_1(rtx x)15636ac495dSmrg encode_pattern_1 (rtx x)
15736ac495dSmrg {
15836ac495dSmrg   int i;
15936ac495dSmrg 
16036ac495dSmrg   if (patternp == pattern + sizeof (pattern) - 2)
16136ac495dSmrg     {
16236ac495dSmrg       patternp[-1] = '?';
16336ac495dSmrg       return;
16436ac495dSmrg     }
16536ac495dSmrg 
16636ac495dSmrg   patternr[patternp - pattern] = x;
16736ac495dSmrg 
16836ac495dSmrg   switch (GET_CODE (x))
16936ac495dSmrg     {
17036ac495dSmrg     case REG:
17136ac495dSmrg       *patternp++ = 'r';
17236ac495dSmrg       break;
17336ac495dSmrg     case SUBREG:
17436ac495dSmrg       if (GET_MODE_SIZE (GET_MODE (x)) !=
17536ac495dSmrg 	  GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))
17636ac495dSmrg 	*patternp++ = 'S';
17736ac495dSmrg       if (GET_MODE (x) == PSImode
17836ac495dSmrg 	  && GET_CODE (XEXP (x, 0)) == REG)
17936ac495dSmrg 	*patternp++ = 'S';
18036ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
18136ac495dSmrg       break;
18236ac495dSmrg     case MEM:
18336ac495dSmrg       *patternp++ = 'm';
18436ac495dSmrg       /* FALLTHRU */
18536ac495dSmrg     case CONST:
18636ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
18736ac495dSmrg       break;
18836ac495dSmrg     case SIGN_EXTEND:
18936ac495dSmrg       *patternp++ = '^';
19036ac495dSmrg       *patternp++ = 'S';
19136ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
19236ac495dSmrg       break;
19336ac495dSmrg     case ZERO_EXTEND:
19436ac495dSmrg       *patternp++ = '^';
19536ac495dSmrg       *patternp++ = 'Z';
19636ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
19736ac495dSmrg       break;
19836ac495dSmrg     case PLUS:
19936ac495dSmrg       *patternp++ = '+';
20036ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
20136ac495dSmrg       encode_pattern_1 (XEXP (x, 1));
20236ac495dSmrg       break;
20336ac495dSmrg     case PRE_DEC:
20436ac495dSmrg       *patternp++ = '>';
20536ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
20636ac495dSmrg       break;
20736ac495dSmrg     case POST_INC:
20836ac495dSmrg       *patternp++ = '<';
20936ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
21036ac495dSmrg       break;
21136ac495dSmrg     case LO_SUM:
21236ac495dSmrg       *patternp++ = 'L';
21336ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
21436ac495dSmrg       encode_pattern_1 (XEXP (x, 1));
21536ac495dSmrg       break;
21636ac495dSmrg     case HIGH:
21736ac495dSmrg       *patternp++ = 'H';
21836ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
21936ac495dSmrg       break;
22036ac495dSmrg     case SYMBOL_REF:
22136ac495dSmrg       *patternp++ = 's';
22236ac495dSmrg       break;
22336ac495dSmrg     case LABEL_REF:
22436ac495dSmrg       *patternp++ = 'l';
22536ac495dSmrg       break;
22636ac495dSmrg     case CODE_LABEL:
22736ac495dSmrg       *patternp++ = 'c';
22836ac495dSmrg       break;
22936ac495dSmrg     case CONST_INT:
23036ac495dSmrg     case CONST_DOUBLE:
23136ac495dSmrg       *patternp++ = 'i';
23236ac495dSmrg       break;
23336ac495dSmrg     case UNSPEC:
23436ac495dSmrg       *patternp++ = 'u';
23536ac495dSmrg       *patternp++ = '0' + XCINT (x, 1, UNSPEC);
23636ac495dSmrg       for (i = 0; i < XVECLEN (x, 0); i++)
23736ac495dSmrg 	encode_pattern_1 (XVECEXP (x, 0, i));
23836ac495dSmrg       break;
23936ac495dSmrg     case USE:
24036ac495dSmrg       *patternp++ = 'U';
24136ac495dSmrg       break;
24236ac495dSmrg     case PARALLEL:
24336ac495dSmrg       *patternp++ = '|';
24436ac495dSmrg       for (i = 0; i < XVECLEN (x, 0); i++)
24536ac495dSmrg 	encode_pattern_1 (XVECEXP (x, 0, i));
24636ac495dSmrg       break;
24736ac495dSmrg     case EXPR_LIST:
24836ac495dSmrg       *patternp++ = 'E';
24936ac495dSmrg       encode_pattern_1 (XEXP (x, 0));
25036ac495dSmrg       if (XEXP (x, 1))
25136ac495dSmrg 	encode_pattern_1 (XEXP (x, 1));
25236ac495dSmrg       break;
25336ac495dSmrg     default:
25436ac495dSmrg       *patternp++ = '?';
25536ac495dSmrg #if DEBUG0
25636ac495dSmrg       fprintf (stderr, "can't encode pattern %s\n",
25736ac495dSmrg 	       GET_RTX_NAME (GET_CODE (x)));
25836ac495dSmrg       debug_rtx (x);
25936ac495dSmrg #endif
26036ac495dSmrg       break;
26136ac495dSmrg     }
26236ac495dSmrg }
26336ac495dSmrg 
26436ac495dSmrg static void
encode_pattern(rtx x)26536ac495dSmrg encode_pattern (rtx x)
26636ac495dSmrg {
26736ac495dSmrg   patternp = pattern;
26836ac495dSmrg   encode_pattern_1 (x);
26936ac495dSmrg   *patternp = 0;
27036ac495dSmrg }
27136ac495dSmrg 
27236ac495dSmrg /* Since register names indicate the mode they're used in, we need a
27336ac495dSmrg    way to determine which name to refer to the register with.  Called
27436ac495dSmrg    by print_operand().  */
27536ac495dSmrg 
27636ac495dSmrg static const char *
reg_name_with_mode(int regno,machine_mode mode)27736ac495dSmrg reg_name_with_mode (int regno, machine_mode mode)
27836ac495dSmrg {
27936ac495dSmrg   int mlen = GET_MODE_SIZE (mode);
28036ac495dSmrg   if (regno == R0_REGNO && mlen == 1)
28136ac495dSmrg     return "r0l";
28236ac495dSmrg   if (regno == R0_REGNO && (mlen == 3 || mlen == 4))
28336ac495dSmrg     return "r2r0";
28436ac495dSmrg   if (regno == R0_REGNO && mlen == 6)
28536ac495dSmrg     return "r2r1r0";
28636ac495dSmrg   if (regno == R0_REGNO && mlen == 8)
28736ac495dSmrg     return "r3r1r2r0";
28836ac495dSmrg   if (regno == R1_REGNO && mlen == 1)
28936ac495dSmrg     return "r1l";
29036ac495dSmrg   if (regno == R1_REGNO && (mlen == 3 || mlen == 4))
29136ac495dSmrg     return "r3r1";
29236ac495dSmrg   if (regno == A0_REGNO && TARGET_A16 && (mlen == 3 || mlen == 4))
29336ac495dSmrg     return "a1a0";
29436ac495dSmrg   return reg_names[regno];
29536ac495dSmrg }
29636ac495dSmrg 
29736ac495dSmrg /* How many bytes a register uses on stack when it's pushed.  We need
29836ac495dSmrg    to know this because the push opcode needs to explicitly indicate
29936ac495dSmrg    the size of the register, even though the name of the register
30036ac495dSmrg    already tells it that.  Used by m32c_output_reg_{push,pop}, which
30136ac495dSmrg    is only used through calls to ASM_OUTPUT_REG_{PUSH,POP}.  */
30236ac495dSmrg 
30336ac495dSmrg static int
reg_push_size(int regno)30436ac495dSmrg reg_push_size (int regno)
30536ac495dSmrg {
30636ac495dSmrg   switch (regno)
30736ac495dSmrg     {
30836ac495dSmrg     case R0_REGNO:
30936ac495dSmrg     case R1_REGNO:
31036ac495dSmrg       return 2;
31136ac495dSmrg     case R2_REGNO:
31236ac495dSmrg     case R3_REGNO:
31336ac495dSmrg     case FLG_REGNO:
31436ac495dSmrg       return 2;
31536ac495dSmrg     case A0_REGNO:
31636ac495dSmrg     case A1_REGNO:
31736ac495dSmrg     case SB_REGNO:
31836ac495dSmrg     case FB_REGNO:
31936ac495dSmrg     case SP_REGNO:
32036ac495dSmrg       if (TARGET_A16)
32136ac495dSmrg 	return 2;
32236ac495dSmrg       else
32336ac495dSmrg 	return 3;
32436ac495dSmrg     default:
32536ac495dSmrg       gcc_unreachable ();
32636ac495dSmrg     }
32736ac495dSmrg }
32836ac495dSmrg 
32936ac495dSmrg /* Given two register classes, find the largest intersection between
33036ac495dSmrg    them.  If there is no intersection, return RETURNED_IF_EMPTY
33136ac495dSmrg    instead.  */
33236ac495dSmrg static reg_class_t
reduce_class(reg_class_t original_class,reg_class_t limiting_class,reg_class_t returned_if_empty)33336ac495dSmrg reduce_class (reg_class_t original_class, reg_class_t limiting_class,
33436ac495dSmrg 	      reg_class_t returned_if_empty)
33536ac495dSmrg {
33636ac495dSmrg   HARD_REG_SET cc;
33736ac495dSmrg   int i;
33836ac495dSmrg   reg_class_t best = NO_REGS;
33936ac495dSmrg   unsigned int best_size = 0;
34036ac495dSmrg 
34136ac495dSmrg   if (original_class == limiting_class)
34236ac495dSmrg     return original_class;
34336ac495dSmrg 
344*8feb0f0bSmrg   cc = reg_class_contents[original_class] & reg_class_contents[limiting_class];
34536ac495dSmrg 
34636ac495dSmrg   for (i = 0; i < LIM_REG_CLASSES; i++)
34736ac495dSmrg     {
34836ac495dSmrg       if (hard_reg_set_subset_p (reg_class_contents[i], cc))
34936ac495dSmrg 	if (best_size < reg_class_size[i])
35036ac495dSmrg 	  {
35136ac495dSmrg 	    best = (reg_class_t) i;
35236ac495dSmrg 	    best_size = reg_class_size[i];
35336ac495dSmrg 	  }
35436ac495dSmrg 
35536ac495dSmrg     }
35636ac495dSmrg   if (best == NO_REGS)
35736ac495dSmrg     return returned_if_empty;
35836ac495dSmrg   return best;
35936ac495dSmrg }
36036ac495dSmrg 
36136ac495dSmrg /* Used by m32c_register_move_cost to determine if a move is
36236ac495dSmrg    impossibly expensive.  */
36336ac495dSmrg static bool
class_can_hold_mode(reg_class_t rclass,machine_mode mode)36436ac495dSmrg class_can_hold_mode (reg_class_t rclass, machine_mode mode)
36536ac495dSmrg {
36636ac495dSmrg   /* Cache the results:  0=untested  1=no  2=yes */
36736ac495dSmrg   static char results[LIM_REG_CLASSES][MAX_MACHINE_MODE];
36836ac495dSmrg 
36936ac495dSmrg   if (results[(int) rclass][mode] == 0)
37036ac495dSmrg     {
37136ac495dSmrg       int r;
37236ac495dSmrg       results[rclass][mode] = 1;
37336ac495dSmrg       for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
37436ac495dSmrg 	if (in_hard_reg_set_p (reg_class_contents[(int) rclass], mode, r)
375a2dc1f3fSmrg 	    && m32c_hard_regno_mode_ok (r, mode))
37636ac495dSmrg 	  {
37736ac495dSmrg 	    results[rclass][mode] = 2;
37836ac495dSmrg 	    break;
37936ac495dSmrg 	  }
38036ac495dSmrg     }
38136ac495dSmrg 
38236ac495dSmrg #if DEBUG0
38336ac495dSmrg   fprintf (stderr, "class %s can hold %s? %s\n",
38436ac495dSmrg 	   class_names[(int) rclass], mode_name[mode],
38536ac495dSmrg 	   (results[rclass][mode] == 2) ? "yes" : "no");
38636ac495dSmrg #endif
38736ac495dSmrg   return results[(int) rclass][mode] == 2;
38836ac495dSmrg }
38936ac495dSmrg 
39036ac495dSmrg /* Run-time Target Specification.  */
39136ac495dSmrg 
39236ac495dSmrg /* Memregs are memory locations that gcc treats like general
39336ac495dSmrg    registers, as there are a limited number of true registers and the
39436ac495dSmrg    m32c families can use memory in most places that registers can be
39536ac495dSmrg    used.
39636ac495dSmrg 
39736ac495dSmrg    However, since memory accesses are more expensive than registers,
39836ac495dSmrg    we allow the user to limit the number of memregs available, in
39936ac495dSmrg    order to try to persuade gcc to try harder to use real registers.
40036ac495dSmrg 
40136ac495dSmrg    Memregs are provided by lib1funcs.S.
40236ac495dSmrg */
40336ac495dSmrg 
40436ac495dSmrg int ok_to_change_target_memregs = TRUE;
40536ac495dSmrg 
40636ac495dSmrg /* Implements TARGET_OPTION_OVERRIDE.  */
40736ac495dSmrg 
40836ac495dSmrg #undef TARGET_OPTION_OVERRIDE
40936ac495dSmrg #define TARGET_OPTION_OVERRIDE m32c_option_override
41036ac495dSmrg 
41136ac495dSmrg static void
m32c_option_override(void)41236ac495dSmrg m32c_option_override (void)
41336ac495dSmrg {
41436ac495dSmrg   /* We limit memregs to 0..16, and provide a default.  */
41536ac495dSmrg   if (global_options_set.x_target_memregs)
41636ac495dSmrg     {
41736ac495dSmrg       if (target_memregs < 0 || target_memregs > 16)
418c0a68be4Smrg 	error ("invalid target memregs value %<%d%>", target_memregs);
41936ac495dSmrg     }
42036ac495dSmrg   else
42136ac495dSmrg     target_memregs = 16;
42236ac495dSmrg 
42336ac495dSmrg   if (TARGET_A24)
42436ac495dSmrg     flag_ivopts = 0;
42536ac495dSmrg 
42636ac495dSmrg   /* This target defaults to strict volatile bitfields.  */
42736ac495dSmrg   if (flag_strict_volatile_bitfields < 0 && abi_version_at_least(2))
42836ac495dSmrg     flag_strict_volatile_bitfields = 1;
42936ac495dSmrg 
43036ac495dSmrg   /* r8c/m16c have no 16-bit indirect call, so thunks are involved.
43136ac495dSmrg      This is always worse than an absolute call.  */
43236ac495dSmrg   if (TARGET_A16)
43336ac495dSmrg     flag_no_function_cse = 1;
43436ac495dSmrg 
43536ac495dSmrg   /* This wants to put insns between compares and their jumps.  */
43636ac495dSmrg   /* FIXME: The right solution is to properly trace the flags register
43736ac495dSmrg      values, but that is too much work for stage 4.  */
43836ac495dSmrg   flag_combine_stack_adjustments = 0;
43936ac495dSmrg }
44036ac495dSmrg 
44136ac495dSmrg #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE
44236ac495dSmrg #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE m32c_override_options_after_change
44336ac495dSmrg 
44436ac495dSmrg static void
m32c_override_options_after_change(void)44536ac495dSmrg m32c_override_options_after_change (void)
44636ac495dSmrg {
44736ac495dSmrg   if (TARGET_A16)
44836ac495dSmrg     flag_no_function_cse = 1;
44936ac495dSmrg }
45036ac495dSmrg 
45136ac495dSmrg /* Defining data structures for per-function information */
45236ac495dSmrg 
45336ac495dSmrg /* The usual; we set up our machine_function data.  */
45436ac495dSmrg static struct machine_function *
m32c_init_machine_status(void)45536ac495dSmrg m32c_init_machine_status (void)
45636ac495dSmrg {
45736ac495dSmrg   return ggc_cleared_alloc<machine_function> ();
45836ac495dSmrg }
45936ac495dSmrg 
46036ac495dSmrg /* Implements INIT_EXPANDERS.  We just set up to call the above
46136ac495dSmrg    function.  */
46236ac495dSmrg void
m32c_init_expanders(void)46336ac495dSmrg m32c_init_expanders (void)
46436ac495dSmrg {
46536ac495dSmrg   init_machine_status = m32c_init_machine_status;
46636ac495dSmrg }
46736ac495dSmrg 
46836ac495dSmrg /* Storage Layout */
46936ac495dSmrg 
47036ac495dSmrg /* Register Basics */
47136ac495dSmrg 
47236ac495dSmrg /* Basic Characteristics of Registers */
47336ac495dSmrg 
47436ac495dSmrg /* Whether a mode fits in a register is complex enough to warrant a
47536ac495dSmrg    table.  */
47636ac495dSmrg static struct
47736ac495dSmrg {
47836ac495dSmrg   char qi_regs;
47936ac495dSmrg   char hi_regs;
48036ac495dSmrg   char pi_regs;
48136ac495dSmrg   char si_regs;
48236ac495dSmrg   char di_regs;
48336ac495dSmrg } nregs_table[FIRST_PSEUDO_REGISTER] =
48436ac495dSmrg {
48536ac495dSmrg   { 1, 1, 2, 2, 4 },		/* r0 */
48636ac495dSmrg   { 0, 1, 0, 0, 0 },		/* r2 */
48736ac495dSmrg   { 1, 1, 2, 2, 0 },		/* r1 */
48836ac495dSmrg   { 0, 1, 0, 0, 0 },		/* r3 */
48936ac495dSmrg   { 0, 1, 1, 0, 0 },		/* a0 */
49036ac495dSmrg   { 0, 1, 1, 0, 0 },		/* a1 */
49136ac495dSmrg   { 0, 1, 1, 0, 0 },		/* sb */
49236ac495dSmrg   { 0, 1, 1, 0, 0 },		/* fb */
49336ac495dSmrg   { 0, 1, 1, 0, 0 },		/* sp */
49436ac495dSmrg   { 1, 1, 1, 0, 0 },		/* pc */
49536ac495dSmrg   { 0, 0, 0, 0, 0 },		/* fl */
49636ac495dSmrg   { 1, 1, 1, 0, 0 },		/* ap */
49736ac495dSmrg   { 1, 1, 2, 2, 4 },		/* mem0 */
49836ac495dSmrg   { 1, 1, 2, 2, 4 },		/* mem1 */
49936ac495dSmrg   { 1, 1, 2, 2, 4 },		/* mem2 */
50036ac495dSmrg   { 1, 1, 2, 2, 4 },		/* mem3 */
50136ac495dSmrg   { 1, 1, 2, 2, 4 },		/* mem4 */
50236ac495dSmrg   { 1, 1, 2, 2, 0 },		/* mem5 */
50336ac495dSmrg   { 1, 1, 2, 2, 0 },		/* mem6 */
50436ac495dSmrg   { 1, 1, 0, 0, 0 },		/* mem7 */
50536ac495dSmrg };
50636ac495dSmrg 
50736ac495dSmrg /* Implements TARGET_CONDITIONAL_REGISTER_USAGE.  We adjust the number
50836ac495dSmrg    of available memregs, and select which registers need to be preserved
50936ac495dSmrg    across calls based on the chip family.  */
51036ac495dSmrg 
51136ac495dSmrg #undef TARGET_CONDITIONAL_REGISTER_USAGE
51236ac495dSmrg #define TARGET_CONDITIONAL_REGISTER_USAGE m32c_conditional_register_usage
51336ac495dSmrg void
m32c_conditional_register_usage(void)51436ac495dSmrg m32c_conditional_register_usage (void)
51536ac495dSmrg {
51636ac495dSmrg   int i;
51736ac495dSmrg 
518a2dc1f3fSmrg   if (target_memregs >= 0 && target_memregs <= 16)
51936ac495dSmrg     {
52036ac495dSmrg       /* The command line option is bytes, but our "registers" are
52136ac495dSmrg 	 16-bit words.  */
52236ac495dSmrg       for (i = (target_memregs+1)/2; i < 8; i++)
52336ac495dSmrg 	{
52436ac495dSmrg 	  fixed_regs[MEM0_REGNO + i] = 1;
52536ac495dSmrg 	  CLEAR_HARD_REG_BIT (reg_class_contents[MEM_REGS], MEM0_REGNO + i);
52636ac495dSmrg 	}
52736ac495dSmrg     }
52836ac495dSmrg 
52936ac495dSmrg   /* M32CM and M32C preserve more registers across function calls.  */
53036ac495dSmrg   if (TARGET_A24)
53136ac495dSmrg     {
53236ac495dSmrg       call_used_regs[R1_REGNO] = 0;
53336ac495dSmrg       call_used_regs[R2_REGNO] = 0;
53436ac495dSmrg       call_used_regs[R3_REGNO] = 0;
53536ac495dSmrg       call_used_regs[A0_REGNO] = 0;
53636ac495dSmrg       call_used_regs[A1_REGNO] = 0;
53736ac495dSmrg     }
53836ac495dSmrg }
53936ac495dSmrg 
54036ac495dSmrg /* How Values Fit in Registers */
54136ac495dSmrg 
542a2dc1f3fSmrg /* Implements TARGET_HARD_REGNO_NREGS.  This is complicated by the fact that
54336ac495dSmrg    different registers are different sizes from each other, *and* may
54436ac495dSmrg    be different sizes in different chip families.  */
545a2dc1f3fSmrg static unsigned int
m32c_hard_regno_nregs_1(unsigned int regno,machine_mode mode)546a2dc1f3fSmrg m32c_hard_regno_nregs_1 (unsigned int regno, machine_mode mode)
54736ac495dSmrg {
54836ac495dSmrg   if (regno == FLG_REGNO && mode == CCmode)
54936ac495dSmrg     return 1;
55036ac495dSmrg   if (regno >= FIRST_PSEUDO_REGISTER)
55136ac495dSmrg     return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
55236ac495dSmrg 
55336ac495dSmrg   if (regno >= MEM0_REGNO && regno <= MEM7_REGNO)
55436ac495dSmrg     return (GET_MODE_SIZE (mode) + 1) / 2;
55536ac495dSmrg 
55636ac495dSmrg   if (GET_MODE_SIZE (mode) <= 1)
55736ac495dSmrg     return nregs_table[regno].qi_regs;
55836ac495dSmrg   if (GET_MODE_SIZE (mode) <= 2)
55936ac495dSmrg     return nregs_table[regno].hi_regs;
56036ac495dSmrg   if (regno == A0_REGNO && mode == SImode && TARGET_A16)
56136ac495dSmrg     return 2;
56236ac495dSmrg   if ((GET_MODE_SIZE (mode) <= 3 || mode == PSImode) && TARGET_A24)
56336ac495dSmrg     return nregs_table[regno].pi_regs;
56436ac495dSmrg   if (GET_MODE_SIZE (mode) <= 4)
56536ac495dSmrg     return nregs_table[regno].si_regs;
56636ac495dSmrg   if (GET_MODE_SIZE (mode) <= 8)
56736ac495dSmrg     return nregs_table[regno].di_regs;
56836ac495dSmrg   return 0;
56936ac495dSmrg }
57036ac495dSmrg 
571a2dc1f3fSmrg static unsigned int
m32c_hard_regno_nregs(unsigned int regno,machine_mode mode)572a2dc1f3fSmrg m32c_hard_regno_nregs (unsigned int regno, machine_mode mode)
57336ac495dSmrg {
574a2dc1f3fSmrg   unsigned int rv = m32c_hard_regno_nregs_1 (regno, mode);
57536ac495dSmrg   return rv ? rv : 1;
57636ac495dSmrg }
57736ac495dSmrg 
578a2dc1f3fSmrg /* Implement TARGET_HARD_REGNO_MODE_OK.  The above function does the work
57936ac495dSmrg    already; just test its return value.  */
580a2dc1f3fSmrg static bool
m32c_hard_regno_mode_ok(unsigned int regno,machine_mode mode)581a2dc1f3fSmrg m32c_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
58236ac495dSmrg {
58336ac495dSmrg   return m32c_hard_regno_nregs_1 (regno, mode) != 0;
58436ac495dSmrg }
58536ac495dSmrg 
586a2dc1f3fSmrg /* Implement TARGET_MODES_TIEABLE_P.  In general, modes aren't tieable since
58736ac495dSmrg    registers are all different sizes.  However, since most modes are
58836ac495dSmrg    bigger than our registers anyway, it's easier to implement this
58936ac495dSmrg    function that way, leaving QImode as the only unique case.  */
590a2dc1f3fSmrg static bool
m32c_modes_tieable_p(machine_mode m1,machine_mode m2)59136ac495dSmrg m32c_modes_tieable_p (machine_mode m1, machine_mode m2)
59236ac495dSmrg {
59336ac495dSmrg   if (GET_MODE_SIZE (m1) == GET_MODE_SIZE (m2))
59436ac495dSmrg     return 1;
59536ac495dSmrg 
59636ac495dSmrg #if 0
59736ac495dSmrg   if (m1 == QImode || m2 == QImode)
59836ac495dSmrg     return 0;
59936ac495dSmrg #endif
60036ac495dSmrg 
60136ac495dSmrg   return 1;
60236ac495dSmrg }
60336ac495dSmrg 
60436ac495dSmrg /* Register Classes */
60536ac495dSmrg 
60636ac495dSmrg /* Implements REGNO_REG_CLASS.  */
60736ac495dSmrg enum reg_class
m32c_regno_reg_class(int regno)60836ac495dSmrg m32c_regno_reg_class (int regno)
60936ac495dSmrg {
61036ac495dSmrg   switch (regno)
61136ac495dSmrg     {
61236ac495dSmrg     case R0_REGNO:
61336ac495dSmrg       return R0_REGS;
61436ac495dSmrg     case R1_REGNO:
61536ac495dSmrg       return R1_REGS;
61636ac495dSmrg     case R2_REGNO:
61736ac495dSmrg       return R2_REGS;
61836ac495dSmrg     case R3_REGNO:
61936ac495dSmrg       return R3_REGS;
62036ac495dSmrg     case A0_REGNO:
62136ac495dSmrg       return A0_REGS;
62236ac495dSmrg     case A1_REGNO:
62336ac495dSmrg       return A1_REGS;
62436ac495dSmrg     case SB_REGNO:
62536ac495dSmrg       return SB_REGS;
62636ac495dSmrg     case FB_REGNO:
62736ac495dSmrg       return FB_REGS;
62836ac495dSmrg     case SP_REGNO:
62936ac495dSmrg       return SP_REGS;
63036ac495dSmrg     case FLG_REGNO:
63136ac495dSmrg       return FLG_REGS;
63236ac495dSmrg     default:
63336ac495dSmrg       if (IS_MEM_REGNO (regno))
63436ac495dSmrg 	return MEM_REGS;
63536ac495dSmrg       return ALL_REGS;
63636ac495dSmrg     }
63736ac495dSmrg }
63836ac495dSmrg 
63936ac495dSmrg /* Implements REGNO_OK_FOR_BASE_P.  */
64036ac495dSmrg int
m32c_regno_ok_for_base_p(int regno)64136ac495dSmrg m32c_regno_ok_for_base_p (int regno)
64236ac495dSmrg {
64336ac495dSmrg   if (regno == A0_REGNO
64436ac495dSmrg       || regno == A1_REGNO || regno >= FIRST_PSEUDO_REGISTER)
64536ac495dSmrg     return 1;
64636ac495dSmrg   return 0;
64736ac495dSmrg }
64836ac495dSmrg 
64936ac495dSmrg /* Implements TARGET_PREFERRED_RELOAD_CLASS.  In general, prefer general
65036ac495dSmrg    registers of the appropriate size.  */
65136ac495dSmrg 
65236ac495dSmrg #undef TARGET_PREFERRED_RELOAD_CLASS
65336ac495dSmrg #define TARGET_PREFERRED_RELOAD_CLASS m32c_preferred_reload_class
65436ac495dSmrg 
65536ac495dSmrg static reg_class_t
m32c_preferred_reload_class(rtx x,reg_class_t rclass)65636ac495dSmrg m32c_preferred_reload_class (rtx x, reg_class_t rclass)
65736ac495dSmrg {
65836ac495dSmrg   reg_class_t newclass = rclass;
65936ac495dSmrg 
66036ac495dSmrg #if DEBUG0
66136ac495dSmrg   fprintf (stderr, "\npreferred_reload_class for %s is ",
66236ac495dSmrg 	   class_names[rclass]);
66336ac495dSmrg #endif
66436ac495dSmrg   if (rclass == NO_REGS)
66536ac495dSmrg     rclass = GET_MODE (x) == QImode ? HL_REGS : R03_REGS;
66636ac495dSmrg 
66736ac495dSmrg   if (reg_classes_intersect_p (rclass, CR_REGS))
66836ac495dSmrg     {
66936ac495dSmrg       switch (GET_MODE (x))
67036ac495dSmrg 	{
671a2dc1f3fSmrg 	case E_QImode:
67236ac495dSmrg 	  newclass = HL_REGS;
67336ac495dSmrg 	  break;
67436ac495dSmrg 	default:
67536ac495dSmrg 	  /*      newclass = HI_REGS; */
67636ac495dSmrg 	  break;
67736ac495dSmrg 	}
67836ac495dSmrg     }
67936ac495dSmrg 
68036ac495dSmrg   else if (newclass == QI_REGS && GET_MODE_SIZE (GET_MODE (x)) > 2)
68136ac495dSmrg     newclass = SI_REGS;
68236ac495dSmrg   else if (GET_MODE_SIZE (GET_MODE (x)) > 4
68336ac495dSmrg 	   && ! reg_class_subset_p (R03_REGS, rclass))
68436ac495dSmrg     newclass = DI_REGS;
68536ac495dSmrg 
68636ac495dSmrg   rclass = reduce_class (rclass, newclass, rclass);
68736ac495dSmrg 
68836ac495dSmrg   if (GET_MODE (x) == QImode)
68936ac495dSmrg     rclass = reduce_class (rclass, HL_REGS, rclass);
69036ac495dSmrg 
69136ac495dSmrg #if DEBUG0
69236ac495dSmrg   fprintf (stderr, "%s\n", class_names[rclass]);
69336ac495dSmrg   debug_rtx (x);
69436ac495dSmrg 
69536ac495dSmrg   if (GET_CODE (x) == MEM
69636ac495dSmrg       && GET_CODE (XEXP (x, 0)) == PLUS
69736ac495dSmrg       && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
69836ac495dSmrg     fprintf (stderr, "Glorm!\n");
69936ac495dSmrg #endif
70036ac495dSmrg   return rclass;
70136ac495dSmrg }
70236ac495dSmrg 
70336ac495dSmrg /* Implements TARGET_PREFERRED_OUTPUT_RELOAD_CLASS.  */
70436ac495dSmrg 
70536ac495dSmrg #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
70636ac495dSmrg #define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS m32c_preferred_output_reload_class
70736ac495dSmrg 
70836ac495dSmrg static reg_class_t
m32c_preferred_output_reload_class(rtx x,reg_class_t rclass)70936ac495dSmrg m32c_preferred_output_reload_class (rtx x, reg_class_t rclass)
71036ac495dSmrg {
71136ac495dSmrg   return m32c_preferred_reload_class (x, rclass);
71236ac495dSmrg }
71336ac495dSmrg 
71436ac495dSmrg /* Implements LIMIT_RELOAD_CLASS.  We basically want to avoid using
71536ac495dSmrg    address registers for reloads since they're needed for address
71636ac495dSmrg    reloads.  */
71736ac495dSmrg int
m32c_limit_reload_class(machine_mode mode,int rclass)71836ac495dSmrg m32c_limit_reload_class (machine_mode mode, int rclass)
71936ac495dSmrg {
72036ac495dSmrg #if DEBUG0
72136ac495dSmrg   fprintf (stderr, "limit_reload_class for %s: %s ->",
72236ac495dSmrg 	   mode_name[mode], class_names[rclass]);
72336ac495dSmrg #endif
72436ac495dSmrg 
72536ac495dSmrg   if (mode == QImode)
72636ac495dSmrg     rclass = reduce_class (rclass, HL_REGS, rclass);
72736ac495dSmrg   else if (mode == HImode)
72836ac495dSmrg     rclass = reduce_class (rclass, HI_REGS, rclass);
72936ac495dSmrg   else if (mode == SImode)
73036ac495dSmrg     rclass = reduce_class (rclass, SI_REGS, rclass);
73136ac495dSmrg 
73236ac495dSmrg   if (rclass != A_REGS)
73336ac495dSmrg     rclass = reduce_class (rclass, DI_REGS, rclass);
73436ac495dSmrg 
73536ac495dSmrg #if DEBUG0
73636ac495dSmrg   fprintf (stderr, " %s\n", class_names[rclass]);
73736ac495dSmrg #endif
73836ac495dSmrg   return rclass;
73936ac495dSmrg }
74036ac495dSmrg 
74136ac495dSmrg /* Implements SECONDARY_RELOAD_CLASS.  QImode have to be reloaded in
74236ac495dSmrg    r0 or r1, as those are the only real QImode registers.  CR regs get
74336ac495dSmrg    reloaded through appropriately sized general or address
74436ac495dSmrg    registers.  */
74536ac495dSmrg int
m32c_secondary_reload_class(int rclass,machine_mode mode,rtx x)74636ac495dSmrg m32c_secondary_reload_class (int rclass, machine_mode mode, rtx x)
74736ac495dSmrg {
74836ac495dSmrg   int cc = class_contents[rclass][0];
74936ac495dSmrg #if DEBUG0
75036ac495dSmrg   fprintf (stderr, "\nsecondary reload class %s %s\n",
75136ac495dSmrg 	   class_names[rclass], mode_name[mode]);
75236ac495dSmrg   debug_rtx (x);
75336ac495dSmrg #endif
75436ac495dSmrg   if (mode == QImode
75536ac495dSmrg       && GET_CODE (x) == MEM && (cc & ~class_contents[R23_REGS][0]) == 0)
75636ac495dSmrg     return QI_REGS;
75736ac495dSmrg   if (reg_classes_intersect_p (rclass, CR_REGS)
75836ac495dSmrg       && GET_CODE (x) == REG
75936ac495dSmrg       && REGNO (x) >= SB_REGNO && REGNO (x) <= SP_REGNO)
76036ac495dSmrg     return (TARGET_A16 || mode == HImode) ? HI_REGS : A_REGS;
76136ac495dSmrg   return NO_REGS;
76236ac495dSmrg }
76336ac495dSmrg 
76436ac495dSmrg /* Implements TARGET_CLASS_LIKELY_SPILLED_P.  A_REGS is needed for address
76536ac495dSmrg    reloads.  */
76636ac495dSmrg 
76736ac495dSmrg #undef TARGET_CLASS_LIKELY_SPILLED_P
76836ac495dSmrg #define TARGET_CLASS_LIKELY_SPILLED_P m32c_class_likely_spilled_p
76936ac495dSmrg 
77036ac495dSmrg static bool
m32c_class_likely_spilled_p(reg_class_t regclass)77136ac495dSmrg m32c_class_likely_spilled_p (reg_class_t regclass)
77236ac495dSmrg {
77336ac495dSmrg   if (regclass == A_REGS)
77436ac495dSmrg     return true;
77536ac495dSmrg 
77636ac495dSmrg   return (reg_class_size[(int) regclass] == 1);
77736ac495dSmrg }
77836ac495dSmrg 
77936ac495dSmrg /* Implements TARGET_CLASS_MAX_NREGS.  We calculate this according to its
78036ac495dSmrg    documented meaning, to avoid potential inconsistencies with actual
78136ac495dSmrg    class definitions.  */
78236ac495dSmrg 
78336ac495dSmrg #undef TARGET_CLASS_MAX_NREGS
78436ac495dSmrg #define TARGET_CLASS_MAX_NREGS m32c_class_max_nregs
78536ac495dSmrg 
78636ac495dSmrg static unsigned char
m32c_class_max_nregs(reg_class_t regclass,machine_mode mode)78736ac495dSmrg m32c_class_max_nregs (reg_class_t regclass, machine_mode mode)
78836ac495dSmrg {
78936ac495dSmrg   int rn;
79036ac495dSmrg   unsigned char max = 0;
79136ac495dSmrg 
79236ac495dSmrg   for (rn = 0; rn < FIRST_PSEUDO_REGISTER; rn++)
79336ac495dSmrg     if (TEST_HARD_REG_BIT (reg_class_contents[(int) regclass], rn))
79436ac495dSmrg       {
79536ac495dSmrg 	unsigned char n = m32c_hard_regno_nregs (rn, mode);
79636ac495dSmrg 	if (max < n)
79736ac495dSmrg 	  max = n;
79836ac495dSmrg       }
79936ac495dSmrg   return max;
80036ac495dSmrg }
80136ac495dSmrg 
802a2dc1f3fSmrg /* Implements TARGET_CAN_CHANGE_MODE_CLASS.  Only r0 and r1 can change to
80336ac495dSmrg    QI (r0l, r1l) because the chip doesn't support QI ops on other
80436ac495dSmrg    registers (well, it does on a0/a1 but if we let gcc do that, reload
80536ac495dSmrg    suffers).  Otherwise, we allow changes to larger modes.  */
806a2dc1f3fSmrg static bool
m32c_can_change_mode_class(machine_mode from,machine_mode to,reg_class_t rclass)807a2dc1f3fSmrg m32c_can_change_mode_class (machine_mode from,
808a2dc1f3fSmrg 			    machine_mode to, reg_class_t rclass)
80936ac495dSmrg {
81036ac495dSmrg   int rn;
81136ac495dSmrg #if DEBUG0
812a2dc1f3fSmrg   fprintf (stderr, "can change from %s to %s in %s\n",
81336ac495dSmrg 	   mode_name[from], mode_name[to], class_names[rclass]);
81436ac495dSmrg #endif
81536ac495dSmrg 
81636ac495dSmrg   /* If the larger mode isn't allowed in any of these registers, we
81736ac495dSmrg      can't allow the change.  */
81836ac495dSmrg   for (rn = 0; rn < FIRST_PSEUDO_REGISTER; rn++)
81936ac495dSmrg     if (class_contents[rclass][0] & (1 << rn))
820a2dc1f3fSmrg       if (! m32c_hard_regno_mode_ok (rn, to))
821a2dc1f3fSmrg 	return false;
82236ac495dSmrg 
82336ac495dSmrg   if (to == QImode)
824a2dc1f3fSmrg     return (class_contents[rclass][0] & 0x1ffa) == 0;
82536ac495dSmrg 
82636ac495dSmrg   if (class_contents[rclass][0] & 0x0005	/* r0, r1 */
82736ac495dSmrg       && GET_MODE_SIZE (from) > 1)
828a2dc1f3fSmrg     return true;
82936ac495dSmrg   if (GET_MODE_SIZE (from) > 2)	/* all other regs */
830a2dc1f3fSmrg     return true;
83136ac495dSmrg 
832a2dc1f3fSmrg   return false;
83336ac495dSmrg }
83436ac495dSmrg 
83536ac495dSmrg /* Helpers for the rest of the file.  */
83636ac495dSmrg /* TRUE if the rtx is a REG rtx for the given register.  */
83736ac495dSmrg #define IS_REG(rtx,regno) (GET_CODE (rtx) == REG \
83836ac495dSmrg 			   && REGNO (rtx) == regno)
83936ac495dSmrg /* TRUE if the rtx is a pseudo - specifically, one we can use as a
84036ac495dSmrg    base register in address calculations (hence the "strict"
84136ac495dSmrg    argument).  */
84236ac495dSmrg #define IS_PSEUDO(rtx,strict) (!strict && GET_CODE (rtx) == REG \
84336ac495dSmrg 			       && (REGNO (rtx) == AP_REGNO \
84436ac495dSmrg 				   || REGNO (rtx) >= FIRST_PSEUDO_REGISTER))
84536ac495dSmrg 
84636ac495dSmrg #define A0_OR_PSEUDO(x) (IS_REG(x, A0_REGNO) || REGNO (x) >= FIRST_PSEUDO_REGISTER)
84736ac495dSmrg 
84836ac495dSmrg /* Implements matching for constraints (see next function too).  'S' is
84936ac495dSmrg    for memory constraints, plus "Rpa" for PARALLEL rtx's we use for
85036ac495dSmrg    call return values.  */
85136ac495dSmrg bool
m32c_matches_constraint_p(rtx value,int constraint)85236ac495dSmrg m32c_matches_constraint_p (rtx value, int constraint)
85336ac495dSmrg {
85436ac495dSmrg   encode_pattern (value);
85536ac495dSmrg 
85636ac495dSmrg   switch (constraint) {
85736ac495dSmrg   case CONSTRAINT_SF:
85836ac495dSmrg     return (far_addr_space_p (value)
85936ac495dSmrg 	    && ((RTX_IS ("mr")
86036ac495dSmrg 		 && A0_OR_PSEUDO (patternr[1])
86136ac495dSmrg 		 && GET_MODE (patternr[1]) == SImode)
86236ac495dSmrg 		|| (RTX_IS ("m+^Sri")
86336ac495dSmrg 		    && A0_OR_PSEUDO (patternr[4])
86436ac495dSmrg 		    && GET_MODE (patternr[4]) == HImode)
86536ac495dSmrg 		|| (RTX_IS ("m+^Srs")
86636ac495dSmrg 		    && A0_OR_PSEUDO (patternr[4])
86736ac495dSmrg 		    && GET_MODE (patternr[4]) == HImode)
86836ac495dSmrg 		|| (RTX_IS ("m+^S+ris")
86936ac495dSmrg 		    && A0_OR_PSEUDO (patternr[5])
87036ac495dSmrg 		    && GET_MODE (patternr[5]) == HImode)
87136ac495dSmrg 		|| RTX_IS ("ms")));
87236ac495dSmrg   case CONSTRAINT_Sd:
87336ac495dSmrg     {
87436ac495dSmrg       /* This is the common "src/dest" address */
87536ac495dSmrg       rtx r;
87636ac495dSmrg       if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0)))
87736ac495dSmrg 	return true;
87836ac495dSmrg       if (RTX_IS ("ms") || RTX_IS ("m+si"))
87936ac495dSmrg 	return true;
88036ac495dSmrg       if (RTX_IS ("m++rii"))
88136ac495dSmrg 	{
88236ac495dSmrg 	  if (REGNO (patternr[3]) == FB_REGNO
88336ac495dSmrg 	      && INTVAL (patternr[4]) == 0)
88436ac495dSmrg 	    return true;
88536ac495dSmrg 	}
88636ac495dSmrg       if (RTX_IS ("mr"))
88736ac495dSmrg 	r = patternr[1];
88836ac495dSmrg       else if (RTX_IS ("m+ri") || RTX_IS ("m+rs") || RTX_IS ("m+r+si"))
88936ac495dSmrg 	r = patternr[2];
89036ac495dSmrg       else
89136ac495dSmrg 	return false;
89236ac495dSmrg       if (REGNO (r) == SP_REGNO)
89336ac495dSmrg 	return false;
89436ac495dSmrg       return m32c_legitimate_address_p (GET_MODE (value), XEXP (value, 0), 1);
89536ac495dSmrg     }
89636ac495dSmrg   case CONSTRAINT_Sa:
89736ac495dSmrg     {
89836ac495dSmrg       rtx r;
89936ac495dSmrg       if (RTX_IS ("mr"))
90036ac495dSmrg 	r = patternr[1];
90136ac495dSmrg       else if (RTX_IS ("m+ri"))
90236ac495dSmrg 	r = patternr[2];
90336ac495dSmrg       else
90436ac495dSmrg 	return false;
90536ac495dSmrg       return (IS_REG (r, A0_REGNO) || IS_REG (r, A1_REGNO));
90636ac495dSmrg     }
90736ac495dSmrg   case CONSTRAINT_Si:
90836ac495dSmrg     return (RTX_IS ("mi") || RTX_IS ("ms") || RTX_IS ("m+si"));
90936ac495dSmrg   case CONSTRAINT_Ss:
91036ac495dSmrg     return ((RTX_IS ("mr")
91136ac495dSmrg 	     && (IS_REG (patternr[1], SP_REGNO)))
91236ac495dSmrg 	    || (RTX_IS ("m+ri") && (IS_REG (patternr[2], SP_REGNO))));
91336ac495dSmrg   case CONSTRAINT_Sf:
91436ac495dSmrg     return ((RTX_IS ("mr")
91536ac495dSmrg 	     && (IS_REG (patternr[1], FB_REGNO)))
91636ac495dSmrg 	    || (RTX_IS ("m+ri") && (IS_REG (patternr[2], FB_REGNO))));
91736ac495dSmrg   case CONSTRAINT_Sb:
91836ac495dSmrg     return ((RTX_IS ("mr")
91936ac495dSmrg 	     && (IS_REG (patternr[1], SB_REGNO)))
92036ac495dSmrg 	    || (RTX_IS ("m+ri") && (IS_REG (patternr[2], SB_REGNO))));
92136ac495dSmrg   case CONSTRAINT_Sp:
92236ac495dSmrg     /* Absolute addresses 0..0x1fff used for bit addressing (I/O ports) */
92336ac495dSmrg     return (RTX_IS ("mi")
92436ac495dSmrg 	    && !(INTVAL (patternr[1]) & ~0x1fff));
92536ac495dSmrg   case CONSTRAINT_S1:
92636ac495dSmrg     return r1h_operand (value, QImode);
92736ac495dSmrg   case CONSTRAINT_Rpa:
92836ac495dSmrg     return GET_CODE (value) == PARALLEL;
92936ac495dSmrg   default:
93036ac495dSmrg     return false;
93136ac495dSmrg   }
93236ac495dSmrg }
93336ac495dSmrg 
93436ac495dSmrg /* STACK AND CALLING */
93536ac495dSmrg 
93636ac495dSmrg /* Frame Layout */
93736ac495dSmrg 
93836ac495dSmrg /* Implements RETURN_ADDR_RTX.  Note that R8C and M16C push 24 bits
93936ac495dSmrg    (yes, THREE bytes) onto the stack for the return address, but we
94036ac495dSmrg    don't support pointers bigger than 16 bits on those chips.  This
94136ac495dSmrg    will likely wreak havoc with exception unwinding.  FIXME.  */
94236ac495dSmrg rtx
m32c_return_addr_rtx(int count)94336ac495dSmrg m32c_return_addr_rtx (int count)
94436ac495dSmrg {
94536ac495dSmrg   machine_mode mode;
94636ac495dSmrg   int offset;
94736ac495dSmrg   rtx ra_mem;
94836ac495dSmrg 
94936ac495dSmrg   if (count)
95036ac495dSmrg     return NULL_RTX;
95136ac495dSmrg   /* we want 2[$fb] */
95236ac495dSmrg 
95336ac495dSmrg   if (TARGET_A24)
95436ac495dSmrg     {
95536ac495dSmrg       /* It's four bytes */
95636ac495dSmrg       mode = PSImode;
95736ac495dSmrg       offset = 4;
95836ac495dSmrg     }
95936ac495dSmrg   else
96036ac495dSmrg     {
96136ac495dSmrg       /* FIXME: it's really 3 bytes */
96236ac495dSmrg       mode = HImode;
96336ac495dSmrg       offset = 2;
96436ac495dSmrg     }
96536ac495dSmrg 
96636ac495dSmrg   ra_mem =
96736ac495dSmrg     gen_rtx_MEM (mode, plus_constant (Pmode, gen_rtx_REG (Pmode, FP_REGNO),
96836ac495dSmrg 				      offset));
96936ac495dSmrg   return copy_to_mode_reg (mode, ra_mem);
97036ac495dSmrg }
97136ac495dSmrg 
97236ac495dSmrg /* Implements INCOMING_RETURN_ADDR_RTX.  See comment above.  */
97336ac495dSmrg rtx
m32c_incoming_return_addr_rtx(void)97436ac495dSmrg m32c_incoming_return_addr_rtx (void)
97536ac495dSmrg {
97636ac495dSmrg   /* we want [sp] */
97736ac495dSmrg   return gen_rtx_MEM (PSImode, gen_rtx_REG (PSImode, SP_REGNO));
97836ac495dSmrg }
97936ac495dSmrg 
98036ac495dSmrg /* Exception Handling Support */
98136ac495dSmrg 
98236ac495dSmrg /* Implements EH_RETURN_DATA_REGNO.  Choose registers able to hold
98336ac495dSmrg    pointers.  */
98436ac495dSmrg int
m32c_eh_return_data_regno(int n)98536ac495dSmrg m32c_eh_return_data_regno (int n)
98636ac495dSmrg {
98736ac495dSmrg   switch (n)
98836ac495dSmrg     {
98936ac495dSmrg     case 0:
99036ac495dSmrg       return MEM0_REGNO;
99136ac495dSmrg     case 1:
99236ac495dSmrg       return MEM0_REGNO+4;
99336ac495dSmrg     default:
99436ac495dSmrg       return INVALID_REGNUM;
99536ac495dSmrg     }
99636ac495dSmrg }
99736ac495dSmrg 
99836ac495dSmrg /* Implements EH_RETURN_STACKADJ_RTX.  Saved and used later in
99936ac495dSmrg    m32c_emit_eh_epilogue.  */
100036ac495dSmrg rtx
m32c_eh_return_stackadj_rtx(void)100136ac495dSmrg m32c_eh_return_stackadj_rtx (void)
100236ac495dSmrg {
100336ac495dSmrg   if (!cfun->machine->eh_stack_adjust)
100436ac495dSmrg     {
100536ac495dSmrg       rtx sa;
100636ac495dSmrg 
100736ac495dSmrg       sa = gen_rtx_REG (Pmode, R0_REGNO);
100836ac495dSmrg       cfun->machine->eh_stack_adjust = sa;
100936ac495dSmrg     }
101036ac495dSmrg   return cfun->machine->eh_stack_adjust;
101136ac495dSmrg }
101236ac495dSmrg 
101336ac495dSmrg /* Registers That Address the Stack Frame */
101436ac495dSmrg 
101536ac495dSmrg /* Implements DWARF_FRAME_REGNUM and DBX_REGISTER_NUMBER.  Note that
101636ac495dSmrg    the original spec called for dwarf numbers to vary with register
101736ac495dSmrg    width as well, for example, r0l, r0, and r2r0 would each have
101836ac495dSmrg    different dwarf numbers.  GCC doesn't support this, and we don't do
101936ac495dSmrg    it, and gdb seems to like it this way anyway.  */
102036ac495dSmrg unsigned int
m32c_dwarf_frame_regnum(int n)102136ac495dSmrg m32c_dwarf_frame_regnum (int n)
102236ac495dSmrg {
102336ac495dSmrg   switch (n)
102436ac495dSmrg     {
102536ac495dSmrg     case R0_REGNO:
102636ac495dSmrg       return 5;
102736ac495dSmrg     case R1_REGNO:
102836ac495dSmrg       return 6;
102936ac495dSmrg     case R2_REGNO:
103036ac495dSmrg       return 7;
103136ac495dSmrg     case R3_REGNO:
103236ac495dSmrg       return 8;
103336ac495dSmrg     case A0_REGNO:
103436ac495dSmrg       return 9;
103536ac495dSmrg     case A1_REGNO:
103636ac495dSmrg       return 10;
103736ac495dSmrg     case FB_REGNO:
103836ac495dSmrg       return 11;
103936ac495dSmrg     case SB_REGNO:
104036ac495dSmrg       return 19;
104136ac495dSmrg 
104236ac495dSmrg     case SP_REGNO:
104336ac495dSmrg       return 12;
104436ac495dSmrg     case PC_REGNO:
104536ac495dSmrg       return 13;
104636ac495dSmrg     default:
104736ac495dSmrg       return DWARF_FRAME_REGISTERS + 1;
104836ac495dSmrg     }
104936ac495dSmrg }
105036ac495dSmrg 
105136ac495dSmrg /* The frame looks like this:
105236ac495dSmrg 
105336ac495dSmrg    ap -> +------------------------------
105436ac495dSmrg          | Return address (3 or 4 bytes)
105536ac495dSmrg 	 | Saved FB (2 or 4 bytes)
105636ac495dSmrg    fb -> +------------------------------
105736ac495dSmrg 	 | local vars
105836ac495dSmrg          | register saves fb
105936ac495dSmrg 	 |        through r0 as needed
106036ac495dSmrg    sp -> +------------------------------
106136ac495dSmrg */
106236ac495dSmrg 
106336ac495dSmrg /* We use this to wrap all emitted insns in the prologue.  */
106436ac495dSmrg static rtx
F(rtx x)106536ac495dSmrg F (rtx x)
106636ac495dSmrg {
106736ac495dSmrg   RTX_FRAME_RELATED_P (x) = 1;
106836ac495dSmrg   return x;
106936ac495dSmrg }
107036ac495dSmrg 
107136ac495dSmrg /* This maps register numbers to the PUSHM/POPM bitfield, and tells us
107236ac495dSmrg    how much the stack pointer moves for each, for each cpu family.  */
107336ac495dSmrg static struct
107436ac495dSmrg {
107536ac495dSmrg   int reg1;
107636ac495dSmrg   int bit;
107736ac495dSmrg   int a16_bytes;
107836ac495dSmrg   int a24_bytes;
107936ac495dSmrg } pushm_info[] =
108036ac495dSmrg {
108136ac495dSmrg   /* These are in reverse push (nearest-to-sp) order.  */
108236ac495dSmrg   { R0_REGNO, 0x80, 2, 2 },
108336ac495dSmrg   { R1_REGNO, 0x40, 2, 2 },
108436ac495dSmrg   { R2_REGNO, 0x20, 2, 2 },
108536ac495dSmrg   { R3_REGNO, 0x10, 2, 2 },
108636ac495dSmrg   { A0_REGNO, 0x08, 2, 4 },
108736ac495dSmrg   { A1_REGNO, 0x04, 2, 4 },
108836ac495dSmrg   { SB_REGNO, 0x02, 2, 4 },
108936ac495dSmrg   { FB_REGNO, 0x01, 2, 4 }
109036ac495dSmrg };
109136ac495dSmrg 
109236ac495dSmrg #define PUSHM_N (sizeof(pushm_info)/sizeof(pushm_info[0]))
109336ac495dSmrg 
109436ac495dSmrg /* Returns TRUE if we need to save/restore the given register.  We
109536ac495dSmrg    save everything for exception handlers, so that any register can be
109636ac495dSmrg    unwound.  For interrupt handlers, we save everything if the handler
109736ac495dSmrg    calls something else (because we don't know what *that* function
109836ac495dSmrg    might do), but try to be a bit smarter if the handler is a leaf
109936ac495dSmrg    function.  We always save $a0, though, because we use that in the
110036ac495dSmrg    epilogue to copy $fb to $sp.  */
110136ac495dSmrg static int
need_to_save(int regno)110236ac495dSmrg need_to_save (int regno)
110336ac495dSmrg {
110436ac495dSmrg   if (fixed_regs[regno])
110536ac495dSmrg     return 0;
110636ac495dSmrg   if (crtl->calls_eh_return)
110736ac495dSmrg     return 1;
110836ac495dSmrg   if (regno == FP_REGNO)
110936ac495dSmrg     return 0;
111036ac495dSmrg   if (cfun->machine->is_interrupt
111136ac495dSmrg       && (!cfun->machine->is_leaf
111236ac495dSmrg 	  || (regno == A0_REGNO
111336ac495dSmrg 	      && m32c_function_needs_enter ())
111436ac495dSmrg 	  ))
111536ac495dSmrg     return 1;
111636ac495dSmrg   if (df_regs_ever_live_p (regno)
1117*8feb0f0bSmrg       && (!call_used_or_fixed_reg_p (regno) || cfun->machine->is_interrupt))
111836ac495dSmrg     return 1;
111936ac495dSmrg   return 0;
112036ac495dSmrg }
112136ac495dSmrg 
112236ac495dSmrg /* This function contains all the intelligence about saving and
112336ac495dSmrg    restoring registers.  It always figures out the register save set.
112436ac495dSmrg    When called with PP_justcount, it merely returns the size of the
112536ac495dSmrg    save set (for eliminating the frame pointer, for example).  When
112636ac495dSmrg    called with PP_pushm or PP_popm, it emits the appropriate
112736ac495dSmrg    instructions for saving (pushm) or restoring (popm) the
112836ac495dSmrg    registers.  */
112936ac495dSmrg static int
m32c_pushm_popm(Push_Pop_Type ppt)113036ac495dSmrg m32c_pushm_popm (Push_Pop_Type ppt)
113136ac495dSmrg {
113236ac495dSmrg   int reg_mask = 0;
113336ac495dSmrg   int byte_count = 0, bytes;
113436ac495dSmrg   int i;
113536ac495dSmrg   rtx dwarf_set[PUSHM_N];
113636ac495dSmrg   int n_dwarfs = 0;
113736ac495dSmrg   int nosave_mask = 0;
113836ac495dSmrg 
113936ac495dSmrg   if (crtl->return_rtx
114036ac495dSmrg       && GET_CODE (crtl->return_rtx) == PARALLEL
114136ac495dSmrg       && !(crtl->calls_eh_return || cfun->machine->is_interrupt))
114236ac495dSmrg     {
114336ac495dSmrg       rtx exp = XVECEXP (crtl->return_rtx, 0, 0);
114436ac495dSmrg       rtx rv = XEXP (exp, 0);
114536ac495dSmrg       int rv_bytes = GET_MODE_SIZE (GET_MODE (rv));
114636ac495dSmrg 
114736ac495dSmrg       if (rv_bytes > 2)
114836ac495dSmrg 	nosave_mask |= 0x20;	/* PSI, SI */
114936ac495dSmrg       else
115036ac495dSmrg 	nosave_mask |= 0xf0;	/* DF */
115136ac495dSmrg       if (rv_bytes > 4)
115236ac495dSmrg 	nosave_mask |= 0x50;	/* DI */
115336ac495dSmrg     }
115436ac495dSmrg 
115536ac495dSmrg   for (i = 0; i < (int) PUSHM_N; i++)
115636ac495dSmrg     {
115736ac495dSmrg       /* Skip if neither register needs saving.  */
115836ac495dSmrg       if (!need_to_save (pushm_info[i].reg1))
115936ac495dSmrg 	continue;
116036ac495dSmrg 
116136ac495dSmrg       if (pushm_info[i].bit & nosave_mask)
116236ac495dSmrg 	continue;
116336ac495dSmrg 
116436ac495dSmrg       reg_mask |= pushm_info[i].bit;
116536ac495dSmrg       bytes = TARGET_A16 ? pushm_info[i].a16_bytes : pushm_info[i].a24_bytes;
116636ac495dSmrg 
116736ac495dSmrg       if (ppt == PP_pushm)
116836ac495dSmrg 	{
116936ac495dSmrg 	  machine_mode mode = (bytes == 2) ? HImode : SImode;
117036ac495dSmrg 	  rtx addr;
117136ac495dSmrg 
117236ac495dSmrg 	  /* Always use stack_pointer_rtx instead of calling
117336ac495dSmrg 	     rtx_gen_REG ourselves.  Code elsewhere in GCC assumes
117436ac495dSmrg 	     that there is a single rtx representing the stack pointer,
117536ac495dSmrg 	     namely stack_pointer_rtx, and uses == to recognize it.  */
117636ac495dSmrg 	  addr = stack_pointer_rtx;
117736ac495dSmrg 
117836ac495dSmrg 	  if (byte_count != 0)
117936ac495dSmrg 	    addr = gen_rtx_PLUS (GET_MODE (addr), addr, GEN_INT (byte_count));
118036ac495dSmrg 
118136ac495dSmrg 	  dwarf_set[n_dwarfs++] =
118236ac495dSmrg 	    gen_rtx_SET (gen_rtx_MEM (mode, addr),
118336ac495dSmrg 			 gen_rtx_REG (mode, pushm_info[i].reg1));
118436ac495dSmrg 	  F (dwarf_set[n_dwarfs - 1]);
118536ac495dSmrg 
118636ac495dSmrg 	}
118736ac495dSmrg       byte_count += bytes;
118836ac495dSmrg     }
118936ac495dSmrg 
119036ac495dSmrg   if (cfun->machine->is_interrupt)
119136ac495dSmrg     {
119236ac495dSmrg       cfun->machine->intr_pushm = reg_mask & 0xfe;
119336ac495dSmrg       reg_mask = 0;
119436ac495dSmrg       byte_count = 0;
119536ac495dSmrg     }
119636ac495dSmrg 
119736ac495dSmrg   if (cfun->machine->is_interrupt)
119836ac495dSmrg     for (i = MEM0_REGNO; i <= MEM7_REGNO; i++)
119936ac495dSmrg       if (need_to_save (i))
120036ac495dSmrg 	{
120136ac495dSmrg 	  byte_count += 2;
120236ac495dSmrg 	  cfun->machine->intr_pushmem[i - MEM0_REGNO] = 1;
120336ac495dSmrg 	}
120436ac495dSmrg 
120536ac495dSmrg   if (ppt == PP_pushm && byte_count)
120636ac495dSmrg     {
120736ac495dSmrg       rtx note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (n_dwarfs + 1));
120836ac495dSmrg       rtx pushm;
120936ac495dSmrg 
121036ac495dSmrg       if (reg_mask)
121136ac495dSmrg 	{
121236ac495dSmrg 	  XVECEXP (note, 0, 0)
121336ac495dSmrg 	    = gen_rtx_SET (stack_pointer_rtx,
121436ac495dSmrg 			   gen_rtx_PLUS (GET_MODE (stack_pointer_rtx),
121536ac495dSmrg 					 stack_pointer_rtx,
121636ac495dSmrg 					 GEN_INT (-byte_count)));
121736ac495dSmrg 	  F (XVECEXP (note, 0, 0));
121836ac495dSmrg 
121936ac495dSmrg 	  for (i = 0; i < n_dwarfs; i++)
122036ac495dSmrg 	    XVECEXP (note, 0, i + 1) = dwarf_set[i];
122136ac495dSmrg 
122236ac495dSmrg 	  pushm = F (emit_insn (gen_pushm (GEN_INT (reg_mask))));
122336ac495dSmrg 
122436ac495dSmrg 	  add_reg_note (pushm, REG_FRAME_RELATED_EXPR, note);
122536ac495dSmrg 	}
122636ac495dSmrg 
122736ac495dSmrg       if (cfun->machine->is_interrupt)
122836ac495dSmrg 	for (i = MEM0_REGNO; i <= MEM7_REGNO; i++)
122936ac495dSmrg 	  if (cfun->machine->intr_pushmem[i - MEM0_REGNO])
123036ac495dSmrg 	    {
123136ac495dSmrg 	      if (TARGET_A16)
123236ac495dSmrg 		pushm = emit_insn (gen_pushhi_16 (gen_rtx_REG (HImode, i)));
123336ac495dSmrg 	      else
123436ac495dSmrg 		pushm = emit_insn (gen_pushhi_24 (gen_rtx_REG (HImode, i)));
123536ac495dSmrg 	      F (pushm);
123636ac495dSmrg 	    }
123736ac495dSmrg     }
123836ac495dSmrg   if (ppt == PP_popm && byte_count)
123936ac495dSmrg     {
124036ac495dSmrg       if (cfun->machine->is_interrupt)
124136ac495dSmrg 	for (i = MEM7_REGNO; i >= MEM0_REGNO; i--)
124236ac495dSmrg 	  if (cfun->machine->intr_pushmem[i - MEM0_REGNO])
124336ac495dSmrg 	    {
124436ac495dSmrg 	      if (TARGET_A16)
124536ac495dSmrg 		emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, i)));
124636ac495dSmrg 	      else
124736ac495dSmrg 		emit_insn (gen_pophi_24 (gen_rtx_REG (HImode, i)));
124836ac495dSmrg 	    }
124936ac495dSmrg       if (reg_mask)
125036ac495dSmrg 	emit_insn (gen_popm (GEN_INT (reg_mask)));
125136ac495dSmrg     }
125236ac495dSmrg 
125336ac495dSmrg   return byte_count;
125436ac495dSmrg }
125536ac495dSmrg 
125636ac495dSmrg /* Implements INITIAL_ELIMINATION_OFFSET.  See the comment above that
125736ac495dSmrg    diagrams our call frame.  */
125836ac495dSmrg int
m32c_initial_elimination_offset(int from,int to)125936ac495dSmrg m32c_initial_elimination_offset (int from, int to)
126036ac495dSmrg {
126136ac495dSmrg   int ofs = 0;
126236ac495dSmrg 
126336ac495dSmrg   if (from == AP_REGNO)
126436ac495dSmrg     {
126536ac495dSmrg       if (TARGET_A16)
126636ac495dSmrg 	ofs += 5;
126736ac495dSmrg       else
126836ac495dSmrg 	ofs += 8;
126936ac495dSmrg     }
127036ac495dSmrg 
127136ac495dSmrg   if (to == SP_REGNO)
127236ac495dSmrg     {
127336ac495dSmrg       ofs += m32c_pushm_popm (PP_justcount);
127436ac495dSmrg       ofs += get_frame_size ();
127536ac495dSmrg     }
127636ac495dSmrg 
127736ac495dSmrg   /* Account for push rounding.  */
127836ac495dSmrg   if (TARGET_A24)
127936ac495dSmrg     ofs = (ofs + 1) & ~1;
128036ac495dSmrg #if DEBUG0
128136ac495dSmrg   fprintf (stderr, "initial_elimination_offset from=%d to=%d, ofs=%d\n", from,
128236ac495dSmrg 	   to, ofs);
128336ac495dSmrg #endif
128436ac495dSmrg   return ofs;
128536ac495dSmrg }
128636ac495dSmrg 
128736ac495dSmrg /* Passing Function Arguments on the Stack */
128836ac495dSmrg 
128936ac495dSmrg /* Implements PUSH_ROUNDING.  The R8C and M16C have byte stacks, the
129036ac495dSmrg    M32C has word stacks.  */
1291a2dc1f3fSmrg poly_int64
m32c_push_rounding(poly_int64 n)1292a2dc1f3fSmrg m32c_push_rounding (poly_int64 n)
129336ac495dSmrg {
129436ac495dSmrg   if (TARGET_R8C || TARGET_M16C)
129536ac495dSmrg     return n;
129636ac495dSmrg   return (n + 1) & ~1;
129736ac495dSmrg }
129836ac495dSmrg 
129936ac495dSmrg /* Passing Arguments in Registers */
130036ac495dSmrg 
130136ac495dSmrg /* Implements TARGET_FUNCTION_ARG.  Arguments are passed partly in
130236ac495dSmrg    registers, partly on stack.  If our function returns a struct, a
130336ac495dSmrg    pointer to a buffer for it is at the top of the stack (last thing
130436ac495dSmrg    pushed).  The first few real arguments may be in registers as
130536ac495dSmrg    follows:
130636ac495dSmrg 
130736ac495dSmrg    R8C/M16C:	arg1 in r1 if it's QI or HI (else it's pushed on stack)
130836ac495dSmrg 		arg2 in r2 if it's HI (else pushed on stack)
130936ac495dSmrg 		rest on stack
131036ac495dSmrg    M32C:        arg1 in r0 if it's QI or HI (else it's pushed on stack)
131136ac495dSmrg 		rest on stack
131236ac495dSmrg 
131336ac495dSmrg    Structs are not passed in registers, even if they fit.  Only
131436ac495dSmrg    integer and pointer types are passed in registers.
131536ac495dSmrg 
131636ac495dSmrg    Note that when arg1 doesn't fit in r1, arg2 may still be passed in
131736ac495dSmrg    r2 if it fits.  */
131836ac495dSmrg #undef TARGET_FUNCTION_ARG
131936ac495dSmrg #define TARGET_FUNCTION_ARG m32c_function_arg
132036ac495dSmrg static rtx
m32c_function_arg(cumulative_args_t ca_v,const function_arg_info & arg)1321*8feb0f0bSmrg m32c_function_arg (cumulative_args_t ca_v, const function_arg_info &arg)
132236ac495dSmrg {
132336ac495dSmrg   CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
132436ac495dSmrg 
132536ac495dSmrg   /* Can return a reg, parallel, or 0 for stack */
132636ac495dSmrg   rtx rv = NULL_RTX;
132736ac495dSmrg #if DEBUG0
132836ac495dSmrg   fprintf (stderr, "func_arg %d (%s, %d)\n",
1329*8feb0f0bSmrg 	   ca->parm_num, mode_name[arg.mode], arg.named);
1330*8feb0f0bSmrg   debug_tree (arg.type);
133136ac495dSmrg #endif
133236ac495dSmrg 
1333*8feb0f0bSmrg   if (arg.end_marker_p ())
133436ac495dSmrg     return GEN_INT (0);
133536ac495dSmrg 
1336*8feb0f0bSmrg   if (ca->force_mem || !arg.named)
133736ac495dSmrg     {
133836ac495dSmrg #if DEBUG0
133936ac495dSmrg       fprintf (stderr, "func arg: force %d named %d, mem\n", ca->force_mem,
1340*8feb0f0bSmrg 	       arg.named);
134136ac495dSmrg #endif
134236ac495dSmrg       return NULL_RTX;
134336ac495dSmrg     }
134436ac495dSmrg 
1345*8feb0f0bSmrg   if (arg.type && INTEGRAL_TYPE_P (arg.type) && POINTER_TYPE_P (arg.type))
134636ac495dSmrg     return NULL_RTX;
134736ac495dSmrg 
1348*8feb0f0bSmrg   if (arg.aggregate_type_p ())
134936ac495dSmrg     return NULL_RTX;
135036ac495dSmrg 
135136ac495dSmrg   switch (ca->parm_num)
135236ac495dSmrg     {
135336ac495dSmrg     case 1:
1354*8feb0f0bSmrg       if (GET_MODE_SIZE (arg.mode) == 1 || GET_MODE_SIZE (arg.mode) == 2)
1355*8feb0f0bSmrg 	rv = gen_rtx_REG (arg.mode, TARGET_A16 ? R1_REGNO : R0_REGNO);
135636ac495dSmrg       break;
135736ac495dSmrg 
135836ac495dSmrg     case 2:
1359*8feb0f0bSmrg       if (TARGET_A16 && GET_MODE_SIZE (arg.mode) == 2)
1360*8feb0f0bSmrg 	rv = gen_rtx_REG (arg.mode, R2_REGNO);
136136ac495dSmrg       break;
136236ac495dSmrg     }
136336ac495dSmrg 
136436ac495dSmrg #if DEBUG0
136536ac495dSmrg   debug_rtx (rv);
136636ac495dSmrg #endif
136736ac495dSmrg   return rv;
136836ac495dSmrg }
136936ac495dSmrg 
137036ac495dSmrg #undef TARGET_PASS_BY_REFERENCE
137136ac495dSmrg #define TARGET_PASS_BY_REFERENCE m32c_pass_by_reference
137236ac495dSmrg static bool
m32c_pass_by_reference(cumulative_args_t,const function_arg_info &)1373*8feb0f0bSmrg m32c_pass_by_reference (cumulative_args_t, const function_arg_info &)
137436ac495dSmrg {
137536ac495dSmrg   return 0;
137636ac495dSmrg }
137736ac495dSmrg 
137836ac495dSmrg /* Implements INIT_CUMULATIVE_ARGS.  */
137936ac495dSmrg void
m32c_init_cumulative_args(CUMULATIVE_ARGS * ca,tree fntype,rtx libname ATTRIBUTE_UNUSED,tree fndecl,int n_named_args ATTRIBUTE_UNUSED)138036ac495dSmrg m32c_init_cumulative_args (CUMULATIVE_ARGS * ca,
138136ac495dSmrg 			   tree fntype,
138236ac495dSmrg 			   rtx libname ATTRIBUTE_UNUSED,
138336ac495dSmrg 			   tree fndecl,
138436ac495dSmrg 			   int n_named_args ATTRIBUTE_UNUSED)
138536ac495dSmrg {
138636ac495dSmrg   if (fntype && aggregate_value_p (TREE_TYPE (fntype), fndecl))
138736ac495dSmrg     ca->force_mem = 1;
138836ac495dSmrg   else
138936ac495dSmrg     ca->force_mem = 0;
139036ac495dSmrg   ca->parm_num = 1;
139136ac495dSmrg }
139236ac495dSmrg 
139336ac495dSmrg /* Implements TARGET_FUNCTION_ARG_ADVANCE.  force_mem is set for
139436ac495dSmrg    functions returning structures, so we always reset that.  Otherwise,
139536ac495dSmrg    we only need to know the sequence number of the argument to know what
139636ac495dSmrg    to do with it.  */
139736ac495dSmrg #undef TARGET_FUNCTION_ARG_ADVANCE
139836ac495dSmrg #define TARGET_FUNCTION_ARG_ADVANCE m32c_function_arg_advance
139936ac495dSmrg static void
m32c_function_arg_advance(cumulative_args_t ca_v,const function_arg_info &)140036ac495dSmrg m32c_function_arg_advance (cumulative_args_t ca_v,
1401*8feb0f0bSmrg 			   const function_arg_info &)
140236ac495dSmrg {
140336ac495dSmrg   CUMULATIVE_ARGS *ca = get_cumulative_args (ca_v);
140436ac495dSmrg 
140536ac495dSmrg   if (ca->force_mem)
140636ac495dSmrg     ca->force_mem = 0;
140736ac495dSmrg   else
140836ac495dSmrg     ca->parm_num++;
140936ac495dSmrg }
141036ac495dSmrg 
141136ac495dSmrg /* Implements TARGET_FUNCTION_ARG_BOUNDARY.  */
141236ac495dSmrg #undef TARGET_FUNCTION_ARG_BOUNDARY
141336ac495dSmrg #define TARGET_FUNCTION_ARG_BOUNDARY m32c_function_arg_boundary
141436ac495dSmrg static unsigned int
m32c_function_arg_boundary(machine_mode mode ATTRIBUTE_UNUSED,const_tree type ATTRIBUTE_UNUSED)141536ac495dSmrg m32c_function_arg_boundary (machine_mode mode ATTRIBUTE_UNUSED,
141636ac495dSmrg 			    const_tree type ATTRIBUTE_UNUSED)
141736ac495dSmrg {
141836ac495dSmrg   return (TARGET_A16 ? 8 : 16);
141936ac495dSmrg }
142036ac495dSmrg 
142136ac495dSmrg /* Implements FUNCTION_ARG_REGNO_P.  */
142236ac495dSmrg int
m32c_function_arg_regno_p(int r)142336ac495dSmrg m32c_function_arg_regno_p (int r)
142436ac495dSmrg {
142536ac495dSmrg   if (TARGET_A24)
142636ac495dSmrg     return (r == R0_REGNO);
142736ac495dSmrg   return (r == R1_REGNO || r == R2_REGNO);
142836ac495dSmrg }
142936ac495dSmrg 
143036ac495dSmrg /* HImode and PSImode are the two "native" modes as far as GCC is
143136ac495dSmrg    concerned, but the chips also support a 32-bit mode which is used
143236ac495dSmrg    for some opcodes in R8C/M16C and for reset vectors and such.  */
143336ac495dSmrg #undef TARGET_VALID_POINTER_MODE
143436ac495dSmrg #define TARGET_VALID_POINTER_MODE m32c_valid_pointer_mode
143536ac495dSmrg static bool
m32c_valid_pointer_mode(scalar_int_mode mode)1436a2dc1f3fSmrg m32c_valid_pointer_mode (scalar_int_mode mode)
143736ac495dSmrg {
143836ac495dSmrg   if (mode == HImode
143936ac495dSmrg       || mode == PSImode
144036ac495dSmrg       || mode == SImode
144136ac495dSmrg       )
144236ac495dSmrg     return 1;
144336ac495dSmrg   return 0;
144436ac495dSmrg }
144536ac495dSmrg 
144636ac495dSmrg /* How Scalar Function Values Are Returned */
144736ac495dSmrg 
144836ac495dSmrg /* Implements TARGET_LIBCALL_VALUE.  Most values are returned in $r0, or some
144936ac495dSmrg    combination of registers starting there (r2r0 for longs, r3r1r2r0
145036ac495dSmrg    for long long, r3r2r1r0 for doubles), except that that ABI
145136ac495dSmrg    currently doesn't work because it ends up using all available
145236ac495dSmrg    general registers and gcc often can't compile it.  So, instead, we
145336ac495dSmrg    return anything bigger than 16 bits in "mem0" (effectively, a
145436ac495dSmrg    memory location).  */
145536ac495dSmrg 
145636ac495dSmrg #undef TARGET_LIBCALL_VALUE
145736ac495dSmrg #define TARGET_LIBCALL_VALUE m32c_libcall_value
145836ac495dSmrg 
145936ac495dSmrg static rtx
m32c_libcall_value(machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)146036ac495dSmrg m32c_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
146136ac495dSmrg {
146236ac495dSmrg   /* return reg or parallel */
146336ac495dSmrg #if 0
146436ac495dSmrg   /* FIXME: GCC has difficulty returning large values in registers,
146536ac495dSmrg      because that ties up most of the general registers and gives the
146636ac495dSmrg      register allocator little to work with.  Until we can resolve
146736ac495dSmrg      this, large values are returned in memory.  */
146836ac495dSmrg   if (mode == DFmode)
146936ac495dSmrg     {
147036ac495dSmrg       rtx rv;
147136ac495dSmrg 
147236ac495dSmrg       rv = gen_rtx_PARALLEL (mode, rtvec_alloc (4));
147336ac495dSmrg       XVECEXP (rv, 0, 0) = gen_rtx_EXPR_LIST (VOIDmode,
147436ac495dSmrg 					      gen_rtx_REG (HImode,
147536ac495dSmrg 							   R0_REGNO),
147636ac495dSmrg 					      GEN_INT (0));
147736ac495dSmrg       XVECEXP (rv, 0, 1) = gen_rtx_EXPR_LIST (VOIDmode,
147836ac495dSmrg 					      gen_rtx_REG (HImode,
147936ac495dSmrg 							   R1_REGNO),
148036ac495dSmrg 					      GEN_INT (2));
148136ac495dSmrg       XVECEXP (rv, 0, 2) = gen_rtx_EXPR_LIST (VOIDmode,
148236ac495dSmrg 					      gen_rtx_REG (HImode,
148336ac495dSmrg 							   R2_REGNO),
148436ac495dSmrg 					      GEN_INT (4));
148536ac495dSmrg       XVECEXP (rv, 0, 3) = gen_rtx_EXPR_LIST (VOIDmode,
148636ac495dSmrg 					      gen_rtx_REG (HImode,
148736ac495dSmrg 							   R3_REGNO),
148836ac495dSmrg 					      GEN_INT (6));
148936ac495dSmrg       return rv;
149036ac495dSmrg     }
149136ac495dSmrg 
149236ac495dSmrg   if (TARGET_A24 && GET_MODE_SIZE (mode) > 2)
149336ac495dSmrg     {
149436ac495dSmrg       rtx rv;
149536ac495dSmrg 
149636ac495dSmrg       rv = gen_rtx_PARALLEL (mode, rtvec_alloc (1));
149736ac495dSmrg       XVECEXP (rv, 0, 0) = gen_rtx_EXPR_LIST (VOIDmode,
149836ac495dSmrg 					      gen_rtx_REG (mode,
149936ac495dSmrg 							   R0_REGNO),
150036ac495dSmrg 					      GEN_INT (0));
150136ac495dSmrg       return rv;
150236ac495dSmrg     }
150336ac495dSmrg #endif
150436ac495dSmrg 
150536ac495dSmrg   if (GET_MODE_SIZE (mode) > 2)
150636ac495dSmrg     return gen_rtx_REG (mode, MEM0_REGNO);
150736ac495dSmrg   return gen_rtx_REG (mode, R0_REGNO);
150836ac495dSmrg }
150936ac495dSmrg 
151036ac495dSmrg /* Implements TARGET_FUNCTION_VALUE.  Functions and libcalls have the same
151136ac495dSmrg    conventions.  */
151236ac495dSmrg 
151336ac495dSmrg #undef TARGET_FUNCTION_VALUE
151436ac495dSmrg #define TARGET_FUNCTION_VALUE m32c_function_value
151536ac495dSmrg 
151636ac495dSmrg static rtx
m32c_function_value(const_tree valtype,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)151736ac495dSmrg m32c_function_value (const_tree valtype,
151836ac495dSmrg 		     const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
151936ac495dSmrg 		     bool outgoing ATTRIBUTE_UNUSED)
152036ac495dSmrg {
152136ac495dSmrg   /* return reg or parallel */
152236ac495dSmrg   const machine_mode mode = TYPE_MODE (valtype);
152336ac495dSmrg   return m32c_libcall_value (mode, NULL_RTX);
152436ac495dSmrg }
152536ac495dSmrg 
152636ac495dSmrg /* Implements TARGET_FUNCTION_VALUE_REGNO_P.  */
152736ac495dSmrg 
152836ac495dSmrg #undef TARGET_FUNCTION_VALUE_REGNO_P
152936ac495dSmrg #define TARGET_FUNCTION_VALUE_REGNO_P m32c_function_value_regno_p
153036ac495dSmrg 
153136ac495dSmrg static bool
m32c_function_value_regno_p(const unsigned int regno)153236ac495dSmrg m32c_function_value_regno_p (const unsigned int regno)
153336ac495dSmrg {
153436ac495dSmrg   return (regno == R0_REGNO || regno == MEM0_REGNO);
153536ac495dSmrg }
153636ac495dSmrg 
153736ac495dSmrg /* How Large Values Are Returned */
153836ac495dSmrg 
153936ac495dSmrg /* We return structures by pushing the address on the stack, even if
154036ac495dSmrg    we use registers for the first few "real" arguments.  */
154136ac495dSmrg #undef TARGET_STRUCT_VALUE_RTX
154236ac495dSmrg #define TARGET_STRUCT_VALUE_RTX m32c_struct_value_rtx
154336ac495dSmrg static rtx
m32c_struct_value_rtx(tree fndecl ATTRIBUTE_UNUSED,int incoming ATTRIBUTE_UNUSED)154436ac495dSmrg m32c_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
154536ac495dSmrg 		       int incoming ATTRIBUTE_UNUSED)
154636ac495dSmrg {
154736ac495dSmrg   return 0;
154836ac495dSmrg }
154936ac495dSmrg 
155036ac495dSmrg /* Function Entry and Exit */
155136ac495dSmrg 
155236ac495dSmrg /* Implements EPILOGUE_USES.  Interrupts restore all registers.  */
155336ac495dSmrg int
m32c_epilogue_uses(int regno ATTRIBUTE_UNUSED)155436ac495dSmrg m32c_epilogue_uses (int regno ATTRIBUTE_UNUSED)
155536ac495dSmrg {
155636ac495dSmrg   if (cfun->machine->is_interrupt)
155736ac495dSmrg     return 1;
155836ac495dSmrg   return 0;
155936ac495dSmrg }
156036ac495dSmrg 
156136ac495dSmrg /* Implementing the Varargs Macros */
156236ac495dSmrg 
156336ac495dSmrg #undef TARGET_STRICT_ARGUMENT_NAMING
156436ac495dSmrg #define TARGET_STRICT_ARGUMENT_NAMING m32c_strict_argument_naming
156536ac495dSmrg static bool
m32c_strict_argument_naming(cumulative_args_t ca ATTRIBUTE_UNUSED)156636ac495dSmrg m32c_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED)
156736ac495dSmrg {
156836ac495dSmrg   return 1;
156936ac495dSmrg }
157036ac495dSmrg 
157136ac495dSmrg /* Trampolines for Nested Functions */
157236ac495dSmrg 
157336ac495dSmrg /*
157436ac495dSmrg    m16c:
157536ac495dSmrg    1 0000 75C43412              mov.w   #0x1234,a0
157636ac495dSmrg    2 0004 FC000000              jmp.a   label
157736ac495dSmrg 
157836ac495dSmrg    m32c:
157936ac495dSmrg    1 0000 BC563412              mov.l:s #0x123456,a0
158036ac495dSmrg    2 0004 CC000000              jmp.a   label
158136ac495dSmrg */
158236ac495dSmrg 
158336ac495dSmrg /* Implements TRAMPOLINE_SIZE.  */
158436ac495dSmrg int
m32c_trampoline_size(void)158536ac495dSmrg m32c_trampoline_size (void)
158636ac495dSmrg {
158736ac495dSmrg   /* Allocate extra space so we can avoid the messy shifts when we
158836ac495dSmrg      initialize the trampoline; we just write past the end of the
158936ac495dSmrg      opcode.  */
159036ac495dSmrg   return TARGET_A16 ? 8 : 10;
159136ac495dSmrg }
159236ac495dSmrg 
159336ac495dSmrg /* Implements TRAMPOLINE_ALIGNMENT.  */
159436ac495dSmrg int
m32c_trampoline_alignment(void)159536ac495dSmrg m32c_trampoline_alignment (void)
159636ac495dSmrg {
159736ac495dSmrg   return 2;
159836ac495dSmrg }
159936ac495dSmrg 
160036ac495dSmrg /* Implements TARGET_TRAMPOLINE_INIT.  */
160136ac495dSmrg 
160236ac495dSmrg #undef TARGET_TRAMPOLINE_INIT
160336ac495dSmrg #define TARGET_TRAMPOLINE_INIT m32c_trampoline_init
160436ac495dSmrg static void
m32c_trampoline_init(rtx m_tramp,tree fndecl,rtx chainval)160536ac495dSmrg m32c_trampoline_init (rtx m_tramp, tree fndecl, rtx chainval)
160636ac495dSmrg {
160736ac495dSmrg   rtx function = XEXP (DECL_RTL (fndecl), 0);
160836ac495dSmrg 
160936ac495dSmrg #define A0(m,i) adjust_address (m_tramp, m, i)
161036ac495dSmrg   if (TARGET_A16)
161136ac495dSmrg     {
161236ac495dSmrg       /* Note: we subtract a "word" because the moves want signed
161336ac495dSmrg 	 constants, not unsigned constants.  */
161436ac495dSmrg       emit_move_insn (A0 (HImode, 0), GEN_INT (0xc475 - 0x10000));
161536ac495dSmrg       emit_move_insn (A0 (HImode, 2), chainval);
161636ac495dSmrg       emit_move_insn (A0 (QImode, 4), GEN_INT (0xfc - 0x100));
161736ac495dSmrg       /* We use 16-bit addresses here, but store the zero to turn it
161836ac495dSmrg 	 into a 24-bit offset.  */
161936ac495dSmrg       emit_move_insn (A0 (HImode, 5), function);
162036ac495dSmrg       emit_move_insn (A0 (QImode, 7), GEN_INT (0x00));
162136ac495dSmrg     }
162236ac495dSmrg   else
162336ac495dSmrg     {
162436ac495dSmrg       /* Note that the PSI moves actually write 4 bytes.  Make sure we
162536ac495dSmrg 	 write stuff out in the right order, and leave room for the
162636ac495dSmrg 	 extra byte at the end.  */
162736ac495dSmrg       emit_move_insn (A0 (QImode, 0), GEN_INT (0xbc - 0x100));
162836ac495dSmrg       emit_move_insn (A0 (PSImode, 1), chainval);
162936ac495dSmrg       emit_move_insn (A0 (QImode, 4), GEN_INT (0xcc - 0x100));
163036ac495dSmrg       emit_move_insn (A0 (PSImode, 5), function);
163136ac495dSmrg     }
163236ac495dSmrg #undef A0
163336ac495dSmrg }
163436ac495dSmrg 
163536ac495dSmrg #undef TARGET_LRA_P
163636ac495dSmrg #define TARGET_LRA_P hook_bool_void_false
163736ac495dSmrg 
163836ac495dSmrg /* Addressing Modes */
163936ac495dSmrg 
164036ac495dSmrg /* The r8c/m32c family supports a wide range of non-orthogonal
164136ac495dSmrg    addressing modes, including the ability to double-indirect on *some*
164236ac495dSmrg    of them.  Not all insns support all modes, either, but we rely on
164336ac495dSmrg    predicates and constraints to deal with that.  */
164436ac495dSmrg #undef TARGET_LEGITIMATE_ADDRESS_P
164536ac495dSmrg #define TARGET_LEGITIMATE_ADDRESS_P m32c_legitimate_address_p
164636ac495dSmrg bool
m32c_legitimate_address_p(machine_mode mode,rtx x,bool strict)164736ac495dSmrg m32c_legitimate_address_p (machine_mode mode, rtx x, bool strict)
164836ac495dSmrg {
164936ac495dSmrg   int mode_adjust;
165036ac495dSmrg   if (CONSTANT_P (x))
165136ac495dSmrg     return 1;
165236ac495dSmrg 
165336ac495dSmrg   if (TARGET_A16 && GET_MODE (x) != HImode && GET_MODE (x) != SImode)
165436ac495dSmrg     return 0;
165536ac495dSmrg   if (TARGET_A24 && GET_MODE (x) != PSImode)
165636ac495dSmrg     return 0;
165736ac495dSmrg 
165836ac495dSmrg   /* Wide references to memory will be split after reload, so we must
165936ac495dSmrg      ensure that all parts of such splits remain legitimate
166036ac495dSmrg      addresses.  */
166136ac495dSmrg   mode_adjust = GET_MODE_SIZE (mode) - 1;
166236ac495dSmrg 
166336ac495dSmrg   /* allowing PLUS yields mem:HI(plus:SI(mem:SI(plus:SI in m32c_split_move */
166436ac495dSmrg   if (GET_CODE (x) == PRE_DEC
166536ac495dSmrg       || GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_MODIFY)
166636ac495dSmrg     {
166736ac495dSmrg       return (GET_CODE (XEXP (x, 0)) == REG
166836ac495dSmrg 	      && REGNO (XEXP (x, 0)) == SP_REGNO);
166936ac495dSmrg     }
167036ac495dSmrg 
167136ac495dSmrg #if 0
167236ac495dSmrg   /* This is the double indirection detection, but it currently
167336ac495dSmrg      doesn't work as cleanly as this code implies, so until we've had
167436ac495dSmrg      a chance to debug it, leave it disabled.  */
167536ac495dSmrg   if (TARGET_A24 && GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) != PLUS)
167636ac495dSmrg     {
167736ac495dSmrg #if DEBUG_DOUBLE
167836ac495dSmrg       fprintf (stderr, "double indirect\n");
167936ac495dSmrg #endif
168036ac495dSmrg       x = XEXP (x, 0);
168136ac495dSmrg     }
168236ac495dSmrg #endif
168336ac495dSmrg 
168436ac495dSmrg   encode_pattern (x);
168536ac495dSmrg   if (RTX_IS ("r"))
168636ac495dSmrg     {
168736ac495dSmrg       /* Most indexable registers can be used without displacements,
168836ac495dSmrg 	 although some of them will be emitted with an explicit zero
168936ac495dSmrg 	 to please the assembler.  */
169036ac495dSmrg       switch (REGNO (patternr[0]))
169136ac495dSmrg 	{
169236ac495dSmrg 	case A1_REGNO:
169336ac495dSmrg 	case SB_REGNO:
169436ac495dSmrg 	case FB_REGNO:
169536ac495dSmrg 	case SP_REGNO:
169636ac495dSmrg 	  if (TARGET_A16 && GET_MODE (x) == SImode)
169736ac495dSmrg 	    return 0;
169836ac495dSmrg 	  /* FALLTHRU */
169936ac495dSmrg 	case A0_REGNO:
170036ac495dSmrg 	  return 1;
170136ac495dSmrg 
170236ac495dSmrg 	default:
170336ac495dSmrg 	  if (IS_PSEUDO (patternr[0], strict))
170436ac495dSmrg 	    return 1;
170536ac495dSmrg 	  return 0;
170636ac495dSmrg 	}
170736ac495dSmrg     }
170836ac495dSmrg 
170936ac495dSmrg   if (TARGET_A16 && GET_MODE (x) == SImode)
171036ac495dSmrg     return 0;
171136ac495dSmrg 
171236ac495dSmrg   if (RTX_IS ("+ri"))
171336ac495dSmrg     {
171436ac495dSmrg       /* This is more interesting, because different base registers
171536ac495dSmrg 	 allow for different displacements - both range and signedness
171636ac495dSmrg 	 - and it differs from chip series to chip series too.  */
171736ac495dSmrg       int rn = REGNO (patternr[1]);
171836ac495dSmrg       HOST_WIDE_INT offs = INTVAL (patternr[2]);
171936ac495dSmrg       switch (rn)
172036ac495dSmrg 	{
172136ac495dSmrg 	case A0_REGNO:
172236ac495dSmrg 	case A1_REGNO:
172336ac495dSmrg 	case SB_REGNO:
172436ac495dSmrg 	  /* The syntax only allows positive offsets, but when the
172536ac495dSmrg 	     offsets span the entire memory range, we can simulate
172636ac495dSmrg 	     negative offsets by wrapping.  */
172736ac495dSmrg 	  if (TARGET_A16)
172836ac495dSmrg 	    return (offs >= -65536 && offs <= 65535 - mode_adjust);
172936ac495dSmrg 	  if (rn == SB_REGNO)
173036ac495dSmrg 	    return (offs >= 0 && offs <= 65535 - mode_adjust);
173136ac495dSmrg 	  /* A0 or A1 */
173236ac495dSmrg 	  return (offs >= -16777216 && offs <= 16777215);
173336ac495dSmrg 
173436ac495dSmrg 	case FB_REGNO:
173536ac495dSmrg 	  if (TARGET_A16)
173636ac495dSmrg 	    return (offs >= -128 && offs <= 127 - mode_adjust);
173736ac495dSmrg 	  return (offs >= -65536 && offs <= 65535 - mode_adjust);
173836ac495dSmrg 
173936ac495dSmrg 	case SP_REGNO:
174036ac495dSmrg 	  return (offs >= -128 && offs <= 127 - mode_adjust);
174136ac495dSmrg 
174236ac495dSmrg 	default:
174336ac495dSmrg 	  if (IS_PSEUDO (patternr[1], strict))
174436ac495dSmrg 	    return 1;
174536ac495dSmrg 	  return 0;
174636ac495dSmrg 	}
174736ac495dSmrg     }
174836ac495dSmrg   if (RTX_IS ("+rs") || RTX_IS ("+r+si"))
174936ac495dSmrg     {
175036ac495dSmrg       rtx reg = patternr[1];
175136ac495dSmrg 
175236ac495dSmrg       /* We don't know where the symbol is, so only allow base
175336ac495dSmrg 	 registers which support displacements spanning the whole
175436ac495dSmrg 	 address range.  */
175536ac495dSmrg       switch (REGNO (reg))
175636ac495dSmrg 	{
175736ac495dSmrg 	case A0_REGNO:
175836ac495dSmrg 	case A1_REGNO:
175936ac495dSmrg 	  /* $sb needs a secondary reload, but since it's involved in
176036ac495dSmrg 	     memory address reloads too, we don't deal with it very
176136ac495dSmrg 	     well.  */
176236ac495dSmrg 	  /*    case SB_REGNO: */
176336ac495dSmrg 	  return 1;
176436ac495dSmrg 	default:
176536ac495dSmrg 	  if (GET_CODE (reg) == SUBREG)
176636ac495dSmrg 	    return 0;
176736ac495dSmrg 	  if (IS_PSEUDO (reg, strict))
176836ac495dSmrg 	    return 1;
176936ac495dSmrg 	  return 0;
177036ac495dSmrg 	}
177136ac495dSmrg     }
177236ac495dSmrg   return 0;
177336ac495dSmrg }
177436ac495dSmrg 
177536ac495dSmrg /* Implements REG_OK_FOR_BASE_P.  */
177636ac495dSmrg int
m32c_reg_ok_for_base_p(rtx x,int strict)177736ac495dSmrg m32c_reg_ok_for_base_p (rtx x, int strict)
177836ac495dSmrg {
177936ac495dSmrg   if (GET_CODE (x) != REG)
178036ac495dSmrg     return 0;
178136ac495dSmrg   switch (REGNO (x))
178236ac495dSmrg     {
178336ac495dSmrg     case A0_REGNO:
178436ac495dSmrg     case A1_REGNO:
178536ac495dSmrg     case SB_REGNO:
178636ac495dSmrg     case FB_REGNO:
178736ac495dSmrg     case SP_REGNO:
178836ac495dSmrg       return 1;
178936ac495dSmrg     default:
179036ac495dSmrg       if (IS_PSEUDO (x, strict))
179136ac495dSmrg 	return 1;
179236ac495dSmrg       return 0;
179336ac495dSmrg     }
179436ac495dSmrg }
179536ac495dSmrg 
179636ac495dSmrg /* We have three choices for choosing fb->aN offsets.  If we choose -128,
179736ac495dSmrg    we need one MOVA -128[fb],aN opcode and 16-bit aN displacements,
179836ac495dSmrg    like this:
179936ac495dSmrg        EB 4B FF    mova    -128[$fb],$a0
180036ac495dSmrg        D8 0C FF FF mov.w:Q #0,-1[$a0]
180136ac495dSmrg 
180236ac495dSmrg    Alternately, we subtract the frame size, and hopefully use 8-bit aN
180336ac495dSmrg    displacements:
180436ac495dSmrg        7B F4       stc $fb,$a0
180536ac495dSmrg        77 54 00 01 sub #256,$a0
180636ac495dSmrg        D8 08 01    mov.w:Q #0,1[$a0]
180736ac495dSmrg 
180836ac495dSmrg    If we don't offset (i.e. offset by zero), we end up with:
180936ac495dSmrg        7B F4       stc $fb,$a0
181036ac495dSmrg        D8 0C 00 FF mov.w:Q #0,-256[$a0]
181136ac495dSmrg 
181236ac495dSmrg    We have to subtract *something* so that we have a PLUS rtx to mark
181336ac495dSmrg    that we've done this reload.  The -128 offset will never result in
181436ac495dSmrg    an 8-bit aN offset, and the payoff for the second case is five
181536ac495dSmrg    loads *if* those loads are within 256 bytes of the other end of the
181636ac495dSmrg    frame, so the third case seems best.  Note that we subtract the
181736ac495dSmrg    zero, but detect that in the addhi3 pattern.  */
181836ac495dSmrg 
181936ac495dSmrg #define BIG_FB_ADJ 0
182036ac495dSmrg 
182136ac495dSmrg /* Implements LEGITIMIZE_ADDRESS.  The only address we really have to
182236ac495dSmrg    worry about is frame base offsets, as $fb has a limited
182336ac495dSmrg    displacement range.  We deal with this by attempting to reload $fb
182436ac495dSmrg    itself into an address register; that seems to result in the best
182536ac495dSmrg    code.  */
182636ac495dSmrg #undef TARGET_LEGITIMIZE_ADDRESS
182736ac495dSmrg #define TARGET_LEGITIMIZE_ADDRESS m32c_legitimize_address
182836ac495dSmrg static rtx
m32c_legitimize_address(rtx x,rtx oldx ATTRIBUTE_UNUSED,machine_mode mode)182936ac495dSmrg m32c_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
183036ac495dSmrg 			 machine_mode mode)
183136ac495dSmrg {
183236ac495dSmrg #if DEBUG0
183336ac495dSmrg   fprintf (stderr, "m32c_legitimize_address for mode %s\n", mode_name[mode]);
183436ac495dSmrg   debug_rtx (x);
183536ac495dSmrg   fprintf (stderr, "\n");
183636ac495dSmrg #endif
183736ac495dSmrg 
183836ac495dSmrg   if (GET_CODE (x) == PLUS
183936ac495dSmrg       && GET_CODE (XEXP (x, 0)) == REG
184036ac495dSmrg       && REGNO (XEXP (x, 0)) == FB_REGNO
184136ac495dSmrg       && GET_CODE (XEXP (x, 1)) == CONST_INT
184236ac495dSmrg       && (INTVAL (XEXP (x, 1)) < -128
184336ac495dSmrg 	  || INTVAL (XEXP (x, 1)) > (128 - GET_MODE_SIZE (mode))))
184436ac495dSmrg     {
184536ac495dSmrg       /* reload FB to A_REGS */
184636ac495dSmrg       rtx temp = gen_reg_rtx (Pmode);
184736ac495dSmrg       x = copy_rtx (x);
184836ac495dSmrg       emit_insn (gen_rtx_SET (temp, XEXP (x, 0)));
184936ac495dSmrg       XEXP (x, 0) = temp;
185036ac495dSmrg     }
185136ac495dSmrg 
185236ac495dSmrg   return x;
185336ac495dSmrg }
185436ac495dSmrg 
185536ac495dSmrg /* Implements LEGITIMIZE_RELOAD_ADDRESS.  See comment above.  */
185636ac495dSmrg int
m32c_legitimize_reload_address(rtx * x,machine_mode mode,int opnum,int type,int ind_levels ATTRIBUTE_UNUSED)185736ac495dSmrg m32c_legitimize_reload_address (rtx * x,
185836ac495dSmrg 				machine_mode mode,
185936ac495dSmrg 				int opnum,
186036ac495dSmrg 				int type, int ind_levels ATTRIBUTE_UNUSED)
186136ac495dSmrg {
186236ac495dSmrg #if DEBUG0
186336ac495dSmrg   fprintf (stderr, "\nm32c_legitimize_reload_address for mode %s\n",
186436ac495dSmrg 	   mode_name[mode]);
186536ac495dSmrg   debug_rtx (*x);
186636ac495dSmrg #endif
186736ac495dSmrg 
186836ac495dSmrg   /* At one point, this function tried to get $fb copied to an address
186936ac495dSmrg      register, which in theory would maximize sharing, but gcc was
187036ac495dSmrg      *also* still trying to reload the whole address, and we'd run out
187136ac495dSmrg      of address registers.  So we let gcc do the naive (but safe)
187236ac495dSmrg      reload instead, when the above function doesn't handle it for
187336ac495dSmrg      us.
187436ac495dSmrg 
187536ac495dSmrg      The code below is a second attempt at the above.  */
187636ac495dSmrg 
187736ac495dSmrg   if (GET_CODE (*x) == PLUS
187836ac495dSmrg       && GET_CODE (XEXP (*x, 0)) == REG
187936ac495dSmrg       && REGNO (XEXP (*x, 0)) == FB_REGNO
188036ac495dSmrg       && GET_CODE (XEXP (*x, 1)) == CONST_INT
188136ac495dSmrg       && (INTVAL (XEXP (*x, 1)) < -128
188236ac495dSmrg 	  || INTVAL (XEXP (*x, 1)) > (128 - GET_MODE_SIZE (mode))))
188336ac495dSmrg     {
188436ac495dSmrg       rtx sum;
188536ac495dSmrg       int offset = INTVAL (XEXP (*x, 1));
188636ac495dSmrg       int adjustment = -BIG_FB_ADJ;
188736ac495dSmrg 
188836ac495dSmrg       sum = gen_rtx_PLUS (Pmode, XEXP (*x, 0),
188936ac495dSmrg 			  GEN_INT (adjustment));
189036ac495dSmrg       *x = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - adjustment));
189136ac495dSmrg       if (type == RELOAD_OTHER)
189236ac495dSmrg 	type = RELOAD_FOR_OTHER_ADDRESS;
189336ac495dSmrg       push_reload (sum, NULL_RTX, &XEXP (*x, 0), NULL,
189436ac495dSmrg 		   A_REGS, Pmode, VOIDmode, 0, 0, opnum,
189536ac495dSmrg 		   (enum reload_type) type);
189636ac495dSmrg       return 1;
189736ac495dSmrg     }
189836ac495dSmrg 
189936ac495dSmrg   if (GET_CODE (*x) == PLUS
190036ac495dSmrg       && GET_CODE (XEXP (*x, 0)) == PLUS
190136ac495dSmrg       && GET_CODE (XEXP (XEXP (*x, 0), 0)) == REG
190236ac495dSmrg       && REGNO (XEXP (XEXP (*x, 0), 0)) == FB_REGNO
190336ac495dSmrg       && GET_CODE (XEXP (XEXP (*x, 0), 1)) == CONST_INT
190436ac495dSmrg       && GET_CODE (XEXP (*x, 1)) == CONST_INT
190536ac495dSmrg       )
190636ac495dSmrg     {
190736ac495dSmrg       if (type == RELOAD_OTHER)
190836ac495dSmrg 	type = RELOAD_FOR_OTHER_ADDRESS;
190936ac495dSmrg       push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL,
191036ac495dSmrg 		   A_REGS, Pmode, VOIDmode, 0, 0, opnum,
191136ac495dSmrg 		   (enum reload_type) type);
191236ac495dSmrg       return 1;
191336ac495dSmrg     }
191436ac495dSmrg 
191536ac495dSmrg   if (TARGET_A24 && GET_MODE (*x) == PSImode)
191636ac495dSmrg     {
191736ac495dSmrg       push_reload (*x, NULL_RTX, x, NULL,
191836ac495dSmrg 		   A_REGS, PSImode, VOIDmode, 0, 0, opnum,
191936ac495dSmrg 		   (enum reload_type) type);
192036ac495dSmrg       return 1;
192136ac495dSmrg     }
192236ac495dSmrg 
192336ac495dSmrg   return 0;
192436ac495dSmrg }
192536ac495dSmrg 
192636ac495dSmrg /* Return the appropriate mode for a named address pointer.  */
192736ac495dSmrg #undef TARGET_ADDR_SPACE_POINTER_MODE
192836ac495dSmrg #define TARGET_ADDR_SPACE_POINTER_MODE m32c_addr_space_pointer_mode
1929a2dc1f3fSmrg static scalar_int_mode
m32c_addr_space_pointer_mode(addr_space_t addrspace)193036ac495dSmrg m32c_addr_space_pointer_mode (addr_space_t addrspace)
193136ac495dSmrg {
193236ac495dSmrg   switch (addrspace)
193336ac495dSmrg     {
193436ac495dSmrg     case ADDR_SPACE_GENERIC:
193536ac495dSmrg       return TARGET_A24 ? PSImode : HImode;
193636ac495dSmrg     case ADDR_SPACE_FAR:
193736ac495dSmrg       return SImode;
193836ac495dSmrg     default:
193936ac495dSmrg       gcc_unreachable ();
194036ac495dSmrg     }
194136ac495dSmrg }
194236ac495dSmrg 
194336ac495dSmrg /* Return the appropriate mode for a named address address.  */
194436ac495dSmrg #undef TARGET_ADDR_SPACE_ADDRESS_MODE
194536ac495dSmrg #define TARGET_ADDR_SPACE_ADDRESS_MODE m32c_addr_space_address_mode
1946a2dc1f3fSmrg static scalar_int_mode
m32c_addr_space_address_mode(addr_space_t addrspace)194736ac495dSmrg m32c_addr_space_address_mode (addr_space_t addrspace)
194836ac495dSmrg {
194936ac495dSmrg   switch (addrspace)
195036ac495dSmrg     {
195136ac495dSmrg     case ADDR_SPACE_GENERIC:
195236ac495dSmrg       return TARGET_A24 ? PSImode : HImode;
195336ac495dSmrg     case ADDR_SPACE_FAR:
195436ac495dSmrg       return SImode;
195536ac495dSmrg     default:
195636ac495dSmrg       gcc_unreachable ();
195736ac495dSmrg     }
195836ac495dSmrg }
195936ac495dSmrg 
196036ac495dSmrg /* Like m32c_legitimate_address_p, except with named addresses.  */
196136ac495dSmrg #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
196236ac495dSmrg #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
196336ac495dSmrg   m32c_addr_space_legitimate_address_p
196436ac495dSmrg static bool
m32c_addr_space_legitimate_address_p(machine_mode mode,rtx x,bool strict,addr_space_t as)196536ac495dSmrg m32c_addr_space_legitimate_address_p (machine_mode mode, rtx x,
196636ac495dSmrg 				      bool strict, addr_space_t as)
196736ac495dSmrg {
196836ac495dSmrg   if (as == ADDR_SPACE_FAR)
196936ac495dSmrg     {
197036ac495dSmrg       if (TARGET_A24)
197136ac495dSmrg 	return 0;
197236ac495dSmrg       encode_pattern (x);
197336ac495dSmrg       if (RTX_IS ("r"))
197436ac495dSmrg 	{
197536ac495dSmrg 	  if (GET_MODE (x) != SImode)
197636ac495dSmrg 	    return 0;
197736ac495dSmrg 	  switch (REGNO (patternr[0]))
197836ac495dSmrg 	    {
197936ac495dSmrg 	    case A0_REGNO:
198036ac495dSmrg 	      return 1;
198136ac495dSmrg 
198236ac495dSmrg 	    default:
198336ac495dSmrg 	      if (IS_PSEUDO (patternr[0], strict))
198436ac495dSmrg 		return 1;
198536ac495dSmrg 	      return 0;
198636ac495dSmrg 	    }
198736ac495dSmrg 	}
198836ac495dSmrg       if (RTX_IS ("+^Sri"))
198936ac495dSmrg 	{
199036ac495dSmrg 	  int rn = REGNO (patternr[3]);
199136ac495dSmrg 	  HOST_WIDE_INT offs = INTVAL (patternr[4]);
199236ac495dSmrg 	  if (GET_MODE (patternr[3]) != HImode)
199336ac495dSmrg 	    return 0;
199436ac495dSmrg 	  switch (rn)
199536ac495dSmrg 	    {
199636ac495dSmrg 	    case A0_REGNO:
199736ac495dSmrg 	      return (offs >= 0 && offs <= 0xfffff);
199836ac495dSmrg 
199936ac495dSmrg 	    default:
200036ac495dSmrg 	      if (IS_PSEUDO (patternr[3], strict))
200136ac495dSmrg 		return 1;
200236ac495dSmrg 	      return 0;
200336ac495dSmrg 	    }
200436ac495dSmrg 	}
200536ac495dSmrg       if (RTX_IS ("+^Srs"))
200636ac495dSmrg 	{
200736ac495dSmrg 	  int rn = REGNO (patternr[3]);
200836ac495dSmrg 	  if (GET_MODE (patternr[3]) != HImode)
200936ac495dSmrg 	    return 0;
201036ac495dSmrg 	  switch (rn)
201136ac495dSmrg 	    {
201236ac495dSmrg 	    case A0_REGNO:
201336ac495dSmrg 	      return 1;
201436ac495dSmrg 
201536ac495dSmrg 	    default:
201636ac495dSmrg 	      if (IS_PSEUDO (patternr[3], strict))
201736ac495dSmrg 		return 1;
201836ac495dSmrg 	      return 0;
201936ac495dSmrg 	    }
202036ac495dSmrg 	}
202136ac495dSmrg       if (RTX_IS ("+^S+ris"))
202236ac495dSmrg 	{
202336ac495dSmrg 	  int rn = REGNO (patternr[4]);
202436ac495dSmrg 	  if (GET_MODE (patternr[4]) != HImode)
202536ac495dSmrg 	    return 0;
202636ac495dSmrg 	  switch (rn)
202736ac495dSmrg 	    {
202836ac495dSmrg 	    case A0_REGNO:
202936ac495dSmrg 	      return 1;
203036ac495dSmrg 
203136ac495dSmrg 	    default:
203236ac495dSmrg 	      if (IS_PSEUDO (patternr[4], strict))
203336ac495dSmrg 		return 1;
203436ac495dSmrg 	      return 0;
203536ac495dSmrg 	    }
203636ac495dSmrg 	}
203736ac495dSmrg       if (RTX_IS ("s"))
203836ac495dSmrg 	{
203936ac495dSmrg 	  return 1;
204036ac495dSmrg 	}
204136ac495dSmrg       return 0;
204236ac495dSmrg     }
204336ac495dSmrg 
204436ac495dSmrg   else if (as != ADDR_SPACE_GENERIC)
204536ac495dSmrg     gcc_unreachable ();
204636ac495dSmrg 
204736ac495dSmrg   return m32c_legitimate_address_p (mode, x, strict);
204836ac495dSmrg }
204936ac495dSmrg 
205036ac495dSmrg /* Like m32c_legitimate_address, except with named address support.  */
205136ac495dSmrg #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
205236ac495dSmrg #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS m32c_addr_space_legitimize_address
205336ac495dSmrg static rtx
m32c_addr_space_legitimize_address(rtx x,rtx oldx,machine_mode mode,addr_space_t as)205436ac495dSmrg m32c_addr_space_legitimize_address (rtx x, rtx oldx, machine_mode mode,
205536ac495dSmrg 				    addr_space_t as)
205636ac495dSmrg {
205736ac495dSmrg   if (as != ADDR_SPACE_GENERIC)
205836ac495dSmrg     {
205936ac495dSmrg #if DEBUG0
206036ac495dSmrg       fprintf (stderr, "\033[36mm32c_addr_space_legitimize_address for mode %s\033[0m\n", mode_name[mode]);
206136ac495dSmrg       debug_rtx (x);
206236ac495dSmrg       fprintf (stderr, "\n");
206336ac495dSmrg #endif
206436ac495dSmrg 
206536ac495dSmrg       if (GET_CODE (x) != REG)
206636ac495dSmrg 	{
206736ac495dSmrg 	  x = force_reg (SImode, x);
206836ac495dSmrg 	}
206936ac495dSmrg       return x;
207036ac495dSmrg     }
207136ac495dSmrg 
207236ac495dSmrg   return m32c_legitimize_address (x, oldx, mode);
207336ac495dSmrg }
207436ac495dSmrg 
207536ac495dSmrg /* Determine if one named address space is a subset of another.  */
207636ac495dSmrg #undef TARGET_ADDR_SPACE_SUBSET_P
207736ac495dSmrg #define TARGET_ADDR_SPACE_SUBSET_P m32c_addr_space_subset_p
207836ac495dSmrg static bool
m32c_addr_space_subset_p(addr_space_t subset,addr_space_t superset)207936ac495dSmrg m32c_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
208036ac495dSmrg {
208136ac495dSmrg   gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
208236ac495dSmrg   gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
208336ac495dSmrg 
208436ac495dSmrg   if (subset == superset)
208536ac495dSmrg     return true;
208636ac495dSmrg 
208736ac495dSmrg   else
208836ac495dSmrg     return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
208936ac495dSmrg }
209036ac495dSmrg 
209136ac495dSmrg #undef TARGET_ADDR_SPACE_CONVERT
209236ac495dSmrg #define TARGET_ADDR_SPACE_CONVERT m32c_addr_space_convert
209336ac495dSmrg /* Convert from one address space to another.  */
209436ac495dSmrg static rtx
m32c_addr_space_convert(rtx op,tree from_type,tree to_type)209536ac495dSmrg m32c_addr_space_convert (rtx op, tree from_type, tree to_type)
209636ac495dSmrg {
209736ac495dSmrg   addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
209836ac495dSmrg   addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
209936ac495dSmrg   rtx result;
210036ac495dSmrg 
210136ac495dSmrg   gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
210236ac495dSmrg   gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
210336ac495dSmrg 
210436ac495dSmrg   if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
210536ac495dSmrg     {
210636ac495dSmrg       /* This is unpredictable, as we're truncating off usable address
210736ac495dSmrg 	 bits.  */
210836ac495dSmrg 
210936ac495dSmrg       result = gen_reg_rtx (HImode);
211036ac495dSmrg       emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
211136ac495dSmrg       return result;
211236ac495dSmrg     }
211336ac495dSmrg   else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
211436ac495dSmrg     {
211536ac495dSmrg       /* This always works.  */
211636ac495dSmrg       result = gen_reg_rtx (SImode);
211736ac495dSmrg       emit_insn (gen_zero_extendhisi2 (result, op));
211836ac495dSmrg       return result;
211936ac495dSmrg     }
212036ac495dSmrg   else
212136ac495dSmrg     gcc_unreachable ();
212236ac495dSmrg }
212336ac495dSmrg 
212436ac495dSmrg /* Condition Code Status */
212536ac495dSmrg 
212636ac495dSmrg #undef TARGET_FIXED_CONDITION_CODE_REGS
212736ac495dSmrg #define TARGET_FIXED_CONDITION_CODE_REGS m32c_fixed_condition_code_regs
212836ac495dSmrg static bool
m32c_fixed_condition_code_regs(unsigned int * p1,unsigned int * p2)212936ac495dSmrg m32c_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
213036ac495dSmrg {
213136ac495dSmrg   *p1 = FLG_REGNO;
213236ac495dSmrg   *p2 = INVALID_REGNUM;
213336ac495dSmrg   return true;
213436ac495dSmrg }
213536ac495dSmrg 
213636ac495dSmrg /* Describing Relative Costs of Operations */
213736ac495dSmrg 
213836ac495dSmrg /* Implements TARGET_REGISTER_MOVE_COST.  We make impossible moves
213936ac495dSmrg    prohibitively expensive, like trying to put QIs in r2/r3 (there are
214036ac495dSmrg    no opcodes to do that).  We also discourage use of mem* registers
214136ac495dSmrg    since they're really memory.  */
214236ac495dSmrg 
214336ac495dSmrg #undef TARGET_REGISTER_MOVE_COST
214436ac495dSmrg #define TARGET_REGISTER_MOVE_COST m32c_register_move_cost
214536ac495dSmrg 
214636ac495dSmrg static int
m32c_register_move_cost(machine_mode mode,reg_class_t from,reg_class_t to)214736ac495dSmrg m32c_register_move_cost (machine_mode mode, reg_class_t from,
214836ac495dSmrg 			 reg_class_t to)
214936ac495dSmrg {
215036ac495dSmrg   int cost = COSTS_N_INSNS (3);
215136ac495dSmrg   HARD_REG_SET cc;
215236ac495dSmrg 
215336ac495dSmrg /* FIXME: pick real values, but not 2 for now.  */
2154*8feb0f0bSmrg   cc = reg_class_contents[from] | reg_class_contents[(int) to];
215536ac495dSmrg 
215636ac495dSmrg   if (mode == QImode
215736ac495dSmrg       && hard_reg_set_intersect_p (cc, reg_class_contents[R23_REGS]))
215836ac495dSmrg     {
215936ac495dSmrg       if (hard_reg_set_subset_p (cc, reg_class_contents[R23_REGS]))
216036ac495dSmrg 	cost = COSTS_N_INSNS (1000);
216136ac495dSmrg       else
216236ac495dSmrg 	cost = COSTS_N_INSNS (80);
216336ac495dSmrg     }
216436ac495dSmrg 
216536ac495dSmrg   if (!class_can_hold_mode (from, mode) || !class_can_hold_mode (to, mode))
216636ac495dSmrg     cost = COSTS_N_INSNS (1000);
216736ac495dSmrg 
216836ac495dSmrg   if (reg_classes_intersect_p (from, CR_REGS))
216936ac495dSmrg     cost += COSTS_N_INSNS (5);
217036ac495dSmrg 
217136ac495dSmrg   if (reg_classes_intersect_p (to, CR_REGS))
217236ac495dSmrg     cost += COSTS_N_INSNS (5);
217336ac495dSmrg 
217436ac495dSmrg   if (from == MEM_REGS || to == MEM_REGS)
217536ac495dSmrg     cost += COSTS_N_INSNS (50);
217636ac495dSmrg   else if (reg_classes_intersect_p (from, MEM_REGS)
217736ac495dSmrg 	   || reg_classes_intersect_p (to, MEM_REGS))
217836ac495dSmrg     cost += COSTS_N_INSNS (10);
217936ac495dSmrg 
218036ac495dSmrg #if DEBUG0
218136ac495dSmrg   fprintf (stderr, "register_move_cost %s from %s to %s = %d\n",
218236ac495dSmrg 	   mode_name[mode], class_names[(int) from], class_names[(int) to],
218336ac495dSmrg 	   cost);
218436ac495dSmrg #endif
218536ac495dSmrg   return cost;
218636ac495dSmrg }
218736ac495dSmrg 
218836ac495dSmrg /*  Implements TARGET_MEMORY_MOVE_COST.  */
218936ac495dSmrg 
219036ac495dSmrg #undef TARGET_MEMORY_MOVE_COST
219136ac495dSmrg #define TARGET_MEMORY_MOVE_COST m32c_memory_move_cost
219236ac495dSmrg 
219336ac495dSmrg static int
m32c_memory_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)219436ac495dSmrg m32c_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
219536ac495dSmrg 		       reg_class_t rclass ATTRIBUTE_UNUSED,
219636ac495dSmrg 		       bool in ATTRIBUTE_UNUSED)
219736ac495dSmrg {
219836ac495dSmrg   /* FIXME: pick real values.  */
219936ac495dSmrg   return COSTS_N_INSNS (10);
220036ac495dSmrg }
220136ac495dSmrg 
220236ac495dSmrg /* Here we try to describe when we use multiple opcodes for one RTX so
220336ac495dSmrg    that gcc knows when to use them.  */
220436ac495dSmrg #undef TARGET_RTX_COSTS
220536ac495dSmrg #define TARGET_RTX_COSTS m32c_rtx_costs
220636ac495dSmrg static bool
m32c_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed ATTRIBUTE_UNUSED)220736ac495dSmrg m32c_rtx_costs (rtx x, machine_mode mode, int outer_code,
220836ac495dSmrg 		int opno ATTRIBUTE_UNUSED,
220936ac495dSmrg 		int *total, bool speed ATTRIBUTE_UNUSED)
221036ac495dSmrg {
221136ac495dSmrg   int code = GET_CODE (x);
221236ac495dSmrg   switch (code)
221336ac495dSmrg     {
221436ac495dSmrg     case REG:
221536ac495dSmrg       if (REGNO (x) >= MEM0_REGNO && REGNO (x) <= MEM7_REGNO)
221636ac495dSmrg 	*total += COSTS_N_INSNS (500);
221736ac495dSmrg       else
221836ac495dSmrg 	*total += COSTS_N_INSNS (1);
221936ac495dSmrg       return true;
222036ac495dSmrg 
222136ac495dSmrg     case ASHIFT:
222236ac495dSmrg     case LSHIFTRT:
222336ac495dSmrg     case ASHIFTRT:
222436ac495dSmrg       if (GET_CODE (XEXP (x, 1)) != CONST_INT)
222536ac495dSmrg 	{
222636ac495dSmrg 	  /* mov.b r1l, r1h */
222736ac495dSmrg 	  *total +=  COSTS_N_INSNS (1);
222836ac495dSmrg 	  return true;
222936ac495dSmrg 	}
223036ac495dSmrg       if (INTVAL (XEXP (x, 1)) > 8
223136ac495dSmrg 	  || INTVAL (XEXP (x, 1)) < -8)
223236ac495dSmrg 	{
223336ac495dSmrg 	  /* mov.b #N, r1l */
223436ac495dSmrg 	  /* mov.b r1l, r1h */
223536ac495dSmrg 	  *total +=  COSTS_N_INSNS (2);
223636ac495dSmrg 	  return true;
223736ac495dSmrg 	}
223836ac495dSmrg       return true;
223936ac495dSmrg 
224036ac495dSmrg     case LE:
224136ac495dSmrg     case LEU:
224236ac495dSmrg     case LT:
224336ac495dSmrg     case LTU:
224436ac495dSmrg     case GT:
224536ac495dSmrg     case GTU:
224636ac495dSmrg     case GE:
224736ac495dSmrg     case GEU:
224836ac495dSmrg     case NE:
224936ac495dSmrg     case EQ:
225036ac495dSmrg       if (outer_code == SET)
225136ac495dSmrg 	{
225236ac495dSmrg 	  *total += COSTS_N_INSNS (2);
225336ac495dSmrg 	  return true;
225436ac495dSmrg 	}
225536ac495dSmrg       break;
225636ac495dSmrg 
225736ac495dSmrg     case ZERO_EXTRACT:
225836ac495dSmrg       {
225936ac495dSmrg 	rtx dest = XEXP (x, 0);
226036ac495dSmrg 	rtx addr = XEXP (dest, 0);
226136ac495dSmrg 	switch (GET_CODE (addr))
226236ac495dSmrg 	  {
226336ac495dSmrg 	  case CONST_INT:
226436ac495dSmrg 	    *total += COSTS_N_INSNS (1);
226536ac495dSmrg 	    break;
226636ac495dSmrg 	  case SYMBOL_REF:
226736ac495dSmrg 	    *total += COSTS_N_INSNS (3);
226836ac495dSmrg 	    break;
226936ac495dSmrg 	  default:
227036ac495dSmrg 	    *total += COSTS_N_INSNS (2);
227136ac495dSmrg 	    break;
227236ac495dSmrg 	  }
227336ac495dSmrg 	return true;
227436ac495dSmrg       }
227536ac495dSmrg       break;
227636ac495dSmrg 
227736ac495dSmrg     default:
227836ac495dSmrg       /* Reasonable default.  */
227936ac495dSmrg       if (TARGET_A16 && mode == SImode)
228036ac495dSmrg 	*total += COSTS_N_INSNS (2);
228136ac495dSmrg       break;
228236ac495dSmrg     }
228336ac495dSmrg   return false;
228436ac495dSmrg }
228536ac495dSmrg 
228636ac495dSmrg #undef TARGET_ADDRESS_COST
228736ac495dSmrg #define TARGET_ADDRESS_COST m32c_address_cost
228836ac495dSmrg static int
m32c_address_cost(rtx addr,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)228936ac495dSmrg m32c_address_cost (rtx addr, machine_mode mode ATTRIBUTE_UNUSED,
229036ac495dSmrg 		   addr_space_t as ATTRIBUTE_UNUSED,
229136ac495dSmrg 		   bool speed ATTRIBUTE_UNUSED)
229236ac495dSmrg {
229336ac495dSmrg   int i;
229436ac495dSmrg   /*  fprintf(stderr, "\naddress_cost\n");
229536ac495dSmrg       debug_rtx(addr);*/
229636ac495dSmrg   switch (GET_CODE (addr))
229736ac495dSmrg     {
229836ac495dSmrg     case CONST_INT:
229936ac495dSmrg       i = INTVAL (addr);
230036ac495dSmrg       if (i == 0)
230136ac495dSmrg 	return COSTS_N_INSNS(1);
2302a2dc1f3fSmrg       if (i > 0 && i <= 255)
230336ac495dSmrg 	return COSTS_N_INSNS(2);
2304a2dc1f3fSmrg       if (i > 0 && i <= 65535)
230536ac495dSmrg 	return COSTS_N_INSNS(3);
230636ac495dSmrg       return COSTS_N_INSNS(4);
230736ac495dSmrg     case SYMBOL_REF:
230836ac495dSmrg       return COSTS_N_INSNS(4);
230936ac495dSmrg     case REG:
231036ac495dSmrg       return COSTS_N_INSNS(1);
231136ac495dSmrg     case PLUS:
231236ac495dSmrg       if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
231336ac495dSmrg 	{
231436ac495dSmrg 	  i = INTVAL (XEXP (addr, 1));
231536ac495dSmrg 	  if (i == 0)
231636ac495dSmrg 	    return COSTS_N_INSNS(1);
2317a2dc1f3fSmrg 	  if (i > 0 && i <= 255)
231836ac495dSmrg 	    return COSTS_N_INSNS(2);
2319a2dc1f3fSmrg 	  if (i > 0 && i <= 65535)
232036ac495dSmrg 	    return COSTS_N_INSNS(3);
232136ac495dSmrg 	}
232236ac495dSmrg       return COSTS_N_INSNS(4);
232336ac495dSmrg     default:
232436ac495dSmrg       return 0;
232536ac495dSmrg     }
232636ac495dSmrg }
232736ac495dSmrg 
232836ac495dSmrg /* Defining the Output Assembler Language */
232936ac495dSmrg 
233036ac495dSmrg /* Output of Data */
233136ac495dSmrg 
233236ac495dSmrg /* We may have 24 bit sizes, which is the native address size.
233336ac495dSmrg    Currently unused, but provided for completeness.  */
233436ac495dSmrg #undef TARGET_ASM_INTEGER
233536ac495dSmrg #define TARGET_ASM_INTEGER m32c_asm_integer
233636ac495dSmrg static bool
m32c_asm_integer(rtx x,unsigned int size,int aligned_p)233736ac495dSmrg m32c_asm_integer (rtx x, unsigned int size, int aligned_p)
233836ac495dSmrg {
233936ac495dSmrg   switch (size)
234036ac495dSmrg     {
234136ac495dSmrg     case 3:
234236ac495dSmrg       fprintf (asm_out_file, "\t.3byte\t");
234336ac495dSmrg       output_addr_const (asm_out_file, x);
234436ac495dSmrg       fputc ('\n', asm_out_file);
234536ac495dSmrg       return true;
234636ac495dSmrg     case 4:
234736ac495dSmrg       if (GET_CODE (x) == SYMBOL_REF)
234836ac495dSmrg 	{
234936ac495dSmrg 	  fprintf (asm_out_file, "\t.long\t");
235036ac495dSmrg 	  output_addr_const (asm_out_file, x);
235136ac495dSmrg 	  fputc ('\n', asm_out_file);
235236ac495dSmrg 	  return true;
235336ac495dSmrg 	}
235436ac495dSmrg       break;
235536ac495dSmrg     }
235636ac495dSmrg   return default_assemble_integer (x, size, aligned_p);
235736ac495dSmrg }
235836ac495dSmrg 
235936ac495dSmrg /* Output of Assembler Instructions */
236036ac495dSmrg 
236136ac495dSmrg /* We use a lookup table because the addressing modes are non-orthogonal.  */
236236ac495dSmrg 
236336ac495dSmrg static struct
236436ac495dSmrg {
236536ac495dSmrg   char code;
236636ac495dSmrg   char const *pattern;
236736ac495dSmrg   char const *format;
236836ac495dSmrg }
236936ac495dSmrg const conversions[] = {
237036ac495dSmrg   { 0, "r", "0" },
237136ac495dSmrg 
237236ac495dSmrg   { 0, "mr", "z[1]" },
237336ac495dSmrg   { 0, "m+ri", "3[2]" },
237436ac495dSmrg   { 0, "m+rs", "3[2]" },
237536ac495dSmrg   { 0, "m+^Zrs", "5[4]" },
237636ac495dSmrg   { 0, "m+^Zri", "5[4]" },
237736ac495dSmrg   { 0, "m+^Z+ris", "7+6[5]" },
237836ac495dSmrg   { 0, "m+^Srs", "5[4]" },
237936ac495dSmrg   { 0, "m+^Sri", "5[4]" },
238036ac495dSmrg   { 0, "m+^S+ris", "7+6[5]" },
238136ac495dSmrg   { 0, "m+r+si", "4+5[2]" },
238236ac495dSmrg   { 0, "ms", "1" },
238336ac495dSmrg   { 0, "mi", "1" },
238436ac495dSmrg   { 0, "m+si", "2+3" },
238536ac495dSmrg 
238636ac495dSmrg   { 0, "mmr", "[z[2]]" },
238736ac495dSmrg   { 0, "mm+ri", "[4[3]]" },
238836ac495dSmrg   { 0, "mm+rs", "[4[3]]" },
238936ac495dSmrg   { 0, "mm+r+si", "[5+6[3]]" },
239036ac495dSmrg   { 0, "mms", "[[2]]" },
239136ac495dSmrg   { 0, "mmi", "[[2]]" },
239236ac495dSmrg   { 0, "mm+si", "[4[3]]" },
239336ac495dSmrg 
239436ac495dSmrg   { 0, "i", "#0" },
239536ac495dSmrg   { 0, "s", "#0" },
239636ac495dSmrg   { 0, "+si", "#1+2" },
239736ac495dSmrg   { 0, "l", "#0" },
239836ac495dSmrg 
239936ac495dSmrg   { 'l', "l", "0" },
240036ac495dSmrg   { 'd', "i", "0" },
240136ac495dSmrg   { 'd', "s", "0" },
240236ac495dSmrg   { 'd', "+si", "1+2" },
240336ac495dSmrg   { 'D', "i", "0" },
240436ac495dSmrg   { 'D', "s", "0" },
240536ac495dSmrg   { 'D', "+si", "1+2" },
240636ac495dSmrg   { 'x', "i", "#0" },
240736ac495dSmrg   { 'X', "i", "#0" },
240836ac495dSmrg   { 'm', "i", "#0" },
240936ac495dSmrg   { 'b', "i", "#0" },
241036ac495dSmrg   { 'B', "i", "0" },
241136ac495dSmrg   { 'p', "i", "0" },
241236ac495dSmrg 
241336ac495dSmrg   { 0, 0, 0 }
241436ac495dSmrg };
241536ac495dSmrg 
241636ac495dSmrg /* This is in order according to the bitfield that pushm/popm use.  */
241736ac495dSmrg static char const *pushm_regs[] = {
241836ac495dSmrg   "fb", "sb", "a1", "a0", "r3", "r2", "r1", "r0"
241936ac495dSmrg };
242036ac495dSmrg 
242136ac495dSmrg /* Implements TARGET_PRINT_OPERAND.  */
242236ac495dSmrg 
242336ac495dSmrg #undef TARGET_PRINT_OPERAND
242436ac495dSmrg #define TARGET_PRINT_OPERAND m32c_print_operand
242536ac495dSmrg 
242636ac495dSmrg static void
m32c_print_operand(FILE * file,rtx x,int code)242736ac495dSmrg m32c_print_operand (FILE * file, rtx x, int code)
242836ac495dSmrg {
242936ac495dSmrg   int i, j, b;
243036ac495dSmrg   const char *comma;
243136ac495dSmrg   HOST_WIDE_INT ival;
243236ac495dSmrg   int unsigned_const = 0;
243336ac495dSmrg   int force_sign;
243436ac495dSmrg 
243536ac495dSmrg   /* Multiplies; constants are converted to sign-extended format but
243636ac495dSmrg    we need unsigned, so 'u' and 'U' tell us what size unsigned we
243736ac495dSmrg    need.  */
243836ac495dSmrg   if (code == 'u')
243936ac495dSmrg     {
244036ac495dSmrg       unsigned_const = 2;
244136ac495dSmrg       code = 0;
244236ac495dSmrg     }
244336ac495dSmrg   if (code == 'U')
244436ac495dSmrg     {
244536ac495dSmrg       unsigned_const = 1;
244636ac495dSmrg       code = 0;
244736ac495dSmrg     }
244836ac495dSmrg   /* This one is only for debugging; you can put it in a pattern to
244936ac495dSmrg      force this error.  */
245036ac495dSmrg   if (code == '!')
245136ac495dSmrg     {
245236ac495dSmrg       fprintf (stderr, "dj: unreviewed pattern:");
245336ac495dSmrg       if (current_output_insn)
245436ac495dSmrg 	debug_rtx (current_output_insn);
245536ac495dSmrg       gcc_unreachable ();
245636ac495dSmrg     }
245736ac495dSmrg   /* PSImode operations are either .w or .l depending on the target.  */
245836ac495dSmrg   if (code == '&')
245936ac495dSmrg     {
246036ac495dSmrg       if (TARGET_A16)
246136ac495dSmrg 	fprintf (file, "w");
246236ac495dSmrg       else
246336ac495dSmrg 	fprintf (file, "l");
246436ac495dSmrg       return;
246536ac495dSmrg     }
246636ac495dSmrg   /* Inverted conditionals.  */
246736ac495dSmrg   if (code == 'C')
246836ac495dSmrg     {
246936ac495dSmrg       switch (GET_CODE (x))
247036ac495dSmrg 	{
247136ac495dSmrg 	case LE:
247236ac495dSmrg 	  fputs ("gt", file);
247336ac495dSmrg 	  break;
247436ac495dSmrg 	case LEU:
247536ac495dSmrg 	  fputs ("gtu", file);
247636ac495dSmrg 	  break;
247736ac495dSmrg 	case LT:
247836ac495dSmrg 	  fputs ("ge", file);
247936ac495dSmrg 	  break;
248036ac495dSmrg 	case LTU:
248136ac495dSmrg 	  fputs ("geu", file);
248236ac495dSmrg 	  break;
248336ac495dSmrg 	case GT:
248436ac495dSmrg 	  fputs ("le", file);
248536ac495dSmrg 	  break;
248636ac495dSmrg 	case GTU:
248736ac495dSmrg 	  fputs ("leu", file);
248836ac495dSmrg 	  break;
248936ac495dSmrg 	case GE:
249036ac495dSmrg 	  fputs ("lt", file);
249136ac495dSmrg 	  break;
249236ac495dSmrg 	case GEU:
249336ac495dSmrg 	  fputs ("ltu", file);
249436ac495dSmrg 	  break;
249536ac495dSmrg 	case NE:
249636ac495dSmrg 	  fputs ("eq", file);
249736ac495dSmrg 	  break;
249836ac495dSmrg 	case EQ:
249936ac495dSmrg 	  fputs ("ne", file);
250036ac495dSmrg 	  break;
250136ac495dSmrg 	default:
250236ac495dSmrg 	  gcc_unreachable ();
250336ac495dSmrg 	}
250436ac495dSmrg       return;
250536ac495dSmrg     }
250636ac495dSmrg   /* Regular conditionals.  */
250736ac495dSmrg   if (code == 'c')
250836ac495dSmrg     {
250936ac495dSmrg       switch (GET_CODE (x))
251036ac495dSmrg 	{
251136ac495dSmrg 	case LE:
251236ac495dSmrg 	  fputs ("le", file);
251336ac495dSmrg 	  break;
251436ac495dSmrg 	case LEU:
251536ac495dSmrg 	  fputs ("leu", file);
251636ac495dSmrg 	  break;
251736ac495dSmrg 	case LT:
251836ac495dSmrg 	  fputs ("lt", file);
251936ac495dSmrg 	  break;
252036ac495dSmrg 	case LTU:
252136ac495dSmrg 	  fputs ("ltu", file);
252236ac495dSmrg 	  break;
252336ac495dSmrg 	case GT:
252436ac495dSmrg 	  fputs ("gt", file);
252536ac495dSmrg 	  break;
252636ac495dSmrg 	case GTU:
252736ac495dSmrg 	  fputs ("gtu", file);
252836ac495dSmrg 	  break;
252936ac495dSmrg 	case GE:
253036ac495dSmrg 	  fputs ("ge", file);
253136ac495dSmrg 	  break;
253236ac495dSmrg 	case GEU:
253336ac495dSmrg 	  fputs ("geu", file);
253436ac495dSmrg 	  break;
253536ac495dSmrg 	case NE:
253636ac495dSmrg 	  fputs ("ne", file);
253736ac495dSmrg 	  break;
253836ac495dSmrg 	case EQ:
253936ac495dSmrg 	  fputs ("eq", file);
254036ac495dSmrg 	  break;
254136ac495dSmrg 	default:
254236ac495dSmrg 	  gcc_unreachable ();
254336ac495dSmrg 	}
254436ac495dSmrg       return;
254536ac495dSmrg     }
254636ac495dSmrg   /* Used in negsi2 to do HImode ops on the two parts of an SImode
254736ac495dSmrg      operand.  */
254836ac495dSmrg   if (code == 'h' && GET_MODE (x) == SImode)
254936ac495dSmrg     {
255036ac495dSmrg       x = m32c_subreg (HImode, x, SImode, 0);
255136ac495dSmrg       code = 0;
255236ac495dSmrg     }
255336ac495dSmrg   if (code == 'H' && GET_MODE (x) == SImode)
255436ac495dSmrg     {
255536ac495dSmrg       x = m32c_subreg (HImode, x, SImode, 2);
255636ac495dSmrg       code = 0;
255736ac495dSmrg     }
255836ac495dSmrg   if (code == 'h' && GET_MODE (x) == HImode)
255936ac495dSmrg     {
256036ac495dSmrg       x = m32c_subreg (QImode, x, HImode, 0);
256136ac495dSmrg       code = 0;
256236ac495dSmrg     }
256336ac495dSmrg   if (code == 'H' && GET_MODE (x) == HImode)
256436ac495dSmrg     {
256536ac495dSmrg       /* We can't actually represent this as an rtx.  Do it here.  */
256636ac495dSmrg       if (GET_CODE (x) == REG)
256736ac495dSmrg 	{
256836ac495dSmrg 	  switch (REGNO (x))
256936ac495dSmrg 	    {
257036ac495dSmrg 	    case R0_REGNO:
257136ac495dSmrg 	      fputs ("r0h", file);
257236ac495dSmrg 	      return;
257336ac495dSmrg 	    case R1_REGNO:
257436ac495dSmrg 	      fputs ("r1h", file);
257536ac495dSmrg 	      return;
257636ac495dSmrg 	    default:
257736ac495dSmrg 	      gcc_unreachable();
257836ac495dSmrg 	    }
257936ac495dSmrg 	}
258036ac495dSmrg       /* This should be a MEM.  */
258136ac495dSmrg       x = m32c_subreg (QImode, x, HImode, 1);
258236ac495dSmrg       code = 0;
258336ac495dSmrg     }
258436ac495dSmrg   /* This is for BMcond, which always wants word register names.  */
258536ac495dSmrg   if (code == 'h' && GET_MODE (x) == QImode)
258636ac495dSmrg     {
258736ac495dSmrg       if (GET_CODE (x) == REG)
258836ac495dSmrg 	x = gen_rtx_REG (HImode, REGNO (x));
258936ac495dSmrg       code = 0;
259036ac495dSmrg     }
259136ac495dSmrg   /* 'x' and 'X' need to be ignored for non-immediates.  */
259236ac495dSmrg   if ((code == 'x' || code == 'X') && GET_CODE (x) != CONST_INT)
259336ac495dSmrg     code = 0;
259436ac495dSmrg 
259536ac495dSmrg   encode_pattern (x);
259636ac495dSmrg   force_sign = 0;
259736ac495dSmrg   for (i = 0; conversions[i].pattern; i++)
259836ac495dSmrg     if (conversions[i].code == code
259936ac495dSmrg 	&& streq (conversions[i].pattern, pattern))
260036ac495dSmrg       {
260136ac495dSmrg 	for (j = 0; conversions[i].format[j]; j++)
260236ac495dSmrg 	  /* backslash quotes the next character in the output pattern.  */
260336ac495dSmrg 	  if (conversions[i].format[j] == '\\')
260436ac495dSmrg 	    {
260536ac495dSmrg 	      fputc (conversions[i].format[j + 1], file);
260636ac495dSmrg 	      j++;
260736ac495dSmrg 	    }
260836ac495dSmrg 	  /* Digits in the output pattern indicate that the
260936ac495dSmrg 	     corresponding RTX is to be output at that point.  */
261036ac495dSmrg 	  else if (ISDIGIT (conversions[i].format[j]))
261136ac495dSmrg 	    {
261236ac495dSmrg 	      rtx r = patternr[conversions[i].format[j] - '0'];
261336ac495dSmrg 	      switch (GET_CODE (r))
261436ac495dSmrg 		{
261536ac495dSmrg 		case REG:
261636ac495dSmrg 		  fprintf (file, "%s",
261736ac495dSmrg 			   reg_name_with_mode (REGNO (r), GET_MODE (r)));
261836ac495dSmrg 		  break;
261936ac495dSmrg 		case CONST_INT:
262036ac495dSmrg 		  switch (code)
262136ac495dSmrg 		    {
262236ac495dSmrg 		    case 'b':
262336ac495dSmrg 		    case 'B':
262436ac495dSmrg 		      {
262536ac495dSmrg 			int v = INTVAL (r);
262636ac495dSmrg 			int i = (int) exact_log2 (v);
262736ac495dSmrg 			if (i == -1)
262836ac495dSmrg 			  i = (int) exact_log2 ((v ^ 0xffff) & 0xffff);
262936ac495dSmrg 			if (i == -1)
263036ac495dSmrg 			  i = (int) exact_log2 ((v ^ 0xff) & 0xff);
263136ac495dSmrg 			/* Bit position.  */
263236ac495dSmrg 			fprintf (file, "%d", i);
263336ac495dSmrg 		      }
263436ac495dSmrg 		      break;
263536ac495dSmrg 		    case 'x':
263636ac495dSmrg 		      /* Unsigned byte.  */
263736ac495dSmrg 		      fprintf (file, HOST_WIDE_INT_PRINT_HEX,
263836ac495dSmrg 			       INTVAL (r) & 0xff);
263936ac495dSmrg 		      break;
264036ac495dSmrg 		    case 'X':
264136ac495dSmrg 		      /* Unsigned word.  */
264236ac495dSmrg 		      fprintf (file, HOST_WIDE_INT_PRINT_HEX,
264336ac495dSmrg 			       INTVAL (r) & 0xffff);
264436ac495dSmrg 		      break;
264536ac495dSmrg 		    case 'p':
264636ac495dSmrg 		      /* pushm and popm encode a register set into a single byte.  */
264736ac495dSmrg 		      comma = "";
264836ac495dSmrg 		      for (b = 7; b >= 0; b--)
264936ac495dSmrg 			if (INTVAL (r) & (1 << b))
265036ac495dSmrg 			  {
265136ac495dSmrg 			    fprintf (file, "%s%s", comma, pushm_regs[b]);
265236ac495dSmrg 			    comma = ",";
265336ac495dSmrg 			  }
265436ac495dSmrg 		      break;
265536ac495dSmrg 		    case 'm':
265636ac495dSmrg 		      /* "Minus".  Output -X  */
265736ac495dSmrg 		      ival = (-INTVAL (r) & 0xffff);
265836ac495dSmrg 		      if (ival & 0x8000)
265936ac495dSmrg 			ival = ival - 0x10000;
266036ac495dSmrg 		      fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
266136ac495dSmrg 		      break;
266236ac495dSmrg 		    default:
266336ac495dSmrg 		      ival = INTVAL (r);
266436ac495dSmrg 		      if (conversions[i].format[j + 1] == '[' && ival < 0)
266536ac495dSmrg 			{
266636ac495dSmrg 			  /* We can simulate negative displacements by
266736ac495dSmrg 			     taking advantage of address space
266836ac495dSmrg 			     wrapping when the offset can span the
266936ac495dSmrg 			     entire address range.  */
267036ac495dSmrg 			  rtx base =
267136ac495dSmrg 			    patternr[conversions[i].format[j + 2] - '0'];
267236ac495dSmrg 			  if (GET_CODE (base) == REG)
267336ac495dSmrg 			    switch (REGNO (base))
267436ac495dSmrg 			      {
267536ac495dSmrg 			      case A0_REGNO:
267636ac495dSmrg 			      case A1_REGNO:
267736ac495dSmrg 				if (TARGET_A24)
267836ac495dSmrg 				  ival = 0x1000000 + ival;
267936ac495dSmrg 				else
268036ac495dSmrg 				  ival = 0x10000 + ival;
268136ac495dSmrg 				break;
268236ac495dSmrg 			      case SB_REGNO:
268336ac495dSmrg 				if (TARGET_A16)
268436ac495dSmrg 				  ival = 0x10000 + ival;
268536ac495dSmrg 				break;
268636ac495dSmrg 			      }
268736ac495dSmrg 			}
268836ac495dSmrg 		      else if (code == 'd' && ival < 0 && j == 0)
268936ac495dSmrg 			/* The "mova" opcode is used to do addition by
269036ac495dSmrg 			   computing displacements, but again, we need
269136ac495dSmrg 			   displacements to be unsigned *if* they're
269236ac495dSmrg 			   the only component of the displacement
269336ac495dSmrg 			   (i.e. no "symbol-4" type displacement).  */
269436ac495dSmrg 			ival = (TARGET_A24 ? 0x1000000 : 0x10000) + ival;
269536ac495dSmrg 
269636ac495dSmrg 		      if (conversions[i].format[j] == '0')
269736ac495dSmrg 			{
269836ac495dSmrg 			  /* More conversions to unsigned.  */
269936ac495dSmrg 			  if (unsigned_const == 2)
270036ac495dSmrg 			    ival &= 0xffff;
270136ac495dSmrg 			  if (unsigned_const == 1)
270236ac495dSmrg 			    ival &= 0xff;
270336ac495dSmrg 			}
270436ac495dSmrg 		      if (streq (conversions[i].pattern, "mi")
270536ac495dSmrg 			  || streq (conversions[i].pattern, "mmi"))
270636ac495dSmrg 			{
270736ac495dSmrg 			  /* Integers used as addresses are unsigned.  */
270836ac495dSmrg 			  ival &= (TARGET_A24 ? 0xffffff : 0xffff);
270936ac495dSmrg 			}
271036ac495dSmrg 		      if (force_sign && ival >= 0)
271136ac495dSmrg 			fputc ('+', file);
271236ac495dSmrg 		      fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
271336ac495dSmrg 		      break;
271436ac495dSmrg 		    }
271536ac495dSmrg 		  break;
271636ac495dSmrg 		case CONST_DOUBLE:
271736ac495dSmrg 		  /* We don't have const_double constants.  If it
271836ac495dSmrg 		     happens, make it obvious.  */
271936ac495dSmrg 		  fprintf (file, "[const_double 0x%lx]",
272036ac495dSmrg 			   (unsigned long) CONST_DOUBLE_HIGH (r));
272136ac495dSmrg 		  break;
272236ac495dSmrg 		case SYMBOL_REF:
272336ac495dSmrg 		  assemble_name (file, XSTR (r, 0));
272436ac495dSmrg 		  break;
272536ac495dSmrg 		case LABEL_REF:
272636ac495dSmrg 		  output_asm_label (r);
272736ac495dSmrg 		  break;
272836ac495dSmrg 		default:
272936ac495dSmrg 		  fprintf (stderr, "don't know how to print this operand:");
273036ac495dSmrg 		  debug_rtx (r);
273136ac495dSmrg 		  gcc_unreachable ();
273236ac495dSmrg 		}
273336ac495dSmrg 	    }
273436ac495dSmrg 	  else
273536ac495dSmrg 	    {
273636ac495dSmrg 	      if (conversions[i].format[j] == 'z')
273736ac495dSmrg 		{
273836ac495dSmrg 		  /* Some addressing modes *must* have a displacement,
273936ac495dSmrg 		     so insert a zero here if needed.  */
274036ac495dSmrg 		  int k;
274136ac495dSmrg 		  for (k = j + 1; conversions[i].format[k]; k++)
274236ac495dSmrg 		    if (ISDIGIT (conversions[i].format[k]))
274336ac495dSmrg 		      {
274436ac495dSmrg 			rtx reg = patternr[conversions[i].format[k] - '0'];
274536ac495dSmrg 			if (GET_CODE (reg) == REG
274636ac495dSmrg 			    && (REGNO (reg) == SB_REGNO
274736ac495dSmrg 				|| REGNO (reg) == FB_REGNO
274836ac495dSmrg 				|| REGNO (reg) == SP_REGNO))
274936ac495dSmrg 			  fputc ('0', file);
275036ac495dSmrg 		      }
275136ac495dSmrg 		  continue;
275236ac495dSmrg 		}
275336ac495dSmrg 	      /* Signed displacements off symbols need to have signs
275436ac495dSmrg 		 blended cleanly.  */
275536ac495dSmrg 	      if (conversions[i].format[j] == '+'
275636ac495dSmrg 		  && (!code || code == 'D' || code == 'd')
275736ac495dSmrg 		  && ISDIGIT (conversions[i].format[j + 1])
275836ac495dSmrg 		  && (GET_CODE (patternr[conversions[i].format[j + 1] - '0'])
275936ac495dSmrg 		      == CONST_INT))
276036ac495dSmrg 		{
276136ac495dSmrg 		  force_sign = 1;
276236ac495dSmrg 		  continue;
276336ac495dSmrg 		}
276436ac495dSmrg 	      fputc (conversions[i].format[j], file);
276536ac495dSmrg 	    }
276636ac495dSmrg 	break;
276736ac495dSmrg       }
276836ac495dSmrg   if (!conversions[i].pattern)
276936ac495dSmrg     {
277036ac495dSmrg       fprintf (stderr, "unconvertible operand %c `%s'", code ? code : '-',
277136ac495dSmrg 	       pattern);
277236ac495dSmrg       debug_rtx (x);
277336ac495dSmrg       fprintf (file, "[%c.%s]", code ? code : '-', pattern);
277436ac495dSmrg     }
277536ac495dSmrg 
277636ac495dSmrg   return;
277736ac495dSmrg }
277836ac495dSmrg 
277936ac495dSmrg /* Implements TARGET_PRINT_OPERAND_PUNCT_VALID_P.
278036ac495dSmrg 
278136ac495dSmrg    See m32c_print_operand above for descriptions of what these do.  */
278236ac495dSmrg 
278336ac495dSmrg #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
278436ac495dSmrg #define TARGET_PRINT_OPERAND_PUNCT_VALID_P m32c_print_operand_punct_valid_p
278536ac495dSmrg 
278636ac495dSmrg static bool
m32c_print_operand_punct_valid_p(unsigned char c)278736ac495dSmrg m32c_print_operand_punct_valid_p (unsigned char c)
278836ac495dSmrg {
278936ac495dSmrg   if (c == '&' || c == '!')
279036ac495dSmrg     return true;
279136ac495dSmrg 
279236ac495dSmrg   return false;
279336ac495dSmrg }
279436ac495dSmrg 
279536ac495dSmrg /* Implements TARGET_PRINT_OPERAND_ADDRESS.  Nothing unusual here.  */
279636ac495dSmrg 
279736ac495dSmrg #undef TARGET_PRINT_OPERAND_ADDRESS
279836ac495dSmrg #define TARGET_PRINT_OPERAND_ADDRESS m32c_print_operand_address
279936ac495dSmrg 
280036ac495dSmrg static void
m32c_print_operand_address(FILE * stream,machine_mode,rtx address)280136ac495dSmrg m32c_print_operand_address (FILE * stream, machine_mode /*mode*/, rtx address)
280236ac495dSmrg {
280336ac495dSmrg   if (GET_CODE (address) == MEM)
280436ac495dSmrg     address = XEXP (address, 0);
280536ac495dSmrg   else
280636ac495dSmrg     /* cf: gcc.dg/asm-4.c.  */
280736ac495dSmrg     gcc_assert (GET_CODE (address) == REG);
280836ac495dSmrg 
280936ac495dSmrg   m32c_print_operand (stream, address, 0);
281036ac495dSmrg }
281136ac495dSmrg 
281236ac495dSmrg /* Implements ASM_OUTPUT_REG_PUSH.  Control registers are pushed
281336ac495dSmrg    differently than general registers.  */
281436ac495dSmrg void
m32c_output_reg_push(FILE * s,int regno)281536ac495dSmrg m32c_output_reg_push (FILE * s, int regno)
281636ac495dSmrg {
281736ac495dSmrg   if (regno == FLG_REGNO)
281836ac495dSmrg     fprintf (s, "\tpushc\tflg\n");
281936ac495dSmrg   else
282036ac495dSmrg     fprintf (s, "\tpush.%c\t%s\n",
282136ac495dSmrg 	     " bwll"[reg_push_size (regno)], reg_names[regno]);
282236ac495dSmrg }
282336ac495dSmrg 
282436ac495dSmrg /* Likewise for ASM_OUTPUT_REG_POP.  */
282536ac495dSmrg void
m32c_output_reg_pop(FILE * s,int regno)282636ac495dSmrg m32c_output_reg_pop (FILE * s, int regno)
282736ac495dSmrg {
282836ac495dSmrg   if (regno == FLG_REGNO)
282936ac495dSmrg     fprintf (s, "\tpopc\tflg\n");
283036ac495dSmrg   else
283136ac495dSmrg     fprintf (s, "\tpop.%c\t%s\n",
283236ac495dSmrg 	     " bwll"[reg_push_size (regno)], reg_names[regno]);
283336ac495dSmrg }
283436ac495dSmrg 
283536ac495dSmrg /* Defining target-specific uses of `__attribute__' */
283636ac495dSmrg 
283736ac495dSmrg /* Used to simplify the logic below.  Find the attributes wherever
283836ac495dSmrg    they may be.  */
283936ac495dSmrg #define M32C_ATTRIBUTES(decl) \
284036ac495dSmrg   (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \
284136ac495dSmrg                 : DECL_ATTRIBUTES (decl) \
284236ac495dSmrg                   ? (DECL_ATTRIBUTES (decl)) \
284336ac495dSmrg 		  : TYPE_ATTRIBUTES (TREE_TYPE (decl))
284436ac495dSmrg 
284536ac495dSmrg /* Returns TRUE if the given tree has the "interrupt" attribute.  */
284636ac495dSmrg static int
interrupt_p(tree node ATTRIBUTE_UNUSED)284736ac495dSmrg interrupt_p (tree node ATTRIBUTE_UNUSED)
284836ac495dSmrg {
284936ac495dSmrg   tree list = M32C_ATTRIBUTES (node);
285036ac495dSmrg   while (list)
285136ac495dSmrg     {
285236ac495dSmrg       if (is_attribute_p ("interrupt", TREE_PURPOSE (list)))
285336ac495dSmrg 	return 1;
285436ac495dSmrg       list = TREE_CHAIN (list);
285536ac495dSmrg     }
285636ac495dSmrg   return fast_interrupt_p (node);
285736ac495dSmrg }
285836ac495dSmrg 
285936ac495dSmrg /* Returns TRUE if the given tree has the "bank_switch" attribute.  */
286036ac495dSmrg static int
bank_switch_p(tree node ATTRIBUTE_UNUSED)286136ac495dSmrg bank_switch_p (tree node ATTRIBUTE_UNUSED)
286236ac495dSmrg {
286336ac495dSmrg   tree list = M32C_ATTRIBUTES (node);
286436ac495dSmrg   while (list)
286536ac495dSmrg     {
286636ac495dSmrg       if (is_attribute_p ("bank_switch", TREE_PURPOSE (list)))
286736ac495dSmrg 	return 1;
286836ac495dSmrg       list = TREE_CHAIN (list);
286936ac495dSmrg     }
287036ac495dSmrg   return 0;
287136ac495dSmrg }
287236ac495dSmrg 
287336ac495dSmrg /* Returns TRUE if the given tree has the "fast_interrupt" attribute.  */
287436ac495dSmrg static int
fast_interrupt_p(tree node ATTRIBUTE_UNUSED)287536ac495dSmrg fast_interrupt_p (tree node ATTRIBUTE_UNUSED)
287636ac495dSmrg {
287736ac495dSmrg   tree list = M32C_ATTRIBUTES (node);
287836ac495dSmrg   while (list)
287936ac495dSmrg     {
288036ac495dSmrg       if (is_attribute_p ("fast_interrupt", TREE_PURPOSE (list)))
288136ac495dSmrg 	return 1;
288236ac495dSmrg       list = TREE_CHAIN (list);
288336ac495dSmrg     }
288436ac495dSmrg   return 0;
288536ac495dSmrg }
288636ac495dSmrg 
288736ac495dSmrg static tree
interrupt_handler(tree * node ATTRIBUTE_UNUSED,tree name ATTRIBUTE_UNUSED,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs ATTRIBUTE_UNUSED)288836ac495dSmrg interrupt_handler (tree * node ATTRIBUTE_UNUSED,
288936ac495dSmrg 		   tree name ATTRIBUTE_UNUSED,
289036ac495dSmrg 		   tree args ATTRIBUTE_UNUSED,
289136ac495dSmrg 		   int flags ATTRIBUTE_UNUSED,
289236ac495dSmrg 		   bool * no_add_attrs ATTRIBUTE_UNUSED)
289336ac495dSmrg {
289436ac495dSmrg   return NULL_TREE;
289536ac495dSmrg }
289636ac495dSmrg 
289736ac495dSmrg /* Returns TRUE if given tree has the "function_vector" attribute. */
289836ac495dSmrg int
m32c_special_page_vector_p(tree func)289936ac495dSmrg m32c_special_page_vector_p (tree func)
290036ac495dSmrg {
290136ac495dSmrg   tree list;
290236ac495dSmrg 
290336ac495dSmrg   if (TREE_CODE (func) != FUNCTION_DECL)
290436ac495dSmrg     return 0;
290536ac495dSmrg 
290636ac495dSmrg   list = M32C_ATTRIBUTES (func);
290736ac495dSmrg   while (list)
290836ac495dSmrg     {
290936ac495dSmrg       if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
291036ac495dSmrg         return 1;
291136ac495dSmrg       list = TREE_CHAIN (list);
291236ac495dSmrg     }
291336ac495dSmrg   return 0;
291436ac495dSmrg }
291536ac495dSmrg 
291636ac495dSmrg static tree
function_vector_handler(tree * node ATTRIBUTE_UNUSED,tree name ATTRIBUTE_UNUSED,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs ATTRIBUTE_UNUSED)291736ac495dSmrg function_vector_handler (tree * node ATTRIBUTE_UNUSED,
291836ac495dSmrg                          tree name ATTRIBUTE_UNUSED,
291936ac495dSmrg                          tree args ATTRIBUTE_UNUSED,
292036ac495dSmrg                          int flags ATTRIBUTE_UNUSED,
292136ac495dSmrg                          bool * no_add_attrs ATTRIBUTE_UNUSED)
292236ac495dSmrg {
292336ac495dSmrg   if (TARGET_R8C)
292436ac495dSmrg     {
292536ac495dSmrg       /* The attribute is not supported for R8C target.  */
292636ac495dSmrg       warning (OPT_Wattributes,
292736ac495dSmrg                 "%qE attribute is not supported for R8C target",
292836ac495dSmrg                 name);
292936ac495dSmrg       *no_add_attrs = true;
293036ac495dSmrg     }
293136ac495dSmrg   else if (TREE_CODE (*node) != FUNCTION_DECL)
293236ac495dSmrg     {
293336ac495dSmrg       /* The attribute must be applied to functions only.  */
293436ac495dSmrg       warning (OPT_Wattributes,
293536ac495dSmrg                 "%qE attribute applies only to functions",
293636ac495dSmrg                 name);
293736ac495dSmrg       *no_add_attrs = true;
293836ac495dSmrg     }
293936ac495dSmrg   else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
294036ac495dSmrg     {
294136ac495dSmrg       /* The argument must be a constant integer.  */
294236ac495dSmrg       warning (OPT_Wattributes,
294336ac495dSmrg                 "%qE attribute argument not an integer constant",
294436ac495dSmrg                 name);
294536ac495dSmrg       *no_add_attrs = true;
294636ac495dSmrg     }
294736ac495dSmrg   else if (TREE_INT_CST_LOW (TREE_VALUE (args)) < 18
294836ac495dSmrg            || TREE_INT_CST_LOW (TREE_VALUE (args)) > 255)
294936ac495dSmrg     {
295036ac495dSmrg       /* The argument value must be between 18 to 255.  */
295136ac495dSmrg       warning (OPT_Wattributes,
295236ac495dSmrg                 "%qE attribute argument should be between 18 to 255",
295336ac495dSmrg                 name);
295436ac495dSmrg       *no_add_attrs = true;
295536ac495dSmrg     }
295636ac495dSmrg   return NULL_TREE;
295736ac495dSmrg }
295836ac495dSmrg 
295936ac495dSmrg /* If the function is assigned the attribute 'function_vector', it
296036ac495dSmrg    returns the function vector number, otherwise returns zero.  */
296136ac495dSmrg int
current_function_special_page_vector(rtx x)296236ac495dSmrg current_function_special_page_vector (rtx x)
296336ac495dSmrg {
296436ac495dSmrg   int num;
296536ac495dSmrg 
296636ac495dSmrg   if ((GET_CODE(x) == SYMBOL_REF)
296736ac495dSmrg       && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_FUNCVEC_FUNCTION))
296836ac495dSmrg     {
296936ac495dSmrg       tree list;
297036ac495dSmrg       tree t = SYMBOL_REF_DECL (x);
297136ac495dSmrg 
297236ac495dSmrg       if (TREE_CODE (t) != FUNCTION_DECL)
297336ac495dSmrg         return 0;
297436ac495dSmrg 
297536ac495dSmrg       list = M32C_ATTRIBUTES (t);
297636ac495dSmrg       while (list)
297736ac495dSmrg         {
297836ac495dSmrg           if (is_attribute_p ("function_vector", TREE_PURPOSE (list)))
297936ac495dSmrg             {
298036ac495dSmrg               num = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (list)));
298136ac495dSmrg               return num;
298236ac495dSmrg             }
298336ac495dSmrg 
298436ac495dSmrg           list = TREE_CHAIN (list);
298536ac495dSmrg         }
298636ac495dSmrg 
298736ac495dSmrg       return 0;
298836ac495dSmrg     }
298936ac495dSmrg   else
299036ac495dSmrg     return 0;
299136ac495dSmrg }
299236ac495dSmrg 
299336ac495dSmrg #undef TARGET_ATTRIBUTE_TABLE
299436ac495dSmrg #define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
299536ac495dSmrg static const struct attribute_spec m32c_attribute_table[] = {
2996a2dc1f3fSmrg   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
2997a2dc1f3fSmrg        affects_type_identity, handler, exclude } */
2998a2dc1f3fSmrg   { "interrupt", 0, 0, false, false, false, false, interrupt_handler, NULL },
2999a2dc1f3fSmrg   { "bank_switch", 0, 0, false, false, false, false, interrupt_handler, NULL },
3000a2dc1f3fSmrg   { "fast_interrupt", 0, 0, false, false, false, false,
3001a2dc1f3fSmrg     interrupt_handler, NULL },
3002a2dc1f3fSmrg   { "function_vector", 1, 1, true,  false, false, false,
3003a2dc1f3fSmrg     function_vector_handler, NULL },
3004a2dc1f3fSmrg   { NULL, 0, 0, false, false, false, false, NULL, NULL }
300536ac495dSmrg };
300636ac495dSmrg 
300736ac495dSmrg #undef TARGET_COMP_TYPE_ATTRIBUTES
300836ac495dSmrg #define TARGET_COMP_TYPE_ATTRIBUTES m32c_comp_type_attributes
300936ac495dSmrg static int
m32c_comp_type_attributes(const_tree type1 ATTRIBUTE_UNUSED,const_tree type2 ATTRIBUTE_UNUSED)301036ac495dSmrg m32c_comp_type_attributes (const_tree type1 ATTRIBUTE_UNUSED,
301136ac495dSmrg 			   const_tree type2 ATTRIBUTE_UNUSED)
301236ac495dSmrg {
301336ac495dSmrg   /* 0=incompatible 1=compatible 2=warning */
301436ac495dSmrg   return 1;
301536ac495dSmrg }
301636ac495dSmrg 
301736ac495dSmrg #undef TARGET_INSERT_ATTRIBUTES
301836ac495dSmrg #define TARGET_INSERT_ATTRIBUTES m32c_insert_attributes
301936ac495dSmrg static void
m32c_insert_attributes(tree node ATTRIBUTE_UNUSED,tree * attr_ptr ATTRIBUTE_UNUSED)302036ac495dSmrg m32c_insert_attributes (tree node ATTRIBUTE_UNUSED,
302136ac495dSmrg 			tree * attr_ptr ATTRIBUTE_UNUSED)
302236ac495dSmrg {
302336ac495dSmrg   unsigned addr;
302436ac495dSmrg   /* See if we need to make #pragma address variables volatile.  */
302536ac495dSmrg 
302636ac495dSmrg   if (TREE_CODE (node) == VAR_DECL)
302736ac495dSmrg     {
302836ac495dSmrg       const char *name = IDENTIFIER_POINTER (DECL_NAME (node));
302936ac495dSmrg       if (m32c_get_pragma_address  (name, &addr))
303036ac495dSmrg 	{
303136ac495dSmrg 	  TREE_THIS_VOLATILE (node) = true;
303236ac495dSmrg 	}
303336ac495dSmrg     }
303436ac495dSmrg }
303536ac495dSmrg 
303636ac495dSmrg /* Hash table of pragma info.  */
303736ac495dSmrg static GTY(()) hash_map<nofree_string_hash, unsigned> *pragma_htab;
303836ac495dSmrg 
303936ac495dSmrg void
m32c_note_pragma_address(const char * varname,unsigned address)304036ac495dSmrg m32c_note_pragma_address (const char *varname, unsigned address)
304136ac495dSmrg {
304236ac495dSmrg   if (!pragma_htab)
304336ac495dSmrg     pragma_htab = hash_map<nofree_string_hash, unsigned>::create_ggc (31);
304436ac495dSmrg 
304536ac495dSmrg   const char *name = ggc_strdup (varname);
304636ac495dSmrg   unsigned int *slot = &pragma_htab->get_or_insert (name);
304736ac495dSmrg   *slot = address;
304836ac495dSmrg }
304936ac495dSmrg 
305036ac495dSmrg static bool
m32c_get_pragma_address(const char * varname,unsigned * address)305136ac495dSmrg m32c_get_pragma_address (const char *varname, unsigned *address)
305236ac495dSmrg {
305336ac495dSmrg   if (!pragma_htab)
305436ac495dSmrg     return false;
305536ac495dSmrg 
305636ac495dSmrg   unsigned int *slot = pragma_htab->get (varname);
305736ac495dSmrg   if (slot)
305836ac495dSmrg     {
305936ac495dSmrg       *address = *slot;
306036ac495dSmrg       return true;
306136ac495dSmrg     }
306236ac495dSmrg   return false;
306336ac495dSmrg }
306436ac495dSmrg 
306536ac495dSmrg void
m32c_output_aligned_common(FILE * stream,tree decl ATTRIBUTE_UNUSED,const char * name,int size,int align,int global)306636ac495dSmrg m32c_output_aligned_common (FILE *stream, tree decl ATTRIBUTE_UNUSED,
306736ac495dSmrg 			    const char *name,
306836ac495dSmrg 			    int size, int align, int global)
306936ac495dSmrg {
307036ac495dSmrg   unsigned address;
307136ac495dSmrg 
307236ac495dSmrg   if (m32c_get_pragma_address (name, &address))
307336ac495dSmrg     {
307436ac495dSmrg       /* We never output these as global.  */
307536ac495dSmrg       assemble_name (stream, name);
307636ac495dSmrg       fprintf (stream, " = 0x%04x\n", address);
307736ac495dSmrg       return;
307836ac495dSmrg     }
307936ac495dSmrg   if (!global)
308036ac495dSmrg     {
308136ac495dSmrg       fprintf (stream, "\t.local\t");
308236ac495dSmrg       assemble_name (stream, name);
308336ac495dSmrg       fprintf (stream, "\n");
308436ac495dSmrg     }
308536ac495dSmrg   fprintf (stream, "\t.comm\t");
308636ac495dSmrg   assemble_name (stream, name);
308736ac495dSmrg   fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);
308836ac495dSmrg }
308936ac495dSmrg 
309036ac495dSmrg /* Predicates */
309136ac495dSmrg 
309236ac495dSmrg /* This is a list of legal subregs of hard regs.  */
309336ac495dSmrg static const struct {
309436ac495dSmrg   unsigned char outer_mode_size;
309536ac495dSmrg   unsigned char inner_mode_size;
309636ac495dSmrg   unsigned char byte_mask;
309736ac495dSmrg   unsigned char legal_when;
309836ac495dSmrg   unsigned int regno;
309936ac495dSmrg } legal_subregs[] = {
310036ac495dSmrg   {1, 2, 0x03, 1, R0_REGNO}, /* r0h r0l */
310136ac495dSmrg   {1, 2, 0x03, 1, R1_REGNO}, /* r1h r1l */
310236ac495dSmrg   {1, 2, 0x01, 1, A0_REGNO},
310336ac495dSmrg   {1, 2, 0x01, 1, A1_REGNO},
310436ac495dSmrg 
310536ac495dSmrg   {1, 4, 0x01, 1, A0_REGNO},
310636ac495dSmrg   {1, 4, 0x01, 1, A1_REGNO},
310736ac495dSmrg 
310836ac495dSmrg   {2, 4, 0x05, 1, R0_REGNO}, /* r2 r0 */
310936ac495dSmrg   {2, 4, 0x05, 1, R1_REGNO}, /* r3 r1 */
311036ac495dSmrg   {2, 4, 0x05, 16, A0_REGNO}, /* a1 a0 */
311136ac495dSmrg   {2, 4, 0x01, 24, A0_REGNO}, /* a1 a0 */
311236ac495dSmrg   {2, 4, 0x01, 24, A1_REGNO}, /* a1 a0 */
311336ac495dSmrg 
311436ac495dSmrg   {4, 8, 0x55, 1, R0_REGNO}, /* r3 r1 r2 r0 */
311536ac495dSmrg };
311636ac495dSmrg 
311736ac495dSmrg /* Returns TRUE if OP is a subreg of a hard reg which we don't
311836ac495dSmrg    support.  We also bail on MEMs with illegal addresses.  */
311936ac495dSmrg bool
m32c_illegal_subreg_p(rtx op)312036ac495dSmrg m32c_illegal_subreg_p (rtx op)
312136ac495dSmrg {
312236ac495dSmrg   int offset;
312336ac495dSmrg   unsigned int i;
312436ac495dSmrg   machine_mode src_mode, dest_mode;
312536ac495dSmrg 
312636ac495dSmrg   if (GET_CODE (op) == MEM
312736ac495dSmrg       && ! m32c_legitimate_address_p (Pmode, XEXP (op, 0), false))
312836ac495dSmrg     {
312936ac495dSmrg       return true;
313036ac495dSmrg     }
313136ac495dSmrg 
313236ac495dSmrg   if (GET_CODE (op) != SUBREG)
313336ac495dSmrg     return false;
313436ac495dSmrg 
313536ac495dSmrg   dest_mode = GET_MODE (op);
313636ac495dSmrg   offset = SUBREG_BYTE (op);
313736ac495dSmrg   op = SUBREG_REG (op);
313836ac495dSmrg   src_mode = GET_MODE (op);
313936ac495dSmrg 
314036ac495dSmrg   if (GET_MODE_SIZE (dest_mode) == GET_MODE_SIZE (src_mode))
314136ac495dSmrg     return false;
314236ac495dSmrg   if (GET_CODE (op) != REG)
314336ac495dSmrg     return false;
314436ac495dSmrg   if (REGNO (op) >= MEM0_REGNO)
314536ac495dSmrg     return false;
314636ac495dSmrg 
314736ac495dSmrg   offset = (1 << offset);
314836ac495dSmrg 
314936ac495dSmrg   for (i = 0; i < ARRAY_SIZE (legal_subregs); i ++)
315036ac495dSmrg     if (legal_subregs[i].outer_mode_size == GET_MODE_SIZE (dest_mode)
315136ac495dSmrg 	&& legal_subregs[i].regno == REGNO (op)
315236ac495dSmrg 	&& legal_subregs[i].inner_mode_size == GET_MODE_SIZE (src_mode)
315336ac495dSmrg 	&& legal_subregs[i].byte_mask & offset)
315436ac495dSmrg       {
315536ac495dSmrg 	switch (legal_subregs[i].legal_when)
315636ac495dSmrg 	  {
315736ac495dSmrg 	  case 1:
315836ac495dSmrg 	    return false;
315936ac495dSmrg 	  case 16:
316036ac495dSmrg 	    if (TARGET_A16)
316136ac495dSmrg 	      return false;
316236ac495dSmrg 	    break;
316336ac495dSmrg 	  case 24:
316436ac495dSmrg 	    if (TARGET_A24)
316536ac495dSmrg 	      return false;
316636ac495dSmrg 	    break;
316736ac495dSmrg 	  }
316836ac495dSmrg       }
316936ac495dSmrg   return true;
317036ac495dSmrg }
317136ac495dSmrg 
317236ac495dSmrg /* Returns TRUE if we support a move between the first two operands.
317336ac495dSmrg    At the moment, we just want to discourage mem to mem moves until
317436ac495dSmrg    after reload, because reload has a hard time with our limited
317536ac495dSmrg    number of address registers, and we can get into a situation where
317636ac495dSmrg    we need three of them when we only have two.  */
317736ac495dSmrg bool
m32c_mov_ok(rtx * operands,machine_mode mode ATTRIBUTE_UNUSED)317836ac495dSmrg m32c_mov_ok (rtx * operands, machine_mode mode ATTRIBUTE_UNUSED)
317936ac495dSmrg {
318036ac495dSmrg   rtx op0 = operands[0];
318136ac495dSmrg   rtx op1 = operands[1];
318236ac495dSmrg 
318336ac495dSmrg   if (TARGET_A24)
318436ac495dSmrg     return true;
318536ac495dSmrg 
318636ac495dSmrg #define DEBUG_MOV_OK 0
318736ac495dSmrg #if DEBUG_MOV_OK
318836ac495dSmrg   fprintf (stderr, "m32c_mov_ok %s\n", mode_name[mode]);
318936ac495dSmrg   debug_rtx (op0);
319036ac495dSmrg   debug_rtx (op1);
319136ac495dSmrg #endif
319236ac495dSmrg 
319336ac495dSmrg   if (GET_CODE (op0) == SUBREG)
319436ac495dSmrg     op0 = XEXP (op0, 0);
319536ac495dSmrg   if (GET_CODE (op1) == SUBREG)
319636ac495dSmrg     op1 = XEXP (op1, 0);
319736ac495dSmrg 
319836ac495dSmrg   if (GET_CODE (op0) == MEM
319936ac495dSmrg       && GET_CODE (op1) == MEM
320036ac495dSmrg       && ! reload_completed)
320136ac495dSmrg     {
320236ac495dSmrg #if DEBUG_MOV_OK
320336ac495dSmrg       fprintf (stderr, " - no, mem to mem\n");
320436ac495dSmrg #endif
320536ac495dSmrg       return false;
320636ac495dSmrg     }
320736ac495dSmrg 
320836ac495dSmrg #if DEBUG_MOV_OK
320936ac495dSmrg   fprintf (stderr, " - ok\n");
321036ac495dSmrg #endif
321136ac495dSmrg   return true;
321236ac495dSmrg }
321336ac495dSmrg 
321436ac495dSmrg /* Returns TRUE if two consecutive HImode mov instructions, generated
321536ac495dSmrg    for moving an immediate double data to a double data type variable
321636ac495dSmrg    location, can be combined into single SImode mov instruction.  */
321736ac495dSmrg bool
m32c_immd_dbl_mov(rtx * operands ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED)321836ac495dSmrg m32c_immd_dbl_mov (rtx * operands ATTRIBUTE_UNUSED,
321936ac495dSmrg 		   machine_mode mode ATTRIBUTE_UNUSED)
322036ac495dSmrg {
322136ac495dSmrg   /* ??? This relied on the now-defunct MEM_SCALAR and MEM_IN_STRUCT_P
322236ac495dSmrg      flags.  */
322336ac495dSmrg   return false;
322436ac495dSmrg }
322536ac495dSmrg 
322636ac495dSmrg /* Expanders */
322736ac495dSmrg 
322836ac495dSmrg /* Subregs are non-orthogonal for us, because our registers are all
322936ac495dSmrg    different sizes.  */
323036ac495dSmrg static rtx
m32c_subreg(machine_mode outer,rtx x,machine_mode inner,int byte)323136ac495dSmrg m32c_subreg (machine_mode outer,
323236ac495dSmrg 	     rtx x, machine_mode inner, int byte)
323336ac495dSmrg {
323436ac495dSmrg   int r, nr = -1;
323536ac495dSmrg 
323636ac495dSmrg   /* Converting MEMs to different types that are the same size, we
323736ac495dSmrg      just rewrite them.  */
323836ac495dSmrg   if (GET_CODE (x) == SUBREG
323936ac495dSmrg       && SUBREG_BYTE (x) == 0
324036ac495dSmrg       && GET_CODE (SUBREG_REG (x)) == MEM
324136ac495dSmrg       && (GET_MODE_SIZE (GET_MODE (x))
324236ac495dSmrg 	  == GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
324336ac495dSmrg     {
324436ac495dSmrg       rtx oldx = x;
324536ac495dSmrg       x = gen_rtx_MEM (GET_MODE (x), XEXP (SUBREG_REG (x), 0));
324636ac495dSmrg       MEM_COPY_ATTRIBUTES (x, SUBREG_REG (oldx));
324736ac495dSmrg     }
324836ac495dSmrg 
324936ac495dSmrg   /* Push/pop get done as smaller push/pops.  */
325036ac495dSmrg   if (GET_CODE (x) == MEM
325136ac495dSmrg       && (GET_CODE (XEXP (x, 0)) == PRE_DEC
325236ac495dSmrg 	  || GET_CODE (XEXP (x, 0)) == POST_INC))
325336ac495dSmrg     return gen_rtx_MEM (outer, XEXP (x, 0));
325436ac495dSmrg   if (GET_CODE (x) == SUBREG
325536ac495dSmrg       && GET_CODE (XEXP (x, 0)) == MEM
325636ac495dSmrg       && (GET_CODE (XEXP (XEXP (x, 0), 0)) == PRE_DEC
325736ac495dSmrg 	  || GET_CODE (XEXP (XEXP (x, 0), 0)) == POST_INC))
325836ac495dSmrg     return gen_rtx_MEM (outer, XEXP (XEXP (x, 0), 0));
325936ac495dSmrg 
326036ac495dSmrg   if (GET_CODE (x) != REG)
326136ac495dSmrg     {
326236ac495dSmrg       rtx r = simplify_gen_subreg (outer, x, inner, byte);
326336ac495dSmrg       if (GET_CODE (r) == SUBREG
326436ac495dSmrg 	  && GET_CODE (x) == MEM
326536ac495dSmrg 	  && MEM_VOLATILE_P (x))
326636ac495dSmrg 	{
326736ac495dSmrg 	  /* Volatile MEMs don't get simplified, but we need them to
326836ac495dSmrg 	     be.  We are little endian, so the subreg byte is the
326936ac495dSmrg 	     offset.  */
327036ac495dSmrg 	  r = adjust_address_nv (x, outer, byte);
327136ac495dSmrg 	}
327236ac495dSmrg       return r;
327336ac495dSmrg     }
327436ac495dSmrg 
327536ac495dSmrg   r = REGNO (x);
327636ac495dSmrg   if (r >= FIRST_PSEUDO_REGISTER || r == AP_REGNO)
327736ac495dSmrg     return simplify_gen_subreg (outer, x, inner, byte);
327836ac495dSmrg 
327936ac495dSmrg   if (IS_MEM_REGNO (r))
328036ac495dSmrg     return simplify_gen_subreg (outer, x, inner, byte);
328136ac495dSmrg 
328236ac495dSmrg   /* This is where the complexities of our register layout are
328336ac495dSmrg      described.  */
328436ac495dSmrg   if (byte == 0)
328536ac495dSmrg     nr = r;
328636ac495dSmrg   else if (outer == HImode)
328736ac495dSmrg     {
328836ac495dSmrg       if (r == R0_REGNO && byte == 2)
328936ac495dSmrg 	nr = R2_REGNO;
329036ac495dSmrg       else if (r == R0_REGNO && byte == 4)
329136ac495dSmrg 	nr = R1_REGNO;
329236ac495dSmrg       else if (r == R0_REGNO && byte == 6)
329336ac495dSmrg 	nr = R3_REGNO;
329436ac495dSmrg       else if (r == R1_REGNO && byte == 2)
329536ac495dSmrg 	nr = R3_REGNO;
329636ac495dSmrg       else if (r == A0_REGNO && byte == 2)
329736ac495dSmrg 	nr = A1_REGNO;
329836ac495dSmrg     }
329936ac495dSmrg   else if (outer == SImode)
330036ac495dSmrg     {
330136ac495dSmrg       if (r == R0_REGNO && byte == 0)
330236ac495dSmrg 	nr = R0_REGNO;
330336ac495dSmrg       else if (r == R0_REGNO && byte == 4)
330436ac495dSmrg 	nr = R1_REGNO;
330536ac495dSmrg     }
330636ac495dSmrg   if (nr == -1)
330736ac495dSmrg     {
330836ac495dSmrg       fprintf (stderr, "m32c_subreg %s %s %d\n",
330936ac495dSmrg 	       mode_name[outer], mode_name[inner], byte);
331036ac495dSmrg       debug_rtx (x);
331136ac495dSmrg       gcc_unreachable ();
331236ac495dSmrg     }
331336ac495dSmrg   return gen_rtx_REG (outer, nr);
331436ac495dSmrg }
331536ac495dSmrg 
331636ac495dSmrg /* Used to emit move instructions.  We split some moves,
331736ac495dSmrg    and avoid mem-mem moves.  */
331836ac495dSmrg int
m32c_prepare_move(rtx * operands,machine_mode mode)331936ac495dSmrg m32c_prepare_move (rtx * operands, machine_mode mode)
332036ac495dSmrg {
332136ac495dSmrg   if (far_addr_space_p (operands[0])
332236ac495dSmrg       && CONSTANT_P (operands[1]))
332336ac495dSmrg     {
332436ac495dSmrg       operands[1] = force_reg (GET_MODE (operands[0]), operands[1]);
332536ac495dSmrg     }
332636ac495dSmrg   if (TARGET_A16 && mode == PSImode)
332736ac495dSmrg     return m32c_split_move (operands, mode, 1);
332836ac495dSmrg   if ((GET_CODE (operands[0]) == MEM)
332936ac495dSmrg       && (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY))
333036ac495dSmrg     {
333136ac495dSmrg       rtx pmv = XEXP (operands[0], 0);
333236ac495dSmrg       rtx dest_reg = XEXP (pmv, 0);
333336ac495dSmrg       rtx dest_mod = XEXP (pmv, 1);
333436ac495dSmrg 
333536ac495dSmrg       emit_insn (gen_rtx_SET (dest_reg, dest_mod));
333636ac495dSmrg       operands[0] = gen_rtx_MEM (mode, dest_reg);
333736ac495dSmrg     }
333836ac495dSmrg   if (can_create_pseudo_p () && MEM_P (operands[0]) && MEM_P (operands[1]))
333936ac495dSmrg     operands[1] = copy_to_mode_reg (mode, operands[1]);
334036ac495dSmrg   return 0;
334136ac495dSmrg }
334236ac495dSmrg 
334336ac495dSmrg #define DEBUG_SPLIT 0
334436ac495dSmrg 
334536ac495dSmrg /* Returns TRUE if the given PSImode move should be split.  We split
334636ac495dSmrg    for all r8c/m16c moves, since it doesn't support them, and for
334736ac495dSmrg    POP.L as we can only *push* SImode.  */
334836ac495dSmrg int
m32c_split_psi_p(rtx * operands)334936ac495dSmrg m32c_split_psi_p (rtx * operands)
335036ac495dSmrg {
335136ac495dSmrg #if DEBUG_SPLIT
335236ac495dSmrg   fprintf (stderr, "\nm32c_split_psi_p\n");
335336ac495dSmrg   debug_rtx (operands[0]);
335436ac495dSmrg   debug_rtx (operands[1]);
335536ac495dSmrg #endif
335636ac495dSmrg   if (TARGET_A16)
335736ac495dSmrg     {
335836ac495dSmrg #if DEBUG_SPLIT
335936ac495dSmrg       fprintf (stderr, "yes, A16\n");
336036ac495dSmrg #endif
336136ac495dSmrg       return 1;
336236ac495dSmrg     }
336336ac495dSmrg   if (GET_CODE (operands[1]) == MEM
336436ac495dSmrg       && GET_CODE (XEXP (operands[1], 0)) == POST_INC)
336536ac495dSmrg     {
336636ac495dSmrg #if DEBUG_SPLIT
336736ac495dSmrg       fprintf (stderr, "yes, pop.l\n");
336836ac495dSmrg #endif
336936ac495dSmrg       return 1;
337036ac495dSmrg     }
337136ac495dSmrg #if DEBUG_SPLIT
337236ac495dSmrg   fprintf (stderr, "no, default\n");
337336ac495dSmrg #endif
337436ac495dSmrg   return 0;
337536ac495dSmrg }
337636ac495dSmrg 
337736ac495dSmrg /* Split the given move.  SPLIT_ALL is 0 if splitting is optional
337836ac495dSmrg    (define_expand), 1 if it is not optional (define_insn_and_split),
337936ac495dSmrg    and 3 for define_split (alternate api). */
338036ac495dSmrg int
m32c_split_move(rtx * operands,machine_mode mode,int split_all)338136ac495dSmrg m32c_split_move (rtx * operands, machine_mode mode, int split_all)
338236ac495dSmrg {
338336ac495dSmrg   rtx s[4], d[4];
338436ac495dSmrg   int parts, si, di, rev = 0;
338536ac495dSmrg   int rv = 0, opi = 2;
338636ac495dSmrg   machine_mode submode = HImode;
338736ac495dSmrg   rtx *ops, local_ops[10];
338836ac495dSmrg 
338936ac495dSmrg   /* define_split modifies the existing operands, but the other two
339036ac495dSmrg      emit new insns.  OPS is where we store the operand pairs, which
339136ac495dSmrg      we emit later.  */
339236ac495dSmrg   if (split_all == 3)
339336ac495dSmrg     ops = operands;
339436ac495dSmrg   else
339536ac495dSmrg     ops = local_ops;
339636ac495dSmrg 
339736ac495dSmrg   /* Else HImode.  */
339836ac495dSmrg   if (mode == DImode)
339936ac495dSmrg     submode = SImode;
340036ac495dSmrg 
340136ac495dSmrg   /* Before splitting mem-mem moves, force one operand into a
340236ac495dSmrg      register.  */
340336ac495dSmrg   if (can_create_pseudo_p () && MEM_P (operands[0]) && MEM_P (operands[1]))
340436ac495dSmrg     {
340536ac495dSmrg #if DEBUG0
340636ac495dSmrg       fprintf (stderr, "force_reg...\n");
340736ac495dSmrg       debug_rtx (operands[1]);
340836ac495dSmrg #endif
340936ac495dSmrg       operands[1] = force_reg (mode, operands[1]);
341036ac495dSmrg #if DEBUG0
341136ac495dSmrg       debug_rtx (operands[1]);
341236ac495dSmrg #endif
341336ac495dSmrg     }
341436ac495dSmrg 
341536ac495dSmrg   parts = 2;
341636ac495dSmrg 
341736ac495dSmrg #if DEBUG_SPLIT
341836ac495dSmrg   fprintf (stderr, "\nsplit_move %d all=%d\n", !can_create_pseudo_p (),
341936ac495dSmrg 	   split_all);
342036ac495dSmrg   debug_rtx (operands[0]);
342136ac495dSmrg   debug_rtx (operands[1]);
342236ac495dSmrg #endif
342336ac495dSmrg 
342436ac495dSmrg   /* Note that split_all is not used to select the api after this
342536ac495dSmrg      point, so it's safe to set it to 3 even with define_insn.  */
342636ac495dSmrg   /* None of the chips can move SI operands to sp-relative addresses,
342736ac495dSmrg      so we always split those.  */
342836ac495dSmrg   if (satisfies_constraint_Ss (operands[0]))
342936ac495dSmrg     split_all = 3;
343036ac495dSmrg 
343136ac495dSmrg   if (TARGET_A16
343236ac495dSmrg       && (far_addr_space_p (operands[0])
343336ac495dSmrg 	  || far_addr_space_p (operands[1])))
343436ac495dSmrg     split_all |= 1;
343536ac495dSmrg 
343636ac495dSmrg   /* We don't need to split these.  */
343736ac495dSmrg   if (TARGET_A24
343836ac495dSmrg       && split_all != 3
343936ac495dSmrg       && (mode == SImode || mode == PSImode)
344036ac495dSmrg       && !(GET_CODE (operands[1]) == MEM
344136ac495dSmrg 	   && GET_CODE (XEXP (operands[1], 0)) == POST_INC))
344236ac495dSmrg     return 0;
344336ac495dSmrg 
344436ac495dSmrg   /* First, enumerate the subregs we'll be dealing with.  */
344536ac495dSmrg   for (si = 0; si < parts; si++)
344636ac495dSmrg     {
344736ac495dSmrg       d[si] =
344836ac495dSmrg 	m32c_subreg (submode, operands[0], mode,
344936ac495dSmrg 		     si * GET_MODE_SIZE (submode));
345036ac495dSmrg       s[si] =
345136ac495dSmrg 	m32c_subreg (submode, operands[1], mode,
345236ac495dSmrg 		     si * GET_MODE_SIZE (submode));
345336ac495dSmrg     }
345436ac495dSmrg 
345536ac495dSmrg   /* Split pushes by emitting a sequence of smaller pushes.  */
345636ac495dSmrg   if (GET_CODE (d[0]) == MEM && GET_CODE (XEXP (d[0], 0)) == PRE_DEC)
345736ac495dSmrg     {
345836ac495dSmrg       for (si = parts - 1; si >= 0; si--)
345936ac495dSmrg 	{
346036ac495dSmrg 	  ops[opi++] = gen_rtx_MEM (submode,
346136ac495dSmrg 				    gen_rtx_PRE_DEC (Pmode,
346236ac495dSmrg 						     gen_rtx_REG (Pmode,
346336ac495dSmrg 								  SP_REGNO)));
346436ac495dSmrg 	  ops[opi++] = s[si];
346536ac495dSmrg 	}
346636ac495dSmrg 
346736ac495dSmrg       rv = 1;
346836ac495dSmrg     }
346936ac495dSmrg   /* Likewise for pops.  */
347036ac495dSmrg   else if (GET_CODE (s[0]) == MEM && GET_CODE (XEXP (s[0], 0)) == POST_INC)
347136ac495dSmrg     {
347236ac495dSmrg       for (di = 0; di < parts; di++)
347336ac495dSmrg 	{
347436ac495dSmrg 	  ops[opi++] = d[di];
347536ac495dSmrg 	  ops[opi++] = gen_rtx_MEM (submode,
347636ac495dSmrg 				    gen_rtx_POST_INC (Pmode,
347736ac495dSmrg 						      gen_rtx_REG (Pmode,
347836ac495dSmrg 								   SP_REGNO)));
347936ac495dSmrg 	}
348036ac495dSmrg       rv = 1;
348136ac495dSmrg     }
348236ac495dSmrg   else if (split_all)
348336ac495dSmrg     {
348436ac495dSmrg       /* if d[di] == s[si] for any di < si, we'll early clobber. */
348536ac495dSmrg       for (di = 0; di < parts - 1; di++)
348636ac495dSmrg 	for (si = di + 1; si < parts; si++)
348736ac495dSmrg 	  if (reg_mentioned_p (d[di], s[si]))
348836ac495dSmrg 	    rev = 1;
348936ac495dSmrg 
349036ac495dSmrg       if (rev)
349136ac495dSmrg 	for (si = 0; si < parts; si++)
349236ac495dSmrg 	  {
349336ac495dSmrg 	    ops[opi++] = d[si];
349436ac495dSmrg 	    ops[opi++] = s[si];
349536ac495dSmrg 	  }
349636ac495dSmrg       else
349736ac495dSmrg 	for (si = parts - 1; si >= 0; si--)
349836ac495dSmrg 	  {
349936ac495dSmrg 	    ops[opi++] = d[si];
350036ac495dSmrg 	    ops[opi++] = s[si];
350136ac495dSmrg 	  }
350236ac495dSmrg       rv = 1;
350336ac495dSmrg     }
350436ac495dSmrg   /* Now emit any moves we may have accumulated.  */
350536ac495dSmrg   if (rv && split_all != 3)
350636ac495dSmrg     {
350736ac495dSmrg       int i;
350836ac495dSmrg       for (i = 2; i < opi; i += 2)
350936ac495dSmrg 	emit_move_insn (ops[i], ops[i + 1]);
351036ac495dSmrg     }
351136ac495dSmrg   return rv;
351236ac495dSmrg }
351336ac495dSmrg 
351436ac495dSmrg /* The m32c has a number of opcodes that act like memcpy, strcmp, and
351536ac495dSmrg    the like.  For the R8C they expect one of the addresses to be in
351636ac495dSmrg    R1L:An so we need to arrange for that.  Otherwise, it's just a
351736ac495dSmrg    matter of picking out the operands we want and emitting the right
351836ac495dSmrg    pattern for them.  All these expanders, which correspond to
351936ac495dSmrg    patterns in blkmov.md, must return nonzero if they expand the insn,
352036ac495dSmrg    or zero if they should FAIL.  */
352136ac495dSmrg 
352236ac495dSmrg /* This is a memset() opcode.  All operands are implied, so we need to
352336ac495dSmrg    arrange for them to be in the right registers.  The opcode wants
352436ac495dSmrg    addresses, not [mem] syntax.  $0 is the destination (MEM:BLK), $1
352536ac495dSmrg    the count (HI), and $2 the value (QI).  */
352636ac495dSmrg int
m32c_expand_setmemhi(rtx * operands)352736ac495dSmrg m32c_expand_setmemhi(rtx *operands)
352836ac495dSmrg {
352936ac495dSmrg   rtx desta, count, val;
353036ac495dSmrg   rtx desto, counto;
353136ac495dSmrg 
353236ac495dSmrg   desta = XEXP (operands[0], 0);
353336ac495dSmrg   count = operands[1];
353436ac495dSmrg   val = operands[2];
353536ac495dSmrg 
353636ac495dSmrg   desto = gen_reg_rtx (Pmode);
353736ac495dSmrg   counto = gen_reg_rtx (HImode);
353836ac495dSmrg 
353936ac495dSmrg   if (GET_CODE (desta) != REG
354036ac495dSmrg       || REGNO (desta) < FIRST_PSEUDO_REGISTER)
354136ac495dSmrg     desta = copy_to_mode_reg (Pmode, desta);
354236ac495dSmrg 
354336ac495dSmrg   /* This looks like an arbitrary restriction, but this is by far the
354436ac495dSmrg      most common case.  For counts 8..14 this actually results in
354536ac495dSmrg      smaller code with no speed penalty because the half-sized
354636ac495dSmrg      constant can be loaded with a shorter opcode.  */
354736ac495dSmrg   if (GET_CODE (count) == CONST_INT
354836ac495dSmrg       && GET_CODE (val) == CONST_INT
354936ac495dSmrg       && ! (INTVAL (count) & 1)
355036ac495dSmrg       && (INTVAL (count) > 1)
355136ac495dSmrg       && (INTVAL (val) <= 7 && INTVAL (val) >= -8))
355236ac495dSmrg     {
355336ac495dSmrg       unsigned v = INTVAL (val) & 0xff;
355436ac495dSmrg       v = v | (v << 8);
355536ac495dSmrg       count = copy_to_mode_reg (HImode, GEN_INT (INTVAL (count) / 2));
355636ac495dSmrg       val = copy_to_mode_reg (HImode, GEN_INT (v));
355736ac495dSmrg       if (TARGET_A16)
355836ac495dSmrg 	emit_insn (gen_setmemhi_whi_op (desto, counto, val, desta, count));
355936ac495dSmrg       else
356036ac495dSmrg 	emit_insn (gen_setmemhi_wpsi_op (desto, counto, val, desta, count));
356136ac495dSmrg       return 1;
356236ac495dSmrg     }
356336ac495dSmrg 
356436ac495dSmrg   /* This is the generalized memset() case.  */
356536ac495dSmrg   if (GET_CODE (val) != REG
356636ac495dSmrg       || REGNO (val) < FIRST_PSEUDO_REGISTER)
356736ac495dSmrg     val = copy_to_mode_reg (QImode, val);
356836ac495dSmrg 
356936ac495dSmrg   if (GET_CODE (count) != REG
357036ac495dSmrg       || REGNO (count) < FIRST_PSEUDO_REGISTER)
357136ac495dSmrg     count = copy_to_mode_reg (HImode, count);
357236ac495dSmrg 
357336ac495dSmrg   if (TARGET_A16)
357436ac495dSmrg     emit_insn (gen_setmemhi_bhi_op (desto, counto, val, desta, count));
357536ac495dSmrg   else
357636ac495dSmrg     emit_insn (gen_setmemhi_bpsi_op (desto, counto, val, desta, count));
357736ac495dSmrg 
357836ac495dSmrg   return 1;
357936ac495dSmrg }
358036ac495dSmrg 
358136ac495dSmrg /* This is a memcpy() opcode.  All operands are implied, so we need to
358236ac495dSmrg    arrange for them to be in the right registers.  The opcode wants
358336ac495dSmrg    addresses, not [mem] syntax.  $0 is the destination (MEM:BLK), $1
358436ac495dSmrg    is the source (MEM:BLK), and $2 the count (HI).  */
358536ac495dSmrg int
m32c_expand_cpymemhi(rtx * operands)3586*8feb0f0bSmrg m32c_expand_cpymemhi(rtx *operands)
358736ac495dSmrg {
358836ac495dSmrg   rtx desta, srca, count;
358936ac495dSmrg   rtx desto, srco, counto;
359036ac495dSmrg 
359136ac495dSmrg   desta = XEXP (operands[0], 0);
359236ac495dSmrg   srca = XEXP (operands[1], 0);
359336ac495dSmrg   count = operands[2];
359436ac495dSmrg 
359536ac495dSmrg   desto = gen_reg_rtx (Pmode);
359636ac495dSmrg   srco = gen_reg_rtx (Pmode);
359736ac495dSmrg   counto = gen_reg_rtx (HImode);
359836ac495dSmrg 
359936ac495dSmrg   if (GET_CODE (desta) != REG
360036ac495dSmrg       || REGNO (desta) < FIRST_PSEUDO_REGISTER)
360136ac495dSmrg     desta = copy_to_mode_reg (Pmode, desta);
360236ac495dSmrg 
360336ac495dSmrg   if (GET_CODE (srca) != REG
360436ac495dSmrg       || REGNO (srca) < FIRST_PSEUDO_REGISTER)
360536ac495dSmrg     srca = copy_to_mode_reg (Pmode, srca);
360636ac495dSmrg 
360736ac495dSmrg   /* Similar to setmem, but we don't need to check the value.  */
360836ac495dSmrg   if (GET_CODE (count) == CONST_INT
360936ac495dSmrg       && ! (INTVAL (count) & 1)
361036ac495dSmrg       && (INTVAL (count) > 1))
361136ac495dSmrg     {
361236ac495dSmrg       count = copy_to_mode_reg (HImode, GEN_INT (INTVAL (count) / 2));
361336ac495dSmrg       if (TARGET_A16)
3614*8feb0f0bSmrg 	emit_insn (gen_cpymemhi_whi_op (desto, srco, counto, desta, srca, count));
361536ac495dSmrg       else
3616*8feb0f0bSmrg 	emit_insn (gen_cpymemhi_wpsi_op (desto, srco, counto, desta, srca, count));
361736ac495dSmrg       return 1;
361836ac495dSmrg     }
361936ac495dSmrg 
362036ac495dSmrg   /* This is the generalized memset() case.  */
362136ac495dSmrg   if (GET_CODE (count) != REG
362236ac495dSmrg       || REGNO (count) < FIRST_PSEUDO_REGISTER)
362336ac495dSmrg     count = copy_to_mode_reg (HImode, count);
362436ac495dSmrg 
362536ac495dSmrg   if (TARGET_A16)
3626*8feb0f0bSmrg     emit_insn (gen_cpymemhi_bhi_op (desto, srco, counto, desta, srca, count));
362736ac495dSmrg   else
3628*8feb0f0bSmrg     emit_insn (gen_cpymemhi_bpsi_op (desto, srco, counto, desta, srca, count));
362936ac495dSmrg 
363036ac495dSmrg   return 1;
363136ac495dSmrg }
363236ac495dSmrg 
363336ac495dSmrg /* This is a stpcpy() opcode.  $0 is the destination (MEM:BLK) after
363436ac495dSmrg    the copy, which should point to the NUL at the end of the string,
363536ac495dSmrg    $1 is the destination (MEM:BLK), and $2 is the source (MEM:BLK).
363636ac495dSmrg    Since our opcode leaves the destination pointing *after* the NUL,
363736ac495dSmrg    we must emit an adjustment.  */
363836ac495dSmrg int
m32c_expand_movstr(rtx * operands)363936ac495dSmrg m32c_expand_movstr(rtx *operands)
364036ac495dSmrg {
364136ac495dSmrg   rtx desta, srca;
364236ac495dSmrg   rtx desto, srco;
364336ac495dSmrg 
364436ac495dSmrg   desta = XEXP (operands[1], 0);
364536ac495dSmrg   srca = XEXP (operands[2], 0);
364636ac495dSmrg 
364736ac495dSmrg   desto = gen_reg_rtx (Pmode);
364836ac495dSmrg   srco = gen_reg_rtx (Pmode);
364936ac495dSmrg 
365036ac495dSmrg   if (GET_CODE (desta) != REG
365136ac495dSmrg       || REGNO (desta) < FIRST_PSEUDO_REGISTER)
365236ac495dSmrg     desta = copy_to_mode_reg (Pmode, desta);
365336ac495dSmrg 
365436ac495dSmrg   if (GET_CODE (srca) != REG
365536ac495dSmrg       || REGNO (srca) < FIRST_PSEUDO_REGISTER)
365636ac495dSmrg     srca = copy_to_mode_reg (Pmode, srca);
365736ac495dSmrg 
365836ac495dSmrg   emit_insn (gen_movstr_op (desto, srco, desta, srca));
365936ac495dSmrg   /* desto ends up being a1, which allows this type of add through MOVA.  */
366036ac495dSmrg   emit_insn (gen_addpsi3 (operands[0], desto, GEN_INT (-1)));
366136ac495dSmrg 
366236ac495dSmrg   return 1;
366336ac495dSmrg }
366436ac495dSmrg 
366536ac495dSmrg /* This is a strcmp() opcode.  $0 is the destination (HI) which holds
366636ac495dSmrg    <=>0 depending on the comparison, $1 is one string (MEM:BLK), and
366736ac495dSmrg    $2 is the other (MEM:BLK).  We must do the comparison, and then
366836ac495dSmrg    convert the flags to a signed integer result.  */
366936ac495dSmrg int
m32c_expand_cmpstr(rtx * operands)367036ac495dSmrg m32c_expand_cmpstr(rtx *operands)
367136ac495dSmrg {
367236ac495dSmrg   rtx src1a, src2a;
367336ac495dSmrg 
367436ac495dSmrg   src1a = XEXP (operands[1], 0);
367536ac495dSmrg   src2a = XEXP (operands[2], 0);
367636ac495dSmrg 
367736ac495dSmrg   if (GET_CODE (src1a) != REG
367836ac495dSmrg       || REGNO (src1a) < FIRST_PSEUDO_REGISTER)
367936ac495dSmrg     src1a = copy_to_mode_reg (Pmode, src1a);
368036ac495dSmrg 
368136ac495dSmrg   if (GET_CODE (src2a) != REG
368236ac495dSmrg       || REGNO (src2a) < FIRST_PSEUDO_REGISTER)
368336ac495dSmrg     src2a = copy_to_mode_reg (Pmode, src2a);
368436ac495dSmrg 
368536ac495dSmrg   emit_insn (gen_cmpstrhi_op (src1a, src2a, src1a, src2a));
368636ac495dSmrg   emit_insn (gen_cond_to_int (operands[0]));
368736ac495dSmrg 
368836ac495dSmrg   return 1;
368936ac495dSmrg }
369036ac495dSmrg 
369136ac495dSmrg 
369236ac495dSmrg typedef rtx (*shift_gen_func)(rtx, rtx, rtx);
369336ac495dSmrg 
369436ac495dSmrg static shift_gen_func
shift_gen_func_for(int mode,int code)369536ac495dSmrg shift_gen_func_for (int mode, int code)
369636ac495dSmrg {
369736ac495dSmrg #define GFF(m,c,f) if (mode == m && code == c) return f
369836ac495dSmrg   GFF(QImode,  ASHIFT,   gen_ashlqi3_i);
369936ac495dSmrg   GFF(QImode,  ASHIFTRT, gen_ashrqi3_i);
370036ac495dSmrg   GFF(QImode,  LSHIFTRT, gen_lshrqi3_i);
370136ac495dSmrg   GFF(HImode,  ASHIFT,   gen_ashlhi3_i);
370236ac495dSmrg   GFF(HImode,  ASHIFTRT, gen_ashrhi3_i);
370336ac495dSmrg   GFF(HImode,  LSHIFTRT, gen_lshrhi3_i);
370436ac495dSmrg   GFF(PSImode, ASHIFT,   gen_ashlpsi3_i);
370536ac495dSmrg   GFF(PSImode, ASHIFTRT, gen_ashrpsi3_i);
370636ac495dSmrg   GFF(PSImode, LSHIFTRT, gen_lshrpsi3_i);
370736ac495dSmrg   GFF(SImode,  ASHIFT,   TARGET_A16 ? gen_ashlsi3_16 : gen_ashlsi3_24);
370836ac495dSmrg   GFF(SImode,  ASHIFTRT, TARGET_A16 ? gen_ashrsi3_16 : gen_ashrsi3_24);
370936ac495dSmrg   GFF(SImode,  LSHIFTRT, TARGET_A16 ? gen_lshrsi3_16 : gen_lshrsi3_24);
371036ac495dSmrg #undef GFF
371136ac495dSmrg   gcc_unreachable ();
371236ac495dSmrg }
371336ac495dSmrg 
371436ac495dSmrg /* The m32c only has one shift, but it takes a signed count.  GCC
371536ac495dSmrg    doesn't want this, so we fake it by negating any shift count when
371636ac495dSmrg    we're pretending to shift the other way.  Also, the shift count is
371736ac495dSmrg    limited to -8..8.  It's slightly better to use two shifts for 9..15
371836ac495dSmrg    than to load the count into r1h, so we do that too.  */
371936ac495dSmrg int
m32c_prepare_shift(rtx * operands,int scale,int shift_code)372036ac495dSmrg m32c_prepare_shift (rtx * operands, int scale, int shift_code)
372136ac495dSmrg {
372236ac495dSmrg   machine_mode mode = GET_MODE (operands[0]);
372336ac495dSmrg   shift_gen_func func = shift_gen_func_for (mode, shift_code);
372436ac495dSmrg   rtx temp;
372536ac495dSmrg 
372636ac495dSmrg   if (GET_CODE (operands[2]) == CONST_INT)
372736ac495dSmrg     {
372836ac495dSmrg       int maxc = TARGET_A24 && (mode == PSImode || mode == SImode) ? 32 : 8;
372936ac495dSmrg       int count = INTVAL (operands[2]) * scale;
373036ac495dSmrg 
373136ac495dSmrg       while (count > maxc)
373236ac495dSmrg 	{
373336ac495dSmrg 	  temp = gen_reg_rtx (mode);
373436ac495dSmrg 	  emit_insn (func (temp, operands[1], GEN_INT (maxc)));
373536ac495dSmrg 	  operands[1] = temp;
373636ac495dSmrg 	  count -= maxc;
373736ac495dSmrg 	}
373836ac495dSmrg       while (count < -maxc)
373936ac495dSmrg 	{
374036ac495dSmrg 	  temp = gen_reg_rtx (mode);
374136ac495dSmrg 	  emit_insn (func (temp, operands[1], GEN_INT (-maxc)));
374236ac495dSmrg 	  operands[1] = temp;
374336ac495dSmrg 	  count += maxc;
374436ac495dSmrg 	}
374536ac495dSmrg       emit_insn (func (operands[0], operands[1], GEN_INT (count)));
374636ac495dSmrg       return 1;
374736ac495dSmrg     }
374836ac495dSmrg 
374936ac495dSmrg   temp = gen_reg_rtx (QImode);
375036ac495dSmrg   if (scale < 0)
375136ac495dSmrg     /* The pattern has a NEG that corresponds to this. */
375236ac495dSmrg     emit_move_insn (temp, gen_rtx_NEG (QImode, operands[2]));
375336ac495dSmrg   else if (TARGET_A16 && mode == SImode)
375436ac495dSmrg     /* We do this because the code below may modify this, we don't
375536ac495dSmrg        want to modify the origin of this value.  */
375636ac495dSmrg     emit_move_insn (temp, operands[2]);
375736ac495dSmrg   else
375836ac495dSmrg     /* We'll only use it for the shift, no point emitting a move.  */
375936ac495dSmrg     temp = operands[2];
376036ac495dSmrg 
376136ac495dSmrg   if (TARGET_A16 && GET_MODE_SIZE (mode) == 4)
376236ac495dSmrg     {
376336ac495dSmrg       /* The m16c has a limit of -16..16 for SI shifts, even when the
376436ac495dSmrg 	 shift count is in a register.  Since there are so many targets
376536ac495dSmrg 	 of these shifts, it's better to expand the RTL here than to
376636ac495dSmrg 	 call a helper function.
376736ac495dSmrg 
376836ac495dSmrg 	 The resulting code looks something like this:
376936ac495dSmrg 
377036ac495dSmrg 		cmp.b	r1h,-16
377136ac495dSmrg 		jge.b	1f
377236ac495dSmrg 		shl.l	-16,dest
377336ac495dSmrg 		add.b	r1h,16
377436ac495dSmrg 	1f:	cmp.b	r1h,16
377536ac495dSmrg 		jle.b	1f
377636ac495dSmrg 		shl.l	16,dest
377736ac495dSmrg 		sub.b	r1h,16
377836ac495dSmrg 	1f:	shl.l	r1h,dest
377936ac495dSmrg 
378036ac495dSmrg 	 We take advantage of the fact that "negative" shifts are
378136ac495dSmrg 	 undefined to skip one of the comparisons.  */
378236ac495dSmrg 
378336ac495dSmrg       rtx count;
378436ac495dSmrg       rtx tempvar;
378536ac495dSmrg       rtx_insn *insn;
378636ac495dSmrg 
378736ac495dSmrg       emit_move_insn (operands[0], operands[1]);
378836ac495dSmrg 
378936ac495dSmrg       count = temp;
379036ac495dSmrg       rtx_code_label *label = gen_label_rtx ();
379136ac495dSmrg       LABEL_NUSES (label) ++;
379236ac495dSmrg 
379336ac495dSmrg       tempvar = gen_reg_rtx (mode);
379436ac495dSmrg 
379536ac495dSmrg       if (shift_code == ASHIFT)
379636ac495dSmrg 	{
379736ac495dSmrg 	  /* This is a left shift.  We only need check positive counts.  */
379836ac495dSmrg 	  emit_jump_insn (gen_cbranchqi4 (gen_rtx_LE (VOIDmode, 0, 0),
379936ac495dSmrg 					  count, GEN_INT (16), label));
380036ac495dSmrg 	  emit_insn (func (tempvar, operands[0], GEN_INT (8)));
380136ac495dSmrg 	  emit_insn (func (operands[0], tempvar, GEN_INT (8)));
380236ac495dSmrg 	  insn = emit_insn (gen_addqi3 (count, count, GEN_INT (-16)));
380336ac495dSmrg 	  emit_label_after (label, insn);
380436ac495dSmrg 	}
380536ac495dSmrg       else
380636ac495dSmrg 	{
380736ac495dSmrg 	  /* This is a right shift.  We only need check negative counts.  */
380836ac495dSmrg 	  emit_jump_insn (gen_cbranchqi4 (gen_rtx_GE (VOIDmode, 0, 0),
380936ac495dSmrg 					  count, GEN_INT (-16), label));
381036ac495dSmrg 	  emit_insn (func (tempvar, operands[0], GEN_INT (-8)));
381136ac495dSmrg 	  emit_insn (func (operands[0], tempvar, GEN_INT (-8)));
381236ac495dSmrg 	  insn = emit_insn (gen_addqi3 (count, count, GEN_INT (16)));
381336ac495dSmrg 	  emit_label_after (label, insn);
381436ac495dSmrg 	}
381536ac495dSmrg       operands[1] = operands[0];
381636ac495dSmrg       emit_insn (func (operands[0], operands[0], count));
381736ac495dSmrg       return 1;
381836ac495dSmrg     }
381936ac495dSmrg 
382036ac495dSmrg   operands[2] = temp;
382136ac495dSmrg   return 0;
382236ac495dSmrg }
382336ac495dSmrg 
382436ac495dSmrg /* The m32c has a limited range of operations that work on PSImode
382536ac495dSmrg    values; we have to expand to SI, do the math, and truncate back to
382636ac495dSmrg    PSI.  Yes, this is expensive, but hopefully gcc will learn to avoid
382736ac495dSmrg    those cases.  */
382836ac495dSmrg void
m32c_expand_neg_mulpsi3(rtx * operands)382936ac495dSmrg m32c_expand_neg_mulpsi3 (rtx * operands)
383036ac495dSmrg {
383136ac495dSmrg   /* operands: a = b * i */
383236ac495dSmrg   rtx temp1; /* b as SI */
383336ac495dSmrg   rtx scale /* i as SI */;
383436ac495dSmrg   rtx temp2; /* a*b as SI */
383536ac495dSmrg 
383636ac495dSmrg   temp1 = gen_reg_rtx (SImode);
383736ac495dSmrg   temp2 = gen_reg_rtx (SImode);
383836ac495dSmrg   if (GET_CODE (operands[2]) != CONST_INT)
383936ac495dSmrg     {
384036ac495dSmrg       scale = gen_reg_rtx (SImode);
384136ac495dSmrg       emit_insn (gen_zero_extendpsisi2 (scale, operands[2]));
384236ac495dSmrg     }
384336ac495dSmrg   else
384436ac495dSmrg     scale = copy_to_mode_reg (SImode, operands[2]);
384536ac495dSmrg 
384636ac495dSmrg   emit_insn (gen_zero_extendpsisi2 (temp1, operands[1]));
384736ac495dSmrg   temp2 = expand_simple_binop (SImode, MULT, temp1, scale, temp2, 1, OPTAB_LIB);
384836ac495dSmrg   emit_insn (gen_truncsipsi2 (operands[0], temp2));
384936ac495dSmrg }
385036ac495dSmrg 
385136ac495dSmrg /* Pattern Output Functions */
385236ac495dSmrg 
385336ac495dSmrg int
m32c_expand_movcc(rtx * operands)385436ac495dSmrg m32c_expand_movcc (rtx *operands)
385536ac495dSmrg {
385636ac495dSmrg   rtx rel = operands[1];
385736ac495dSmrg 
385836ac495dSmrg   if (GET_CODE (rel) != EQ && GET_CODE (rel) != NE)
385936ac495dSmrg     return 1;
386036ac495dSmrg   if (GET_CODE (operands[2]) != CONST_INT
386136ac495dSmrg       || GET_CODE (operands[3]) != CONST_INT)
386236ac495dSmrg     return 1;
386336ac495dSmrg   if (GET_CODE (rel) == NE)
386436ac495dSmrg     {
386536ac495dSmrg       rtx tmp = operands[2];
386636ac495dSmrg       operands[2] = operands[3];
386736ac495dSmrg       operands[3] = tmp;
386836ac495dSmrg       rel = gen_rtx_EQ (GET_MODE (rel), XEXP (rel, 0), XEXP (rel, 1));
386936ac495dSmrg     }
387036ac495dSmrg 
387136ac495dSmrg   emit_move_insn (operands[0],
387236ac495dSmrg 		  gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
387336ac495dSmrg 					rel,
387436ac495dSmrg 					operands[2],
387536ac495dSmrg 					operands[3]));
387636ac495dSmrg   return 0;
387736ac495dSmrg }
387836ac495dSmrg 
387936ac495dSmrg /* Used for the "insv" pattern.  Return nonzero to fail, else done.  */
388036ac495dSmrg int
m32c_expand_insv(rtx * operands)388136ac495dSmrg m32c_expand_insv (rtx *operands)
388236ac495dSmrg {
388336ac495dSmrg   rtx op0, src0, p;
388436ac495dSmrg   int mask;
388536ac495dSmrg 
388636ac495dSmrg   if (INTVAL (operands[1]) != 1)
388736ac495dSmrg     return 1;
388836ac495dSmrg 
388936ac495dSmrg   /* Our insv opcode (bset, bclr) can only insert a one-bit constant.  */
389036ac495dSmrg   if (GET_CODE (operands[3]) != CONST_INT)
389136ac495dSmrg     return 1;
389236ac495dSmrg   if (INTVAL (operands[3]) != 0
389336ac495dSmrg       && INTVAL (operands[3]) != 1
389436ac495dSmrg       && INTVAL (operands[3]) != -1)
389536ac495dSmrg     return 1;
389636ac495dSmrg 
389736ac495dSmrg   mask = 1 << INTVAL (operands[2]);
389836ac495dSmrg 
389936ac495dSmrg   op0 = operands[0];
390036ac495dSmrg   if (GET_CODE (op0) == SUBREG
390136ac495dSmrg       && SUBREG_BYTE (op0) == 0)
390236ac495dSmrg     {
390336ac495dSmrg       rtx sub = SUBREG_REG (op0);
390436ac495dSmrg       if (GET_MODE (sub) == HImode || GET_MODE (sub) == QImode)
390536ac495dSmrg 	op0 = sub;
390636ac495dSmrg     }
390736ac495dSmrg 
390836ac495dSmrg   if (!can_create_pseudo_p ()
390936ac495dSmrg       || (GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0)))
391036ac495dSmrg     src0 = op0;
391136ac495dSmrg   else
391236ac495dSmrg     {
391336ac495dSmrg       src0 = gen_reg_rtx (GET_MODE (op0));
391436ac495dSmrg       emit_move_insn (src0, op0);
391536ac495dSmrg     }
391636ac495dSmrg 
391736ac495dSmrg   if (GET_MODE (op0) == HImode
391836ac495dSmrg       && INTVAL (operands[2]) >= 8
391936ac495dSmrg       && GET_CODE (op0) == MEM)
392036ac495dSmrg     {
392136ac495dSmrg       /* We are little endian.  */
392236ac495dSmrg       rtx new_mem = gen_rtx_MEM (QImode, plus_constant (Pmode,
392336ac495dSmrg 							XEXP (op0, 0), 1));
392436ac495dSmrg       MEM_COPY_ATTRIBUTES (new_mem, op0);
392536ac495dSmrg       mask >>= 8;
392636ac495dSmrg     }
392736ac495dSmrg 
392836ac495dSmrg   /* First, we generate a mask with the correct polarity.  If we are
392936ac495dSmrg      storing a zero, we want an AND mask, so invert it.  */
393036ac495dSmrg   if (INTVAL (operands[3]) == 0)
393136ac495dSmrg     {
393236ac495dSmrg       /* Storing a zero, use an AND mask */
393336ac495dSmrg       if (GET_MODE (op0) == HImode)
393436ac495dSmrg 	mask ^= 0xffff;
393536ac495dSmrg       else
393636ac495dSmrg 	mask ^= 0xff;
393736ac495dSmrg     }
393836ac495dSmrg   /* Now we need to properly sign-extend the mask in case we need to
393936ac495dSmrg      fall back to an AND or OR opcode.  */
394036ac495dSmrg   if (GET_MODE (op0) == HImode)
394136ac495dSmrg     {
394236ac495dSmrg       if (mask & 0x8000)
394336ac495dSmrg 	mask -= 0x10000;
394436ac495dSmrg     }
394536ac495dSmrg   else
394636ac495dSmrg     {
394736ac495dSmrg       if (mask & 0x80)
394836ac495dSmrg 	mask -= 0x100;
394936ac495dSmrg     }
395036ac495dSmrg 
395136ac495dSmrg   switch (  (INTVAL (operands[3]) ? 4 : 0)
395236ac495dSmrg 	  + ((GET_MODE (op0) == HImode) ? 2 : 0)
395336ac495dSmrg 	  + (TARGET_A24 ? 1 : 0))
395436ac495dSmrg     {
395536ac495dSmrg     case 0: p = gen_andqi3_16 (op0, src0, GEN_INT (mask)); break;
395636ac495dSmrg     case 1: p = gen_andqi3_24 (op0, src0, GEN_INT (mask)); break;
395736ac495dSmrg     case 2: p = gen_andhi3_16 (op0, src0, GEN_INT (mask)); break;
395836ac495dSmrg     case 3: p = gen_andhi3_24 (op0, src0, GEN_INT (mask)); break;
395936ac495dSmrg     case 4: p = gen_iorqi3_16 (op0, src0, GEN_INT (mask)); break;
396036ac495dSmrg     case 5: p = gen_iorqi3_24 (op0, src0, GEN_INT (mask)); break;
396136ac495dSmrg     case 6: p = gen_iorhi3_16 (op0, src0, GEN_INT (mask)); break;
396236ac495dSmrg     case 7: p = gen_iorhi3_24 (op0, src0, GEN_INT (mask)); break;
396336ac495dSmrg     default: p = NULL_RTX; break; /* Not reached, but silences a warning.  */
396436ac495dSmrg     }
396536ac495dSmrg 
396636ac495dSmrg   emit_insn (p);
396736ac495dSmrg   return 0;
396836ac495dSmrg }
396936ac495dSmrg 
397036ac495dSmrg const char *
m32c_scc_pattern(rtx * operands,RTX_CODE code)397136ac495dSmrg m32c_scc_pattern(rtx *operands, RTX_CODE code)
397236ac495dSmrg {
397336ac495dSmrg   static char buf[30];
397436ac495dSmrg   if (GET_CODE (operands[0]) == REG
397536ac495dSmrg       && REGNO (operands[0]) == R0_REGNO)
397636ac495dSmrg     {
397736ac495dSmrg       if (code == EQ)
397836ac495dSmrg 	return "stzx\t#1,#0,r0l";
397936ac495dSmrg       if (code == NE)
398036ac495dSmrg 	return "stzx\t#0,#1,r0l";
398136ac495dSmrg     }
398236ac495dSmrg   sprintf(buf, "bm%s\t0,%%h0\n\tand.b\t#1,%%0", GET_RTX_NAME (code));
398336ac495dSmrg   return buf;
398436ac495dSmrg }
398536ac495dSmrg 
398636ac495dSmrg /* Encode symbol attributes of a SYMBOL_REF into its
398736ac495dSmrg    SYMBOL_REF_FLAGS. */
398836ac495dSmrg static void
m32c_encode_section_info(tree decl,rtx rtl,int first)398936ac495dSmrg m32c_encode_section_info (tree decl, rtx rtl, int first)
399036ac495dSmrg {
399136ac495dSmrg   int extra_flags = 0;
399236ac495dSmrg 
399336ac495dSmrg   default_encode_section_info (decl, rtl, first);
399436ac495dSmrg   if (TREE_CODE (decl) == FUNCTION_DECL
399536ac495dSmrg       && m32c_special_page_vector_p (decl))
399636ac495dSmrg 
399736ac495dSmrg     extra_flags = SYMBOL_FLAG_FUNCVEC_FUNCTION;
399836ac495dSmrg 
399936ac495dSmrg   if (extra_flags)
400036ac495dSmrg     SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= extra_flags;
400136ac495dSmrg }
400236ac495dSmrg 
400336ac495dSmrg /* Returns TRUE if the current function is a leaf, and thus we can
400436ac495dSmrg    determine which registers an interrupt function really needs to
400536ac495dSmrg    save.  The logic below is mostly about finding the insn sequence
400636ac495dSmrg    that's the function, versus any sequence that might be open for the
400736ac495dSmrg    current insn.  */
400836ac495dSmrg static int
m32c_leaf_function_p(void)400936ac495dSmrg m32c_leaf_function_p (void)
401036ac495dSmrg {
401136ac495dSmrg   int rv;
401236ac495dSmrg 
401336ac495dSmrg   push_topmost_sequence ();
401436ac495dSmrg   rv = leaf_function_p ();
401536ac495dSmrg   pop_topmost_sequence ();
401636ac495dSmrg   return rv;
401736ac495dSmrg }
401836ac495dSmrg 
401936ac495dSmrg /* Returns TRUE if the current function needs to use the ENTER/EXIT
402036ac495dSmrg    opcodes.  If the function doesn't need the frame base or stack
402136ac495dSmrg    pointer, it can use the simpler RTS opcode.  */
402236ac495dSmrg static bool
m32c_function_needs_enter(void)402336ac495dSmrg m32c_function_needs_enter (void)
402436ac495dSmrg {
402536ac495dSmrg   rtx_insn *insn;
402636ac495dSmrg   rtx sp = gen_rtx_REG (Pmode, SP_REGNO);
402736ac495dSmrg   rtx fb = gen_rtx_REG (Pmode, FB_REGNO);
402836ac495dSmrg 
402936ac495dSmrg   for (insn = get_topmost_sequence ()->first; insn; insn = NEXT_INSN (insn))
403036ac495dSmrg     if (NONDEBUG_INSN_P (insn))
403136ac495dSmrg       {
403236ac495dSmrg 	if (reg_mentioned_p (sp, insn))
403336ac495dSmrg 	  return true;
403436ac495dSmrg 	if (reg_mentioned_p (fb, insn))
403536ac495dSmrg 	  return true;
403636ac495dSmrg       }
403736ac495dSmrg   return false;
403836ac495dSmrg }
403936ac495dSmrg 
404036ac495dSmrg /* Mark all the subexpressions of the PARALLEL rtx PAR as
404136ac495dSmrg    frame-related.  Return PAR.
404236ac495dSmrg 
404336ac495dSmrg    dwarf2out.c:dwarf2out_frame_debug_expr ignores sub-expressions of a
404436ac495dSmrg    PARALLEL rtx other than the first if they do not have the
404536ac495dSmrg    FRAME_RELATED flag set on them.  So this function is handy for
404636ac495dSmrg    marking up 'enter' instructions.  */
404736ac495dSmrg static rtx
m32c_all_frame_related(rtx par)404836ac495dSmrg m32c_all_frame_related (rtx par)
404936ac495dSmrg {
405036ac495dSmrg   int len = XVECLEN (par, 0);
405136ac495dSmrg   int i;
405236ac495dSmrg 
405336ac495dSmrg   for (i = 0; i < len; i++)
405436ac495dSmrg     F (XVECEXP (par, 0, i));
405536ac495dSmrg 
405636ac495dSmrg   return par;
405736ac495dSmrg }
405836ac495dSmrg 
405936ac495dSmrg /* Emits the prologue.  See the frame layout comment earlier in this
406036ac495dSmrg    file.  We can reserve up to 256 bytes with the ENTER opcode, beyond
406136ac495dSmrg    that we manually update sp.  */
406236ac495dSmrg void
m32c_emit_prologue(void)406336ac495dSmrg m32c_emit_prologue (void)
406436ac495dSmrg {
406536ac495dSmrg   int frame_size, extra_frame_size = 0, reg_save_size;
406636ac495dSmrg   int complex_prologue = 0;
406736ac495dSmrg 
406836ac495dSmrg   cfun->machine->is_leaf = m32c_leaf_function_p ();
406936ac495dSmrg   if (interrupt_p (cfun->decl))
407036ac495dSmrg     {
407136ac495dSmrg       cfun->machine->is_interrupt = 1;
407236ac495dSmrg       complex_prologue = 1;
407336ac495dSmrg     }
407436ac495dSmrg   else if (bank_switch_p (cfun->decl))
407536ac495dSmrg     warning (OPT_Wattributes,
407636ac495dSmrg 	     "%<bank_switch%> has no effect on non-interrupt functions");
407736ac495dSmrg 
407836ac495dSmrg   reg_save_size = m32c_pushm_popm (PP_justcount);
407936ac495dSmrg 
408036ac495dSmrg   if (interrupt_p (cfun->decl))
408136ac495dSmrg     {
408236ac495dSmrg       if (bank_switch_p (cfun->decl))
408336ac495dSmrg 	emit_insn (gen_fset_b ());
408436ac495dSmrg       else if (cfun->machine->intr_pushm)
408536ac495dSmrg 	emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm)));
408636ac495dSmrg     }
408736ac495dSmrg 
408836ac495dSmrg   frame_size =
408936ac495dSmrg     m32c_initial_elimination_offset (FB_REGNO, SP_REGNO) - reg_save_size;
409036ac495dSmrg   if (frame_size == 0
409136ac495dSmrg       && !m32c_function_needs_enter ())
409236ac495dSmrg     cfun->machine->use_rts = 1;
409336ac495dSmrg 
409436ac495dSmrg   if (flag_stack_usage_info)
409536ac495dSmrg     current_function_static_stack_size = frame_size;
409636ac495dSmrg 
409736ac495dSmrg   if (frame_size > 254)
409836ac495dSmrg     {
409936ac495dSmrg       extra_frame_size = frame_size - 254;
410036ac495dSmrg       frame_size = 254;
410136ac495dSmrg     }
410236ac495dSmrg   if (cfun->machine->use_rts == 0)
410336ac495dSmrg     F (emit_insn (m32c_all_frame_related
410436ac495dSmrg 		  (TARGET_A16
410536ac495dSmrg 		   ? gen_prologue_enter_16 (GEN_INT (frame_size + 2))
410636ac495dSmrg 		   : gen_prologue_enter_24 (GEN_INT (frame_size + 4)))));
410736ac495dSmrg 
410836ac495dSmrg   if (extra_frame_size)
410936ac495dSmrg     {
411036ac495dSmrg       complex_prologue = 1;
411136ac495dSmrg       if (TARGET_A16)
411236ac495dSmrg 	F (emit_insn (gen_addhi3 (gen_rtx_REG (HImode, SP_REGNO),
411336ac495dSmrg 				  gen_rtx_REG (HImode, SP_REGNO),
411436ac495dSmrg 				  GEN_INT (-extra_frame_size))));
411536ac495dSmrg       else
411636ac495dSmrg 	F (emit_insn (gen_addpsi3 (gen_rtx_REG (PSImode, SP_REGNO),
411736ac495dSmrg 				   gen_rtx_REG (PSImode, SP_REGNO),
411836ac495dSmrg 				   GEN_INT (-extra_frame_size))));
411936ac495dSmrg     }
412036ac495dSmrg 
412136ac495dSmrg   complex_prologue += m32c_pushm_popm (PP_pushm);
412236ac495dSmrg 
412336ac495dSmrg   /* This just emits a comment into the .s file for debugging.  */
412436ac495dSmrg   if (complex_prologue)
412536ac495dSmrg     emit_insn (gen_prologue_end ());
412636ac495dSmrg }
412736ac495dSmrg 
412836ac495dSmrg /* Likewise, for the epilogue.  The only exception is that, for
412936ac495dSmrg    interrupts, we must manually unwind the frame as the REIT opcode
413036ac495dSmrg    doesn't do that.  */
413136ac495dSmrg void
m32c_emit_epilogue(void)413236ac495dSmrg m32c_emit_epilogue (void)
413336ac495dSmrg {
413436ac495dSmrg   int popm_count = m32c_pushm_popm (PP_justcount);
413536ac495dSmrg 
413636ac495dSmrg   /* This just emits a comment into the .s file for debugging.  */
413736ac495dSmrg   if (popm_count > 0 || cfun->machine->is_interrupt)
413836ac495dSmrg     emit_insn (gen_epilogue_start ());
413936ac495dSmrg 
414036ac495dSmrg   if (popm_count > 0)
414136ac495dSmrg     m32c_pushm_popm (PP_popm);
414236ac495dSmrg 
414336ac495dSmrg   if (cfun->machine->is_interrupt)
414436ac495dSmrg     {
414536ac495dSmrg       machine_mode spmode = TARGET_A16 ? HImode : PSImode;
414636ac495dSmrg 
414736ac495dSmrg       /* REIT clears B flag and restores $fp for us, but we still
414836ac495dSmrg 	 have to fix up the stack.  USE_RTS just means we didn't
414936ac495dSmrg 	 emit ENTER.  */
415036ac495dSmrg       if (!cfun->machine->use_rts)
415136ac495dSmrg 	{
415236ac495dSmrg 	  emit_move_insn (gen_rtx_REG (spmode, A0_REGNO),
415336ac495dSmrg 			  gen_rtx_REG (spmode, FP_REGNO));
415436ac495dSmrg 	  emit_move_insn (gen_rtx_REG (spmode, SP_REGNO),
415536ac495dSmrg 			  gen_rtx_REG (spmode, A0_REGNO));
415636ac495dSmrg 	  /* We can't just add this to the POPM because it would be in
415736ac495dSmrg 	     the wrong order, and wouldn't fix the stack if we're bank
415836ac495dSmrg 	     switching.  */
415936ac495dSmrg 	  if (TARGET_A16)
416036ac495dSmrg 	    emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO)));
416136ac495dSmrg 	  else
416236ac495dSmrg 	    emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO)));
416336ac495dSmrg 	}
416436ac495dSmrg       if (!bank_switch_p (cfun->decl) && cfun->machine->intr_pushm)
416536ac495dSmrg 	emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm)));
416636ac495dSmrg 
416736ac495dSmrg       /* The FREIT (Fast REturn from InTerrupt) instruction should be
416836ac495dSmrg          generated only for M32C/M32CM targets (generate the REIT
416936ac495dSmrg          instruction otherwise).  */
417036ac495dSmrg       if (fast_interrupt_p (cfun->decl))
417136ac495dSmrg         {
417236ac495dSmrg           /* Check if fast_attribute is set for M32C or M32CM.  */
417336ac495dSmrg           if (TARGET_A24)
417436ac495dSmrg             {
417536ac495dSmrg               emit_jump_insn (gen_epilogue_freit ());
417636ac495dSmrg             }
417736ac495dSmrg           /* If fast_interrupt attribute is set for an R8C or M16C
417836ac495dSmrg              target ignore this attribute and generated REIT
417936ac495dSmrg              instruction.  */
418036ac495dSmrg           else
418136ac495dSmrg 	    {
418236ac495dSmrg 	      warning (OPT_Wattributes,
418336ac495dSmrg 		       "%<fast_interrupt%> attribute directive ignored");
418436ac495dSmrg 	      emit_jump_insn (gen_epilogue_reit_16 ());
418536ac495dSmrg 	    }
418636ac495dSmrg         }
418736ac495dSmrg       else if (TARGET_A16)
418836ac495dSmrg 	emit_jump_insn (gen_epilogue_reit_16 ());
418936ac495dSmrg       else
419036ac495dSmrg 	emit_jump_insn (gen_epilogue_reit_24 ());
419136ac495dSmrg     }
419236ac495dSmrg   else if (cfun->machine->use_rts)
419336ac495dSmrg     emit_jump_insn (gen_epilogue_rts ());
419436ac495dSmrg   else if (TARGET_A16)
419536ac495dSmrg     emit_jump_insn (gen_epilogue_exitd_16 ());
419636ac495dSmrg   else
419736ac495dSmrg     emit_jump_insn (gen_epilogue_exitd_24 ());
419836ac495dSmrg }
419936ac495dSmrg 
420036ac495dSmrg void
m32c_emit_eh_epilogue(rtx ret_addr)420136ac495dSmrg m32c_emit_eh_epilogue (rtx ret_addr)
420236ac495dSmrg {
420336ac495dSmrg   /* R0[R2] has the stack adjustment.  R1[R3] has the address to
420436ac495dSmrg      return to.  We have to fudge the stack, pop everything, pop SP
420536ac495dSmrg      (fudged), and return (fudged).  This is actually easier to do in
420636ac495dSmrg      assembler, so punt to libgcc.  */
420736ac495dSmrg   emit_jump_insn (gen_eh_epilogue (ret_addr, cfun->machine->eh_stack_adjust));
420836ac495dSmrg   /*  emit_clobber (gen_rtx_REG (HImode, R0L_REGNO)); */
420936ac495dSmrg }
421036ac495dSmrg 
421136ac495dSmrg /* Indicate which flags must be properly set for a given conditional.  */
421236ac495dSmrg static int
flags_needed_for_conditional(rtx cond)421336ac495dSmrg flags_needed_for_conditional (rtx cond)
421436ac495dSmrg {
421536ac495dSmrg   switch (GET_CODE (cond))
421636ac495dSmrg     {
421736ac495dSmrg     case LE:
421836ac495dSmrg     case GT:
421936ac495dSmrg       return FLAGS_OSZ;
422036ac495dSmrg     case LEU:
422136ac495dSmrg     case GTU:
422236ac495dSmrg       return FLAGS_ZC;
422336ac495dSmrg     case LT:
422436ac495dSmrg     case GE:
422536ac495dSmrg       return FLAGS_OS;
422636ac495dSmrg     case LTU:
422736ac495dSmrg     case GEU:
422836ac495dSmrg       return FLAGS_C;
422936ac495dSmrg     case EQ:
423036ac495dSmrg     case NE:
423136ac495dSmrg       return FLAGS_Z;
423236ac495dSmrg     default:
423336ac495dSmrg       return FLAGS_N;
423436ac495dSmrg     }
423536ac495dSmrg }
423636ac495dSmrg 
423736ac495dSmrg #define DEBUG_CMP 0
423836ac495dSmrg 
423936ac495dSmrg /* Returns true if a compare insn is redundant because it would only
424036ac495dSmrg    set flags that are already set correctly.  */
424136ac495dSmrg static bool
m32c_compare_redundant(rtx_insn * cmp,rtx * operands)424236ac495dSmrg m32c_compare_redundant (rtx_insn *cmp, rtx *operands)
424336ac495dSmrg {
424436ac495dSmrg   int flags_needed;
424536ac495dSmrg   int pflags;
424636ac495dSmrg   rtx_insn *prev;
424736ac495dSmrg   rtx pp, next;
424836ac495dSmrg   rtx op0, op1;
424936ac495dSmrg #if DEBUG_CMP
425036ac495dSmrg   int prev_icode, i;
425136ac495dSmrg #endif
425236ac495dSmrg 
425336ac495dSmrg   op0 = operands[0];
425436ac495dSmrg   op1 = operands[1];
425536ac495dSmrg 
425636ac495dSmrg #if DEBUG_CMP
425736ac495dSmrg   fprintf(stderr, "\n\033[32mm32c_compare_redundant\033[0m\n");
425836ac495dSmrg   debug_rtx(cmp);
425936ac495dSmrg   for (i=0; i<2; i++)
426036ac495dSmrg     {
426136ac495dSmrg       fprintf(stderr, "operands[%d] = ", i);
426236ac495dSmrg       debug_rtx(operands[i]);
426336ac495dSmrg     }
426436ac495dSmrg #endif
426536ac495dSmrg 
426636ac495dSmrg   next = next_nonnote_insn (cmp);
426736ac495dSmrg   if (!next || !INSN_P (next))
426836ac495dSmrg     {
426936ac495dSmrg #if DEBUG_CMP
427036ac495dSmrg       fprintf(stderr, "compare not followed by insn\n");
427136ac495dSmrg       debug_rtx(next);
427236ac495dSmrg #endif
427336ac495dSmrg       return false;
427436ac495dSmrg     }
427536ac495dSmrg   if (GET_CODE (PATTERN (next)) == SET
427636ac495dSmrg       && GET_CODE (XEXP ( PATTERN (next), 1)) == IF_THEN_ELSE)
427736ac495dSmrg     {
427836ac495dSmrg       next = XEXP (XEXP (PATTERN (next), 1), 0);
427936ac495dSmrg     }
428036ac495dSmrg   else if (GET_CODE (PATTERN (next)) == SET)
428136ac495dSmrg     {
428236ac495dSmrg       /* If this is a conditional, flags_needed will be something
428336ac495dSmrg 	 other than FLAGS_N, which we test below.  */
428436ac495dSmrg       next = XEXP (PATTERN (next), 1);
428536ac495dSmrg     }
428636ac495dSmrg   else
428736ac495dSmrg     {
428836ac495dSmrg #if DEBUG_CMP
428936ac495dSmrg       fprintf(stderr, "compare not followed by conditional\n");
429036ac495dSmrg       debug_rtx(next);
429136ac495dSmrg #endif
429236ac495dSmrg       return false;
429336ac495dSmrg     }
429436ac495dSmrg #if DEBUG_CMP
429536ac495dSmrg   fprintf(stderr, "conditional is: ");
429636ac495dSmrg   debug_rtx(next);
429736ac495dSmrg #endif
429836ac495dSmrg 
429936ac495dSmrg   flags_needed = flags_needed_for_conditional (next);
430036ac495dSmrg   if (flags_needed == FLAGS_N)
430136ac495dSmrg     {
430236ac495dSmrg #if DEBUG_CMP
430336ac495dSmrg       fprintf(stderr, "compare not followed by conditional\n");
430436ac495dSmrg       debug_rtx(next);
430536ac495dSmrg #endif
430636ac495dSmrg       return false;
430736ac495dSmrg     }
430836ac495dSmrg 
430936ac495dSmrg   /* Compare doesn't set overflow and carry the same way that
431036ac495dSmrg      arithmetic instructions do, so we can't replace those.  */
431136ac495dSmrg   if (flags_needed & FLAGS_OC)
431236ac495dSmrg     return false;
431336ac495dSmrg 
431436ac495dSmrg   prev = cmp;
431536ac495dSmrg   do {
431636ac495dSmrg     prev = prev_nonnote_insn (prev);
431736ac495dSmrg     if (!prev)
431836ac495dSmrg       {
431936ac495dSmrg #if DEBUG_CMP
432036ac495dSmrg 	fprintf(stderr, "No previous insn.\n");
432136ac495dSmrg #endif
432236ac495dSmrg 	return false;
432336ac495dSmrg       }
432436ac495dSmrg     if (!INSN_P (prev))
432536ac495dSmrg       {
432636ac495dSmrg #if DEBUG_CMP
432736ac495dSmrg 	fprintf(stderr, "Previous insn is a non-insn.\n");
432836ac495dSmrg #endif
432936ac495dSmrg 	return false;
433036ac495dSmrg       }
433136ac495dSmrg     pp = PATTERN (prev);
433236ac495dSmrg     if (GET_CODE (pp) != SET)
433336ac495dSmrg       {
433436ac495dSmrg #if DEBUG_CMP
433536ac495dSmrg 	fprintf(stderr, "Previous insn is not a SET.\n");
433636ac495dSmrg #endif
433736ac495dSmrg 	return false;
433836ac495dSmrg       }
433936ac495dSmrg     pflags = get_attr_flags (prev);
434036ac495dSmrg 
434136ac495dSmrg     /* Looking up attributes of previous insns corrupted the recog
434236ac495dSmrg        tables.  */
434336ac495dSmrg     INSN_UID (cmp) = -1;
434436ac495dSmrg     recog (PATTERN (cmp), cmp, 0);
434536ac495dSmrg 
434636ac495dSmrg     if (pflags == FLAGS_N
434736ac495dSmrg 	&& reg_mentioned_p (op0, pp))
434836ac495dSmrg       {
434936ac495dSmrg #if DEBUG_CMP
435036ac495dSmrg 	fprintf(stderr, "intermediate non-flags insn uses op:\n");
435136ac495dSmrg 	debug_rtx(prev);
435236ac495dSmrg #endif
435336ac495dSmrg 	return false;
435436ac495dSmrg       }
435536ac495dSmrg 
435636ac495dSmrg     /* Check for comparisons against memory - between volatiles and
435736ac495dSmrg        aliases, we just can't risk this one.  */
435836ac495dSmrg     if (GET_CODE (operands[0]) == MEM
435936ac495dSmrg 	|| GET_CODE (operands[0]) == MEM)
436036ac495dSmrg       {
436136ac495dSmrg #if DEBUG_CMP
436236ac495dSmrg 	fprintf(stderr, "comparisons with memory:\n");
436336ac495dSmrg 	debug_rtx(prev);
436436ac495dSmrg #endif
436536ac495dSmrg 	return false;
436636ac495dSmrg       }
436736ac495dSmrg 
436836ac495dSmrg     /* Check for PREV changing a register that's used to compute a
436936ac495dSmrg        value in CMP, even if it doesn't otherwise change flags.  */
437036ac495dSmrg     if (GET_CODE (operands[0]) == REG
437136ac495dSmrg 	&& rtx_referenced_p (SET_DEST (PATTERN (prev)), operands[0]))
437236ac495dSmrg       {
437336ac495dSmrg #if DEBUG_CMP
437436ac495dSmrg 	fprintf(stderr, "sub-value affected, op0:\n");
437536ac495dSmrg 	debug_rtx(prev);
437636ac495dSmrg #endif
437736ac495dSmrg 	return false;
437836ac495dSmrg       }
437936ac495dSmrg     if (GET_CODE (operands[1]) == REG
438036ac495dSmrg 	&& rtx_referenced_p (SET_DEST (PATTERN (prev)), operands[1]))
438136ac495dSmrg       {
438236ac495dSmrg #if DEBUG_CMP
438336ac495dSmrg 	fprintf(stderr, "sub-value affected, op1:\n");
438436ac495dSmrg 	debug_rtx(prev);
438536ac495dSmrg #endif
438636ac495dSmrg 	return false;
438736ac495dSmrg       }
438836ac495dSmrg 
438936ac495dSmrg   } while (pflags == FLAGS_N);
439036ac495dSmrg #if DEBUG_CMP
439136ac495dSmrg   fprintf(stderr, "previous flag-setting insn:\n");
439236ac495dSmrg   debug_rtx(prev);
439336ac495dSmrg   debug_rtx(pp);
439436ac495dSmrg #endif
439536ac495dSmrg 
439636ac495dSmrg   if (GET_CODE (pp) == SET
439736ac495dSmrg       && GET_CODE (XEXP (pp, 0)) == REG
439836ac495dSmrg       && REGNO (XEXP (pp, 0)) == FLG_REGNO
439936ac495dSmrg       && GET_CODE (XEXP (pp, 1)) == COMPARE)
440036ac495dSmrg     {
440136ac495dSmrg       /* Adjacent cbranches must have the same operands to be
440236ac495dSmrg 	 redundant.  */
440336ac495dSmrg       rtx pop0 = XEXP (XEXP (pp, 1), 0);
440436ac495dSmrg       rtx pop1 = XEXP (XEXP (pp, 1), 1);
440536ac495dSmrg #if DEBUG_CMP
440636ac495dSmrg       fprintf(stderr, "adjacent cbranches\n");
440736ac495dSmrg       debug_rtx(pop0);
440836ac495dSmrg       debug_rtx(pop1);
440936ac495dSmrg #endif
441036ac495dSmrg       if (rtx_equal_p (op0, pop0)
441136ac495dSmrg 	  && rtx_equal_p (op1, pop1))
441236ac495dSmrg 	return true;
441336ac495dSmrg #if DEBUG_CMP
441436ac495dSmrg       fprintf(stderr, "prev cmp not same\n");
441536ac495dSmrg #endif
441636ac495dSmrg       return false;
441736ac495dSmrg     }
441836ac495dSmrg 
441936ac495dSmrg   /* Else the previous insn must be a SET, with either the source or
442036ac495dSmrg      dest equal to operands[0], and operands[1] must be zero.  */
442136ac495dSmrg 
442236ac495dSmrg   if (!rtx_equal_p (op1, const0_rtx))
442336ac495dSmrg     {
442436ac495dSmrg #if DEBUG_CMP
442536ac495dSmrg       fprintf(stderr, "operands[1] not const0_rtx\n");
442636ac495dSmrg #endif
442736ac495dSmrg       return false;
442836ac495dSmrg     }
442936ac495dSmrg   if (GET_CODE (pp) != SET)
443036ac495dSmrg     {
443136ac495dSmrg #if DEBUG_CMP
443236ac495dSmrg       fprintf (stderr, "pp not set\n");
443336ac495dSmrg #endif
443436ac495dSmrg       return false;
443536ac495dSmrg     }
443636ac495dSmrg   if (!rtx_equal_p (op0, SET_SRC (pp))
443736ac495dSmrg       && !rtx_equal_p (op0, SET_DEST (pp)))
443836ac495dSmrg     {
443936ac495dSmrg #if DEBUG_CMP
444036ac495dSmrg       fprintf(stderr, "operands[0] not found in set\n");
444136ac495dSmrg #endif
444236ac495dSmrg       return false;
444336ac495dSmrg     }
444436ac495dSmrg 
444536ac495dSmrg #if DEBUG_CMP
444636ac495dSmrg   fprintf(stderr, "cmp flags %x prev flags %x\n", flags_needed, pflags);
444736ac495dSmrg #endif
444836ac495dSmrg   if ((pflags & flags_needed) == flags_needed)
444936ac495dSmrg     return true;
445036ac495dSmrg 
445136ac495dSmrg   return false;
445236ac495dSmrg }
445336ac495dSmrg 
445436ac495dSmrg /* Return the pattern for a compare.  This will be commented out if
445536ac495dSmrg    the compare is redundant, else a normal pattern is returned.  Thus,
445636ac495dSmrg    the assembler output says where the compare would have been.  */
445736ac495dSmrg char *
m32c_output_compare(rtx_insn * insn,rtx * operands)445836ac495dSmrg m32c_output_compare (rtx_insn *insn, rtx *operands)
445936ac495dSmrg {
446036ac495dSmrg   static char templ[] = ";cmp.b\t%1,%0";
446136ac495dSmrg   /*                             ^ 5  */
446236ac495dSmrg 
446336ac495dSmrg   templ[5] = " bwll"[GET_MODE_SIZE(GET_MODE(operands[0]))];
446436ac495dSmrg   if (m32c_compare_redundant (insn, operands))
446536ac495dSmrg     {
446636ac495dSmrg #if DEBUG_CMP
446736ac495dSmrg       fprintf(stderr, "cbranch: cmp not needed\n");
446836ac495dSmrg #endif
446936ac495dSmrg       return templ;
447036ac495dSmrg     }
447136ac495dSmrg 
447236ac495dSmrg #if DEBUG_CMP
447336ac495dSmrg   fprintf(stderr, "cbranch: cmp needed: `%s'\n", templ + 1);
447436ac495dSmrg #endif
447536ac495dSmrg   return templ + 1;
447636ac495dSmrg }
447736ac495dSmrg 
447836ac495dSmrg #undef TARGET_ENCODE_SECTION_INFO
447936ac495dSmrg #define TARGET_ENCODE_SECTION_INFO m32c_encode_section_info
448036ac495dSmrg 
448136ac495dSmrg /* If the frame pointer isn't used, we detect it manually.  But the
448236ac495dSmrg    stack pointer doesn't have as flexible addressing as the frame
448336ac495dSmrg    pointer, so we always assume we have it.  */
448436ac495dSmrg 
448536ac495dSmrg #undef TARGET_FRAME_POINTER_REQUIRED
448636ac495dSmrg #define TARGET_FRAME_POINTER_REQUIRED hook_bool_void_true
448736ac495dSmrg 
4488a2dc1f3fSmrg #undef TARGET_HARD_REGNO_NREGS
4489a2dc1f3fSmrg #define TARGET_HARD_REGNO_NREGS m32c_hard_regno_nregs
4490a2dc1f3fSmrg #undef TARGET_HARD_REGNO_MODE_OK
4491a2dc1f3fSmrg #define TARGET_HARD_REGNO_MODE_OK m32c_hard_regno_mode_ok
4492a2dc1f3fSmrg #undef TARGET_MODES_TIEABLE_P
4493a2dc1f3fSmrg #define TARGET_MODES_TIEABLE_P m32c_modes_tieable_p
4494a2dc1f3fSmrg 
4495a2dc1f3fSmrg #undef TARGET_CAN_CHANGE_MODE_CLASS
4496a2dc1f3fSmrg #define TARGET_CAN_CHANGE_MODE_CLASS m32c_can_change_mode_class
4497a2dc1f3fSmrg 
449836ac495dSmrg /* The Global `targetm' Variable. */
449936ac495dSmrg 
450036ac495dSmrg struct gcc_target targetm = TARGET_INITIALIZER;
450136ac495dSmrg 
450236ac495dSmrg #include "gt-m32c.h"
4503